221 lines
6.6 KiB
Markdown
221 lines
6.6 KiB
Markdown
|
---
|
||
|
title: File Handling
|
||
|
---
|
||
|
## File Handling
|
||
|
|
||
|
### Introduction
|
||
|
If you've written the C `helloworld` program before, you've already done file IO in C! Congratulations! :tada:
|
||
|
|
||
|
```c
|
||
|
/* A simple hello world in C. */
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
// Import IO functions.
|
||
|
#include <stdio.h>
|
||
|
|
||
|
int main() {
|
||
|
// This printf is where all the file IO magic happens!
|
||
|
// How exciting!
|
||
|
printf("Hello, world!\n");
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
File Handling is most important part of a programmer . In C language we use a structure pointer of a file type to declare a file
|
||
|
|
||
|
```c
|
||
|
FILE *fp;
|
||
|
```
|
||
|
C provides a number of build-in function to perform basic file operation
|
||
|
|
||
|
**fopen()** **-** **create a new file or open a existing file**
|
||
|
|
||
|
**fclose()** **-** **close a file**
|
||
|
|
||
|
**getc()** **-** **reads a character from a file**
|
||
|
|
||
|
**putc()** **-** **writes a character to a file**
|
||
|
|
||
|
**fscanf()** **-** **reads a set of data from a file**
|
||
|
|
||
|
**fprintf()** **-** **writes a set of data to a file**
|
||
|
|
||
|
**getw()** **-** **reads a integer from a file**
|
||
|
|
||
|
**putw()** **-** **writes a integer to a file**
|
||
|
|
||
|
**fseek()** **-** **set the position to desire point**
|
||
|
|
||
|
**ftell()** **-** **gives current position in the file**
|
||
|
|
||
|
**rewind()** **-** **set the position to the begining point**
|
||
|
|
||
|
### Opening a file
|
||
|
|
||
|
The **fopen()** function is used to create a file or open a existing file
|
||
|
|
||
|
```c
|
||
|
fp = fopen(const char filename,const char mode);
|
||
|
```
|
||
|
|
||
|
In C there are many mode for opening a file
|
||
|
**r** **-** **open a file in reading mode**
|
||
|
|
||
|
**w** **-** **opens or create a text file in writing mode**
|
||
|
|
||
|
**a** **-** **opens a file in append mode**
|
||
|
|
||
|
**r+** **-** **opens a file in both reading and writing mode**
|
||
|
|
||
|
**a+** **-** **opens a file in both reading and writing mode**
|
||
|
|
||
|
**w+** **-** **opens a file in both reading and writing mode**
|
||
|
|
||
|
Here's an example of reading and writing data to a file
|
||
|
|
||
|
```c
|
||
|
#include<stdio.h>
|
||
|
#include<conio.h>
|
||
|
main()
|
||
|
{
|
||
|
FILE *fp;
|
||
|
char ch;
|
||
|
fp = fopen("hello.txt", "w");
|
||
|
printf("Enter data");
|
||
|
while( (ch = getchar()) != EOF) {
|
||
|
putc(ch,fp);
|
||
|
}
|
||
|
fclose(fp);
|
||
|
fp = fopen("hello.txt", "r");
|
||
|
|
||
|
while( (ch = getc(fp)! = EOF)
|
||
|
printf("%c",ch);
|
||
|
|
||
|
fclose(fp);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Now you might be thinking, "this justs prints text to my screen. How is this file IO?"
|
||
|
The answer isn't obvious at first, and needs some understanding about the UNIX system.
|
||
|
Under a UNIX system, everything is treated as a file, meaning you can read and write from it.
|
||
|
This means that your printer can be abstracted as a file since all you do with a printer is write with it.
|
||
|
It is also useful to think of these files as streams, since as you'll see later, you can redirect them with the shell.
|
||
|
|
||
|
So how does this relate to `helloworld` and file IO?
|
||
|
|
||
|
When you call `printf`, you are really just writing to a special file called `stdout`, short for __standard output__.
|
||
|
`stdout` represents, well, the standard output as decided by your shell, which is usually the terminal.
|
||
|
This explains why it printed to your screen.
|
||
|
|
||
|
There are two other streams (i.e. files) that are available to you with effort, `stdin` and `stderr`.
|
||
|
`stdin` represents the __standard input__, which your shell usually attaches to the keyboard.
|
||
|
`stderr` represents the __standard error__ output, which your shell usually attaches to the terminal.
|
||
|
|
||
|
### Rudimentary File IO, or How I Learnt to Lay Pipes
|
||
|
Enough theory, let's get down to business by writing some code!
|
||
|
The easist way to write to a file is to redirect the output stream using the output redirect tool, `>`.
|
||
|
If you want to append, you can use `>>`. _N.b. these redirection operators are in_ `bash` _and similar shells._
|
||
|
|
||
|
```bash
|
||
|
# This will output to the screen...
|
||
|
./helloworld
|
||
|
# ...but this will write to a file!
|
||
|
./helloworld > hello.txt
|
||
|
```
|
||
|
|
||
|
The contents of `hello.txt` will, not surprisingly, be
|
||
|
|
||
|
```
|
||
|
Hello, world!
|
||
|
```
|
||
|
|
||
|
Say we have another program called `greet`, similar to `helloworld`, that greets you given your name.
|
||
|
|
||
|
```c
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
int main() {
|
||
|
// Initialize an array to hold the name.
|
||
|
char name[20];
|
||
|
// Read a string and save it to name.
|
||
|
scanf("%s", name);
|
||
|
// Print the greeting.
|
||
|
printf("Hello, %s!", name);
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Instead of reading from the keyboard, we can redirect `stdin` to read from a file using the `<` tool.
|
||
|
|
||
|
```bash
|
||
|
# Write a file containing a name.
|
||
|
echo Kamala > name.txt
|
||
|
# This will read the name from the file and print out the greeting to the screen.
|
||
|
./greet < name.txt
|
||
|
# ==> Hello, Kamala!
|
||
|
# If you wanted to also write the greeting to a file, you could do so using ">".
|
||
|
```
|
||
|
|
||
|
### The Real Deal
|
||
|
The above methods only worked for the most basic of cases. If you wanted to do bigger and better things, you will probably want to work with files from within C instead of through the shell.
|
||
|
To accomplish this, you will use a function called `fopen`. This function takes two string parameters, the first being the file name and the second being the mode.
|
||
|
Mode is basically permissions, so `r` for read, `w` for write, `a` for append. You can also combine them, so `rw` would mean you could read and write to the file. There are more modes, but these are the most used.
|
||
|
|
||
|
After you have a `FILE` pointer, you can use basically the same IO commands you would've used, except that you have to prefix them with `f` and the first argument will be the file pointer.
|
||
|
For example, `printf`'s file version is `fprintf`.
|
||
|
|
||
|
Here's a program called `greetings` that reads a from a file containing a list of names and writes to another file the greetings.
|
||
|
|
||
|
```c
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
int main() {
|
||
|
// Create file pointers.
|
||
|
FILE *names = fopen("names.txt", "r");
|
||
|
FILE *greet = fopen("greet.txt", "w");
|
||
|
|
||
|
// Check that everything is OK.
|
||
|
if (!names || !greet) {
|
||
|
fprintf(stderr, "File opening failed!\n");
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
|
||
|
// Greetings time!
|
||
|
char name[20];
|
||
|
// Basically keep on reading untill there's nothing left.
|
||
|
while (fscanf(names, "%s\n", name) > 0) {
|
||
|
fprintf(greet, "Hello, %s!\n", name);
|
||
|
}
|
||
|
|
||
|
// When reached the end, print a message to the terminal to inform the user.
|
||
|
if (feof(names)) {
|
||
|
printf("Greetings are done!\n");
|
||
|
}
|
||
|
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Suppose `names.txt` contains the following:
|
||
|
|
||
|
```
|
||
|
Kamala
|
||
|
Logan
|
||
|
Carol
|
||
|
```
|
||
|
|
||
|
Then after running `greetings` the file `greet.txt` will contain:
|
||
|
|
||
|
```
|
||
|
Hello, Kamala!
|
||
|
Hello, Logan!
|
||
|
Hello, Carol!
|
||
|
```
|
||
|
|
||
|
Super awesome, right! :smile:
|
||
|
|
||
|
### More Information:
|
||
|
- <a href='https://en.wikibooks.org/wiki/C_Programming/File_IO' target='_blank' rel='nofollow'>Wikibooks page on file IO</a>
|