-
Notifications
You must be signed in to change notification settings - Fork 1
FileIO
Maxwell Talley edited this page Sep 13, 2017
·
6 revisions
-
FILE fopen(const char *path, const char *mode);
- Used to open a file
- path is the path to the file
- mode is the file access mode (read, write, append, or read/write)
- read == "r"
- write == "w"
- append == "a"
- binary == "b" (necessary when using binary files in windows; otherwise a no-op)
- Returns NULL on failure
-
int fclose(FILE *fp);
- Closes a file previously opened by fopen()
-
int fprintf(FILE *stream, const char *format, ...);
- Just like printf(), but first parameter is a FILE *
-
int fscanf(FILE *stream, const char *format, ...);
- Analogous to printf, but for reading
- To read an int (from standard input:
fscanf(stdin, "%d", &i);
)
-
char *fgets(char *s, int size, FILE *stream);
- Reads one line at a time, up to size bytes, where size if the ammount of storage available in s; analogous function called
gets()
- Reads one line at a time, up to size bytes, where size if the ammount of storage available in s; analogous function called
-
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
- Writes binary data to file from ptr, each element is size bytes, there are nmemb elements, write to stream
- Returns the total number of elements successfully returned as a size_t object. If this number is different from nmemb, it will throw an error.
-
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
- Analogous to fwrite, but reads
-
int fseek(FILE *stream, long int offset, int whence)
- stream: file object
- offset: number of bytes to offset from whence
- whence: position from whence offset is added. Specified by one of the following:
-
SEEK_SET
-- beginning of file -
SEEK_CUR
-- current position of the file pointer -
SEEK_END
-- end of file
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum action {
read_binary,
read_text,
write_binary,
write_text
} action_t;
int main(int argc, char *argv[])
{
action_t action;
FILE *f;
/* This is called an "anonymous structure". Notice how it doesn't *
* have a name. The instance, s, has a name (s), but the type *
* does not! */
struct {
char i;
char j;
} s = { 1, 2 };
if (argc != 3) {
fprintf(stderr, "Wrong number of paramenters\n");
return -1;
}
if (argv[1][0] != '-') {
fprintf(stderr, "Bad argument format\n");
return -1;
}
/* I did it this way (below) to illustrate indexing individual *
* characters in the argument vector. Far more robust would *
* be to use strcmp(), for example: *
* if (!strcmp(argv[1], "-wt")) { *
* action = write_text; *
* } else if ... *
* Using the above technique obviates the need for the if *
* statement above. We can instead have a final else to *
* handle errors. */
if (argv[1][1] == 'w') {
if (argv[1][2] == 't') {
action = write_text;
} else {
action = write_binary;
}
f = fopen(argv[2], "w");
} else {
if (argv[1][2] == 't') {
action = read_text;
} else {
action = read_binary;
}
f = fopen(argv[2], "r");
}
if (!f) {
fprintf(stderr, "Couldn't open file\n");
return -1;
}
/* We almost finished in class, but three of these cases were not *
* filled in. Go ahead and try this out. We'll look at the *
* other three and take questions on Friday. */
switch (action) {
case read_text:
fscanf(f, "%hhd %hhd", &s.i, &s.j);
printf("%d %d\n", s.i, s.j);
break;
case read_binary:
fread(&s, sizeof (s), 1, f);
printf("%d %d\n", s.i, s.j);
break;
case write_text:
fprintf(f, "%d %d\n", s.i, s.j);
break;
case write_binary:
/* We did this one in class, but not the three above. */
fwrite(&s, sizeof (s), 1, f);
break;
}
/* What happens if you write a file as binary, then try to read it as *
* text? If you write as text and try to read as binary? In either *
* case, nothing good. There is nothing to protect you from this. */
return 0;
}