CMPT 214 Programming Principles and Practice Lecture 17 - File I/O PDF

Document Details

SumptuousBaroque

Uploaded by SumptuousBaroque

University of Saskatchewan

2024

Noah Orensa, Jon Lovering, Lauresa Stilling, Alexander Dumais, Dwight Makaroff

Tags

programming c programming file i/o computer science

Summary

This document is a lecture for CMPT 214, Programming Principles and Practice, Fall 2024, from the University of Saskatchewan, covering File I/O, system calls, and the C library overview. It details file stream I/O, using FILE pointers, and low-level I/O, using file descriptors. The lecture explores concepts like fopen, fclose, read, write, and lseek.

Full Transcript

CMPT 214 Programming Principles and Practice Lecture 17: File I/O, system calls, and C library overview Reading: Kochan: Chapter 15 1 Original Slides Noah Orensa...

CMPT 214 Programming Principles and Practice Lecture 17: File I/O, system calls, and C library overview Reading: Kochan: Chapter 15 1 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File I/O Two types of file I/O (input/output) methods we will consider: stream I/O (using FILE * ), and low-level I/O (using file descriptors) 2 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O FILE is typedef'ed object type, capable of holding all information needed to control a C I/O stream You have already seen an example of a FILE * : stdin (given to fgets ) Before you can begin to do any I/O operations on a file, the file must first be opened. stdin , stdout , and stderr are already opened when the process is created To open a file, you must specify the name of the file. The system then checks to make certain that this file actually exists and, in certain instances, creates the file for you if it does not. 3 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O When a file is opened, the type of I/O operations intended are required. read mode. write mode append mode In the latter two cases, an error is not returned; file created In read mode, if the file does not exist, an error occurs. ALWAYS CHECK THE RETURN VALUES FROM system calls and library functions 4 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O: fopen() A program can have many different files open at the same time; thus a particular file must have a means of identification: a file pointer. The C-lib function fopen() opens a file and returns unique file pointer for future operations FILE *fopen(const char *pathname, const char *mode); The function takes two arguments: The first is a character string specifying the name of the file to be opened; the second is also a character string that indicates the mode in which the file is to be opened. 5 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O: fopen() On error, returns NULL FILE *inputFile; inputFile = fopen("data", "r"); if (inputFile == NULL) fprintf(stderr, "data could not be opened.\n"); Always check the result of an fopen() call to make certain it succeeds. (Is this 3x or more??) 6 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O: fopen() common C style; combine the two previous statements: opening the file and checking for errors if ((inputFile = fopen ("data", "r")) == NULL) printf("data could not be opened.\n"); 7 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O: fopen() modes Mode Description Open text file for reading. The stream is positioned at the beginning of the r file. Open for reading and writing. The stream is positioned at the beginning of r+ the file. Truncate file to zero length or create text file for writing. The stream is w positioned at the beginning of the file. 8 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O: fopen() modes Mode Description Open for reading and writing. The file is created if it does not exist, w+ otherwise it is truncated. The stream is positioned at the beginning of the file. Open for appending (writing at end of file). The file is created if it does not a exist. The stream is positioned at the end of the file. Open for reading and appending (writing at end of file). The file is created if a+ it does not exist. Output is always appended to the end of the file. 9 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O: fprintf() and fscanf() The functions fprintf() and fscanf() are provided to perform the analogous operations of the printf() and scanf() functions on a file. These functions take an additional argument, which is the FILE * that identifies the file to which the data is to be written or from which the data is to be read. fprintf(outFile, "Programming in C is fun.\n"); fscanf(inFile, "%f", &fv); 10 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O: fgets() and fputs() For reading and writing entire lines of data from and to a file, the fputs() and fgets() functions can be used. fgets(buffer, n, filePtr); fputs(buffer, filePtr); 11 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O: stdin , stdout , and stderr FILE pointers stdin , stdout , and stderr , defined in The reason stderr exists is so that error messages can be logged to a device or file other than where the normal output is written. particularly desirable when program’s normal output is redirected 12 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Redirecting stderr in BASH command > out 2>error This has the effect of redirecting stdout to a file named out , and stderr to a file named error command > out 2>&1 This has the effect of redirecting stdout to a file named out , and redirecting stderr to stdout ; i.e., both stdout and stderr here will be combined into one stream that is redirected to the file out 13 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O: fclose() The fclose() function does the opposite of fopen() fclose (inputFile); necessary housekeeping chores (such as writing all the data that it might be keeping in a buffer in memory to the file); dissociates the particular file identifier from the file 14 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O: fclose() When a program terminates normally, open files are automatically closed. Better programming practice to close a file as soon as you are done with it. Beneficial if your program deals with a large number of files, as there are limits on the number of files that can be kept simultaneously open 15 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall File stream I/O: feof() The single argument to the function is a FILE pointer. The function returns an integer value that is nonzero if an attempt has been made to read past the end of a file, and is zero otherwise. if (feof(inFile)) { printf("Ran out of data.\n"); return 1; } Remember, feof() means attempt has been made to read past the end of the file; not the same reading the last data item from a file. Need to read one past the last data item for feof() to return nonzero. 16 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O using file descriptors and system calls file descriptor: a process-unique identifier (or handle) for a file or other input/output resource, such as a pipe or network socket File descriptors are managed by the operating system for each process OS buffers input/output and transmits the data to/from a file network two ends of a pipe... 17 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O using file descriptors and system calls Stream I/O using FILE * is implemented in the C library using file descriptors and system calls Using file descriptors and system calls, allows direct interface to operating system functions (syscalls) greater flexibility and performance 18 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: open() Much like stream I/O, a file must be opened before use. int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); The pathname and flags are similar to fopen() 's two arguments The first call is used when no file is being created. When a file is created, the mode (access permissions) must be given for the new file Constants are define for flags and mode , and can be combined using bitwise OR to indicate more than one flag/mode 19 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: open() For the flags , one of O_RDONLY , O_WRONLY , O_RDWR must be given. Other flags are optional. The full list of possible flags can be found in man open.2 int flags Description O_RDONLY Read only mode O_WRONLY Write only mode O_RDWR Read/write mode 20 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: open() int Description flags The file is opened in append mode. Before each write, the file offset is O_APPEND positioned at the end of the file. If pathname does not exist, create it as a regular file. mode must be O_CREAT given If the file already exists and is a regular file and the access mode O_TRUNC allows writing (i.e., is O_RDWR or O_WRONLY ) it will be truncated to length 0. 21 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: open() The mode give the file access permissions. This can be an octal constant (starting with 0) Additionally, there are a number of mode constants that are defined and can be combined using bitwise OR 22 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: open() int mode Description S_IRWXU 0700 user (file owner) has read, write, and execute permission S_IRUSR 0400 user has read permission S_IWUSR 0200 user has write permission S_IXUSR 0100 user has execute permission S_IRWXG 0070 group has read, write, and execute permission S_IRGRP 0040 group has read permission S_IWGRP 0020 group has write permission S_IXGRP 0010 group has execute permission S_IRWXO 0007 others have read, write, and execute permission S_IROTH 0004 others have read permission S_IWOTH 0002 others have write permission S_IXOTH 0001 others have execute permission 23 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: close() Similar, to fclose() , close() closes a file descriptor, freeing all resources, flushing buffers, and committing changes. int close(int fd); 24 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: example int fd; if ((fd = open("path/to/my_file", O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) { } if (close(fd)) { } 25 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Converting FILE * to FD You can get a file descriptor from a FILE * using fileno() You can also get a FILE * from a file descriptor using fdopen() 26 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall errno : number of last error errno is a variable in the C library that gives an error code for the last system call/library function. Functions like open() and close() can return -1 if an error occurs. They also set errno to some error code that you can inspect to know exactly what went wrong. You can check errno yourself, or use a function like perror() or strerror() to get a description of the error 27 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: updated example with perror() int fd; if ((fd = open("path/to/my_file", O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) { perror("open"); } if (close(fd)) { perror("close"); } perror() produces a message on stderr describing error code in errno Optionally, the message can be prefixed with a user token (like "open" , "close" , etc.), or NULL can be given Check man errno , man perror , man strerror for more details 28 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: read() / write() ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); read() / write() allow you to read and write from/to a file descriptor. Both take a void * to some memory block and a count describing the size of the memory block in bytes use sizeof to calculate the size in bytes of your memory block return value: number of bytes actually read/written (may be less than requested) advance the file offset associated with the file descriptor by the same number of bytes read/written 29 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: binary data read() example #define BUFSIZE 1024 int buf[BUFSIZE]; read(fd, buf, BUFSIZE * sizeof(int)); This will NOT read characters from every line and interpret them as a decimal number (like fscanf() with %i or %d ) This reads binary integers as-is (file -> memory with no conversion) potentially binary integers that were written in the same manner man read , man write.2 30 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: lseek() off_t lseek(int fd, off_t offset, int whence); lseek() repositions the file offset of the open file description associated with the file descriptor fd to the argument offset according to the directive whence as follows: SEEK_SET : bytes from the beginning of the file. SEEK_CUR : bytes from the current position. SEEK_END : bytes from the end of the file. lseek() returns the file offset associated with the file descriptor 31 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall Low-level I/O: lseek() file size example off_t len = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); 32 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall C library overview Many sources: man pages, online, etc. Some of my go tos: https://en.cppreference.com/w/c/header for a nice organized overview https://sourceware.org/glibc/manual/html_mono/libc.html for in-depth information 33 Original Slides Noah Orensa Modified by Jon Lovering/Lauresa Stilling/Alexander Dumais/Dwight Makaroff CMPT 214 2024 Fall

Use Quizgecko on...
Browser
Browser