60-256 System Programming: Standard Input/Output Library (Cont’d)
Content
COMP 2560 System Programming:
Standard Input/Output Library (Cont’d)
Courtesy of Dr. B. Boufama
Modified by Dan Wu
School of Computer Science University of Windsor
–
Instructor: Dr. Dan Wu
Standard Input/Output Library (Cont’d)
1
Copyright @ 2019, 2020, 2021 all rights reserved
Content
Content
Standard Input/Output Library (Cont’d)
2
hello.c
xxd example.txt
filesize1.c
Copyright @ 2019, 2020, 2021 all rights reserved
Content
Content
Standard Input/Output Library (Cont’d)
3
Copyright @ 2019, 2020, 2021 all rights reserved
Content
Content
Standard Input/Output Library (Cont’d)
4
char_int.c
assume that within the file we are reading from is a byte with value 0xff.
fgetc() returns this value within an int, so it looks like this: 0x00ff (again, assuming 2 byte ints).
To store this value in a char, it must be demoted, and the char value becomes 0xff.
Next, the char c is compared with the int EOF.
Promotion rules apply, and c must be promoted to an int. However, in the sample code, the sign of c isn’t explicitly declared, so we don’t know if it’s signed or unsigned, so the int value could become either 0xff ff or 0x00 ff.
Therefore, the code is not guaranteed to work in the way we require.
Copyright @ 2019, 2020, 2021 all rights reserved
Content
Content
Standard Input/Output Library (Cont’d)
5
Another scenario to consider is where the char is unsigned.
In this case, the process of demoting and promoting the returned value from fgetc() will have the affect of “corrupting” the EOF value, and the program will get stuck in an infinite loop.
unsigned char c;
while ((c = fgetc(fp)) != EOF) { putchar (c);
}
Copyright @ 2019, 2020, 2021 all rights reserved
Content
Content
Standard Input/Output Library (Cont’d)
6
unsigned char c;
while ((c = fgetc(fp)) != EOF) { putchar (c);
}
EOF (0xff ff) is returned by fgetc() due to end of input
Value demoted to 0xff to be stored in unsigned char c
unsigned char c promoted to an int, value goes from 0xff to 0x00 ff
EOF is compared with c, meaning comparison is between 0xff ff and 0x00 ff.
The result is FALSE (the values are different), which is undesirable.
fgetc() is called again, and still returns EOF. The endless loop begins.
Copyright @ 2019, 2020, 2021 all rights reserved
Content
Content
1
Binary I/O
2
Random file access
3
Formatted I/O
4
The errno variable and the function perror()
5
Summary
Standard Input/Output Library (Cont’d)
7
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
Binary I/O
The following I/O functions are not well suited for binary I/O:
fgetc()/fputc() are too slow to handle millions of bytes.
fgets() cannot be used because it stops when it hits a newline character which is usually part of the binary information.
fputs() cannot be used because it stops when it hits a NULL character which is usually part of the binary information.
This makes the above I/O functions not well suited for binary I/O.
Binary I/O functions
Binary I/O functions are specially useful when reading/writing whole structures.
Instead of reading/writing fields, we can read/write a number of bytes(the size of the structure) and therefore, achieve fast input/output operations.
Standard Input/Output Library (Cont’d)
8
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
fread
The read function in the stdio
size t fread(void *ptr, size t size, size t nitems, FILE *fp);
In particular, fread()
reads into an array pointed to by ptr up to nitems items of data from the stream fp, where an item of data is a sequence of size t bytes.
stops reading bytes if an end-of-file or error condition occurs, or if nitems items have been read.
returns number of items (not bytes) read.
When the returned value is less than nitems, feof() or
ferror() should be called to verify the reason.
Standard Input/Output Library (Cont’d)
9
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
fwrite
The write function in the stdio
size t fwrite(const void *ptr, size t size, size t nitems, FILE *fp);
In particular, fwrite()
writes to the stream fp up to nitems items of data from the array, pointed to by ptr, where an item of data is a sequence of size t bytes.
stops writing bytes when it has written nitems items of data or if an error has occurred.
returns number of items(not bytes) read.
An important issue about fwrite()
A call to fwrite() in buffered mode may return success even though the underlying system call (write()) fails. This can cause unpredictable results. Therefore, use fwrite() function
only in unbuffered mode if needed.
Standard Input/Output Library (Cont’d)
10
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
Example: speeding-up input using fread()
typedef struct{ char name[30]; int id; double x, y;
} itemT;
int main(void){ itemT data[100]; FILE *fp;
fp = fopen(‘‘data.bin’’, ‘‘r’’); if(fread(data, sizeof(itemT), 100, fp)!=100){
if(feof(fp))
printf(‘‘End of file before reading all’’); else
printf(‘‘Error occured’’); exit(1);
}
}
Standard Input/Output Library (Cont’d)
11
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
Example: speeding-up output using fwrite()
int main(void){ itemT data[100]; FILE *fp;
:
fp = fopen(‘‘result.bin’’, ‘‘w’’); setbuf(fp, NULL); // turn buffering off
if(fwrite(data, sizeof(itemT), 100, fp)!=100){
printf(‘‘Error occured’’);
exit(1);
}
}
Standard Input/Output Library (Cont’d)
12
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
Standard Input/Output Library (Cont’d)
See pirate.c and dictionary.c for two more examples.
13
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
Problems with binary I/O
There are two fundamental problems with these binary I/O functions:
1
The offset of a structure’s member can differ from one compiler to another.
→ The binary layout of a structure can differ depending on
2
compiler options.
The binary format used to store a multibyte numeric value differs from one architecture to another, known as
little-endian vs. big-endian orders. For example:
Sparc workstations are big-endian : a 4-byte integer is stored with the left-most byte first.
Intel machines are little-endian : a 4-byte integer is stored with the right-most byte first.
Standard Input/Output Library (Cont’d)
14
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
Case example
1-Run this on CS server to create the file data.bin.
#include
#include
int main(int argc, char *argv[]){ FILE *f1;
int data[10], i;
for(i=0; i<10; i++) data[i] = 10*i*i;
if(!(f1=fopen(argv[1], "w"))){ printf("could not create file"); exit(1);
}
if(fwrite(data, sizeof(int), 10, f1) != 10){ printf("Error on writing into file"); exit(2);
}
fclose(f1);
}
Standard Input/Output Library (Cont’d)
15
0x 12 34
Addr: value
: 12
: 34
Addr: value
1000: 34
1000: 12
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
Run this on CS server with data.bin as argv[1]
ftp data.bin to a PC machine
Run this on a PC with data.bin as argv[1]
#include
#include
int main(int argc, char *argv[]){ FILE *f1;
int data[10], i;
if(!(f1=fopen(argv[1], “r”))){ printf(“could open file”); exit(1);
}
if(fread(data, sizeof(int), 10, f1) != 10){ printf(“Could not read data”);
exit(2);
}
for(i=0; i<10; i++)
printf("%d\n", data[i]);
}
Standard Input/Output Library (Cont’d)
16
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
Random file access: ftell, rewind and fseek
The standard I/O library provides functions to
get the current value of the file-position indicator of a stream.
long ftell(FILE *stream);
If successful, it returns the current value of the file-position indicator, measured in bytes from the beginning of the file,
-1 otherwise.
reset file position indicator in a stream
void rewind(FILE *stream);
Sets the value of the file-position indicator to 0. rewind() also clears the error/end-of-file indicators. redefine a file-position indicator in a stream
int fseek(FILE *fp, long offset, int whence);
Return 0 if OK, nonzero otherwise.
Standard Input/Output Library (Cont’d)
17
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
fseek()
int fseek(FILE *fp, long offset, int whence); fseek() redefines the position of the next input or output operation. The new position, measured in bytes from the beginning of the file, is obtained by adding offset to the position specified by whence, whose values are defined in
SEEK SET: set position equal to offset bytes.
SEEK CUR: set position to current location plus offset.
SEEK END: set position to EOF plus offset.
In particular, fseek(fp, 0L, SEEK SET) is equivalent to
rewind(fp)
Note
Note that the fseek() function allows the file-position indicator to be set beyond the end of existing data in the file. Reads of data in the gap will return bytes with the value 0.
These functions can only be used on random access files.
Standard Input/Output Library (Cont’d)
18
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
Formatted output
The standard I/O library provides the following functions:
int printf(const char *format, …);
int fprintf(FILE *fp, const char *format,
…);
int sprintf(char *ar, const char *format,
…);
sprintf is similar to printf, except that it writes to the array ar instead of the standard output and it adds a NULL character at the end.
All these function return the number of written characters (excluding the terminating NULL character in the case of sprintf) and a negative value in case of error.
Example: sprintf(result, ‘‘%f’’, speed);
This converts a float(speed) into a string (result).
Standard Input/Output Library (Cont’d)
19
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
Formatted input
The standard I/O library provides the following functions:
int scanf(const char *format, …);
int fscanf(FILE *fp, const char *format,
…);
int sscanf(const char *ar, const char
*format,…);
sscanf is similar to scanf, except that it reads inputs from the array pointed to by ar instead of the standard input stdin.
All these functions return the number of items successfully read and -1 in case of end-of-file or error.
Example
Example1: sscanf(argv[1], ‘‘%d’’, &n);
Converts the first command argument argv[1], which is read as a string, into an integer and stores it in the variable n.
Standard Input/Output Library (Cont’d)
20
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
Example2: run-time-error-free input functions. (see readInt.c)
int readInt(void){
char input[100];
int value;
do{
printf(‘‘Please enter an integer> ‘‘); scanf(‘‘%s’’, input);
}while (sscanf(input, ‘‘%d’’, &value)!= 1); return(value);
}
//DIY
double readDouble(void){ char input[100];
double value;
do{
printf(‘‘Please enter a real number> ‘‘); scanf(‘‘%s’’, input);
}while (sscanf(input, ‘‘%lf’’, &value)!= 1); return(value);
}
Standard Input/Output Library (Cont’d)
21
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
errno and perror()
All function calls may fail when an error occurs and returns -1 as a consequence.
The standard I/O library functions will fail whenever a related system call fails.
E.g,. fopen() depends on the system call open().
→ fopen() will return a NULL if open() fails.
To gain more information about system call failures, Unix provide two things, a globally accessible integer variable, called errno, and a subroutine, called perror().
In order to use these two tools, you should include
< sys/errno.h > in your program.
Standard Input/Output Library (Cont’d)
22
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
More details: errno and perror()
errno: Every process contains a global variable, called, errno, initialized to 0 when the process is first created.
When a system call error occurs, errno is set to a numerical code corresponding to the error.
For example, if open() fails because the file does not exist, then errno is set to 2.
On the other hand, if a system call was successful, errno
will not be updated.
Note that the list of error codes can be found in
< usr/include/errno.h >.
Standard Input/Output Library (Cont’d)
23
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
More details: errno and perror()
void perror(char *str):
this library routine is provided by Unix for reporting errors.
When called, it will produce a message on the standard error that consists of the string parameter passed to the routine, a colon(:) and, an additional english message associated with the current value of the variable errno.
Standard Input/Output Library (Cont’d)
24
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
#include
void copyFiles(FILE *, FILE *); int main(int argc, char *argv[]){
FILE *f1, *f2;
f1=fopen(argv[1], “r”); if( f1 == NULL){
perror(“main function”); exit(1);
}
f2=fopen(argv[2], “w”); if( f2 == NULL){
perror(“main function”); exit(2);
}
copyFiles(f1, f2); exit(0);
}
Standard Input/Output Library (Cont’d)
25
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
void copyFiles(FILE *f1, FILE *f2){ int c;
while((c=fgetc(f1)) != EOF) if (fputc(c, f2) == EOF){
perror(“copy function”); exit(3);
}
if(ferror(f1)){ perror(“copy function”); exit(4);
}
}
Note that perror() is not a system call.
Standard Input/Output Library (Cont’d)
26
Copyright @ 2019, 2020, 2021 all rights reserved
Binary I/O Random file access
Formatted I/O The errno variable and the function perror()
Summary
We have looked at almost all functions provided by the standard I/O library.
This library is used by most Unix applications.
In particular, you have to be aware of the followings :
Calling a standard I/O function does not necessarily trigger an actual I/O operation.
buffering generates confusion and problems.
I/O are main sources of serious bugs
it is very important to understand each I/O function before using it in order to get a robust software.
Standard Input/Output Library (Cont’d)
27
Copyright @ 2019, 2020, 2021 all rights reserved