C PROGRAMMING FILE IO
Many
examples come from either Beginning Linux Programming by Neil Matthew and
Richard Stones Or from Dr. Robert Siegfried
Difference between Unix system file calls and stdio file stream buffered functions: (In this class, we explore unbuffered OPEN Unix System calls using the file descriptor and in 270 we explore FOPEN buffered stdio.h calls using a file pointer.)
|
FOPEN |
OPEN |
Source |
Stdio.h |
Unix system call |
Comparison of features |
Buffered |
Not buffered |
|
Handles interrupted writes on its own |
Programmer has to handle interrupted writes |
|
Buffering can be faster |
System calls can be slow |
|
Does ascii line end translation |
Does not translate any character including line end |
|
|
Open is guaranteed to be supported on any unix system. |
|
|
Permission control for creating new files |
|
|
Frequently used for socket and device drivers because of non-blocking |
Handle |
File pointer to file descriptor structure |
File Descriptor Number |
Convert to Handle type |
fdopen(give fd and get FILE *) |
Fileno (give FILE * and get fd) |
System tables involved in writing and reading files:
· File descriptor table 1 per process with one row per open file (0,1,2 are given as stdin, stdout and stderr) ; points to the open file table
· Open file table 1 per system with one per opener of a file; points to the inode table; holds current writing position
· Inode table 1 per physical file; points to the actual file location
Open file
· int fd = open(pathname, flags, mode);
o Use comma to separate the 3 parms, and use | to separate all the options you put into each parm.
· examples:
o int outp = open("file1.txt", O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWGRP)
§ // create file and error if it exists (due to O_EXCL) and allow Writing to the file. The new file will ask for the permissions of read for the user and write for the group. However, if UMASK does not allow, you wont get the permission. You will see that in ls -l
o int outp = open("file1.txt", O_APPEND | O_WRONLY)
§ // open file to append: You can never change the contents of the original file with that only add to the end.
o int outp = open("file1.txt", O_WRONLY)
§ // open file to write with your write cursor positioned at the beginning of the file
o int outp = open("file1.txt", O_RDWR )
§ // open file to read and write, and start the cursor for both at the beginning of the file
o int outp = open("file1.txt", O_RDONLY )
§ // open file to read, and start the cursor at the beginning of the file
· flags separate by |
o O_RDONLY : Read only
o O_WRONLY : Write only
o O_RDWR : Read and write
o O_APPEND : Only allow write past end of file
o O_TRUNC: wipe out file and all the space it takes
o O_CREAT: Create the file with the mode permissions if file does not exist
o O_EXCL : With O_CREATE, will fail if the file exists
·
Mode
o
separate by |
o
mode is only needed
for creation of a file
o
see result in ls -l
o
permissions may be
disallowed by UMASK type umask to see your
permissions
|
Owner |
Group |
Others |
Read Permission |
S_IRUSR |
S_IRGRP |
S_IROTH |
Write Permission |
S_IWUSR |
S_IWGRP |
S_IWOTH |
Execute Permission |
S_IXUSR |
S_IXGRP |
S_IXOTH |
· -1 is error
· Good return gives the file descriptor #
Examples: (You can look at the sample files at the location given below)
·
simple
open: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/create_file.c
·
examine
file descriptors: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/create_file_many.c
· Take a look at file descriptors : cd /proc/your process id found via ps
Write
· numwritten = write(fd, buffer, count);
· example: char buf[] = "what I want to write"; int numwritten = write(outp,buf,sizeof(buf));
· Note that if your buffer is a char * then you will want to use strlen not sizeof.
· -1 is error
· Good return gives the number of characters written to the file
· Examples:
o Example
of using write to write to the screen: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/simple_write.c
§ experiment
with command line redirection
o Example
of using write to write to a file: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/simple_write_file.c
Close
· status = close(fd);
Read
· numRead = read(fd, buffer, count);
· example: char buf[20]; int numRead = read(inp,buf,sizeof(buf));
o note that you want sizeof(buf), not strlen(buf) because the buffer is currently empty.
· -1 is error
· Good return gives the number of characters read into the buffer.
· after the read, your buffer is filled with the value read into it.
· Your buffer must have memory allocated use a character array of definite size
· Examples:
o example
of reading screen using read: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/simple_read.c
§ experiment
with redirection on the call
o example of reading file using read
and writing using write: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/copy_system.c
o Another example using a larger
block: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/copy_block.c
o Example of getting the file name
in different ways: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoenvfile2.c
o Example of reading a fixed layout
and making a change: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoenvfile3_onerecord.c
o Example of reading repeatedly
until the end of the file: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoenvfile3.c
o Example of reading until /n: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoreadline.c
§ Why it does not work to just read
to the end of the line: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoreadlinechunk.c
o Example of using a structure to
read and write a fixed layout: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoenvfile3.c
o Example of removing a record from
a fixed record layout: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoremovefixed.c
o Example of removing a record from
a non-fixed layout: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoremovenonfixed.c
o Example of creating a menu: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/menuwork.c
lseek
· #include <sys/types.h>
· #include <unistd.h>
· off_t lseek(int fd, off_t offset, int whence);
· example: int exactOffset = lseek(fd,15,SEEK_CUR);
· -1 is error
· Whence
o SEEK_SET from 0; SEEK_CUR from current offset ; SEEK_END from end
· Examples
o Example
of using seek to write after the start of the file: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/lseek_huge.c
o Example
of using seek to change a particular record: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/timestampwithseek.
§ first
create the file to read using : wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/timestamp.c
fstat
· fstat(file descriptor, pointer to a variable of type struct stat)
· Make a structure to receive the status info:
o struct stat file_info;
· call the fstat command to fill the structure
o fstat (fd, &file_info);
· similar commands:
o fstat reports on open files
o lstat on the link, not the file itself
o stat on a file in a directory
· Inside the structure, find:
o
st_mode
contains the files access permissions and the file type in the higher-order
bits.
o
st_uid and st_gid contain uid (user id number) and gid
group id number)
o
st_size
contains the file size, in bytes.
o
st_atime
contains the time when this file was last accessed (read or written).
o
st_mtime
contains the time when this file was last modified.
o
st_dev contains the major and minor device number of the
hardware device
o
st_ino
contains the inode number of this file.
o
example find
size: size_t size = file_info.st_size;
· Determine file type: (can call S_ISDIR (file_info.st_mode) or other file type macros)
o
S_ISBLK (mode) - block device
o
S_ISCHR (mode) - character device
o
S_ISDIR (mode) - directory
o
S_ISFIFO (mode) - fifo
(named pipe)
o
S_ISLNK (mode) - symbolic link
o
S_ISREG (mode) - regular file
o
S_ISSOCK (mode) - socket
o
Example:
§
if (S_ISDIR (file_info.st_mode))
§
return "directory";
· Examples:
o check if regular file: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/readfile.c
o check if directory: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/readdirectory.c
o https://www.lix.polytechnique.fr/~liberti/public/computing/prog/c/C/FUNCTIONS/stat.html
link:
· creates a new name for a file linked to an existing file
· link (old, new) returns -1 if error
· to rename link (old,new); unlink(old);
unlink
· removes a row from the open file table
· If it is the last open file pointing to a particular file in memory, it removes the file in memory as well as the open file row.
·
Example:
rename a file: wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demorename.c
Directories:
include <dirent.h>
opendir() - returns a DIR* handle, which can be used to access the directory contents.
If an error occurs, the call returns NULL.
example: DIR * dir = opendir (dir_path);
readdir() - returns a pointer to a struct dirent instance corresponding to the next directory entry.
The struct dirent contains
d_name : the name of a file
d_ino : the inode number.
create a pointer to this structure with : struct dirent* varname;
read with: entry = readdir (directory_pointer)
get the filename from a dirent structure as the d_name inside the structure variable
example:
struct dirent* entry;
// assume dir is the directory pointer that was retrieved from opendir
while ((entry = readdir (dir)) != NULL) {
char* filename = entry->d_name;
closedir() closes directory
closedir (dir);
Example:
wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/readdirectory.c
Environment variables:
· putenv( NEWONE=Hello); sets the environment variable you specify as though you had entered the shell command: env NEWONE=Hello. See that no spaces around the = is important. return -1 if not found
· getenv(HOME) ; returns the value of the environment variable.
·
Example:
wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoenvfile2.c
fcntl
· Does lots, but we are using it to lock files
· http://beej.us/guide/bgipc/output/html/multipage/flocking.html
· include <fcntl.h>
· create a variable of the lock type: struct flock fl;
· setting a lock:
o set the structure to the lock you want:
§ fl.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */
§ fl.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
§ fl.l_start = 0; /* Offset from l_whence */
§ fl.l_len = 0; /* length, 0 = to EOF */
§ fl.l_pid = getpid(); /* our PID */
o then set the lock or retrieve the lock info into the structure.
§ example: fcntl(fd, F_SETLKW, &fl); // F_GETLK (get lock info), F_SETLK (set lock) , F_SETLKW (set a lock but wait until the lock is available)
§ returns -1 if it cannot set the lock
· releasing a lock:
o set the structure to indicate unlock: fl.l_type = F_UNLCK; /* tell it to unlock the region */
o call fcntl again
§ example: fcntl(fd, F_SETLKW, &fl);
§ returns -1 if it cannot unset the lock
·
Example:
wget
http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/lockdemo.c
C variable types we will use:
int
double
char
char[#] : for a character array that allocates memory when created with a number inside brackets
char * : for a character array that does not allocate memory now. Later set to a string literal or allocate memory with malloc
char * x; x = (char *) (malloc (sizeof(char) * 30))
struct ? : create a type that has parts which are other variable types
create the struct type first using : struct name { int x; int y;};
create a variable of that type : struct name myvar;
use the type: myvar.x and myvar.y
C functions we will use:
Character functions: requires #include <ctype.h> http://www.tutorialspoint.com/c_standard_library/ctype_h.htm
toupper(char x) returns the uppercase version of x
tolower(char x) returns the lowercase version of x
isupper(char x) returns 0 when x is not uppercase
islower(char x) returns 0 when x is not lowercase
String functions: requires #include <string.h> http://www.tutorialspoint.com/c_standard_library/string_h.htm
strcpy (to, from) copies the "from" string to the "to" string and returns a pointer to the "to" string. Error is a NULL return.
strlen(string) returns the length of a string. It is looking for the first '\0' (NULL) to end the string.
strstr(string to search, string to find) returns a pointer to the first occurrence. You can give it a char * or char[], but you must take the answer back as a char *. It is actually just pointing to the original string, and is not a new string of its own.
memset (array , 0,SIZE ) to initials character array to nulls.
strcspn(string to search, character(s) to find) returns the index of the first occurrence of any of the characters in the second parameter. ex: strcspn("word","o") will return 1.
Standard I/O functions: requires #include <stdio.h> http://www.tutorialspoint.com/c_standard_library/stdio_h.htm
printf ("format string", a variable for each % in the format string) writes to the screen. %d is an integer, %lf is a double, %c is a character, %s is a string
puts("a string to write") writes to the screen with no variable content.
malloc(size) returns a pointer to a void type of the requested size. Upon error, it returns NULL.
C Program Structure:
· No classes
· A main method is required.
o If you want to read the arguments passed upon calling, include main(int argc, char *argv[])
§ argc is number of arguments calculated by the system
§ argv is an array of the arguments
§ ex: ./myprogram abc def a lr 'a var with space '
§ the dash is ignored so the third parm in example is a
§ the last parm is all taken as one 'a var with space ' because of the single quotes
§ the third parm is lr
· No String
· If structure is the same.
· switch (var) { case ? : do something; break; default: do something; break; }
· for same but cannot shortcut to create counter inside the loop
· #define <keyword> <translation> Use the keyword in the code.