9. 库函数方式文件编程
库函数:基于C函数库的文件编程是独立于具体的操作系统平台的,不管是在windows、linux还是其他操作系统中,都是使用这些函数。使用库函数进行程序设计可以提高程序的可移植性。
流:对于标准的C函数库,它们的操作都是围绕流来进行的。流是一个抽象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中"流"动一样。
文件指针:
在系统调用方式实现的文件访问中,使用文件描述符(一个整数)来指向一个文件。在库函数方式的文件访问中,使用FILE类型来表示一个打开的文件,这个类型中包含了管理文件流的信息。而指向该类型的指针FILE* 则被称之为文件指针。
打开文件:
打开文件的库函数是fopen,man fopen:得到下面信息:
NAME
fopen, fdopen, freopen - stream open functions
SYNOPSIS
#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *path, const char *mode, FILE *stream);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
fdopen(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
DESCRIPTION
The fopen() function opens the file whose name is the string pointed to by path
and associates a stream with it.
The argument mode points to a string beginning with one of the following sequences
(Additional characters may follow these sequences.):
r Open text file for reading. The stream is positioned at the beginning of
the file.
r+ Open for reading and writing. The stream is positioned at the beginning of
the file.
w Truncate file to zero length or create text file for writing. The stream
is positioned at the beginning of the file.
w+ Open for reading and writing. The file is created if it does not exist,
otherwise it is truncated. The stream is positioned at the beginning of
the file.
a Open for appending (writing at end of file). The file is created if it
does not exist. The stream is positioned at the end of the file.
a+ Open for reading and appending (writing at end of file). The file is cre-
ated if it does not exist. The initial file position for reading is at the
beginning of the file, but output is always appended to the end of the
file.
The mode string can also include the letter 'b' either as a last character or as a
character between the characters in any of the two-character strings described
above. This is strictly for compatibility with C89 and has no effect; the 'b' is
ignored on all POSIX conforming systems, including Linux. (Other systems may
treat text files and binary files differently, and adding the 'b' may be a good
idea if you do I/O to a binary file and expect that your program may be ported to
non-Unix environments.)
See NOTES below for details of glibc extensions for mode.
Any created files will have mode S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH |
S_IWOTH (0666), as modified by the process's umask value (see umask(2)).
Reads and writes may be intermixed on read/write streams in any order. Note that
ANSI C requires that a file positioning function intervene between output and
input, unless an input operation encounters end-of-file. (If this condition is
not met, then a read is allowed to return the result of writes other than the most
recent.) Therefore it is good practice (and indeed sometimes necessary under
Linux) to put an fseek(3) or fgetpos(3) operation between write and read opera-
tions on such a stream. This operation may be an apparent no-op (as in fseek(...,
0L, SEEK_CUR) called for its synchronizing side effect.
Opening a file in append mode (a as the first character of mode) causes all subse-
quent write operations to this stream to occur at end-of-file, as if preceded by
an
fseek(stream,0,SEEK_END);
call.
The fdopen() function associates a stream with the existing file descriptor, fd.
The mode of the stream (one of the values "r", "r+", "w", "w+", "a", "a+") must be
compatible with the mode of the file descriptor. The file position indicator of
the new stream is set to that belonging to fd, and the error and end-of-file indi-
cators are cleared. Modes "w" or "w+" do not cause truncation of the file. The
file descriptor is not dup'ed, and will be closed when the stream created by
fdopen() is closed. The result of applying fdopen() to a shared memory object is
undefined.
The freopen() function opens the file whose name is the string pointed to by path
and associates the stream pointed to by stream with it. The original stream (if
it exists) is closed. The mode argument is used just as in the fopen() function.
The primary use of the freopen() function is to change the file associated with a
standard text stream (stderr, stdin, or stdout).
RETURN VALUE
Upon successful completion fopen(), fdopen() and freopen() return a FILE pointer.
Otherwise, NULL is returned and errno is set to indicate the error.
ERRORS
EINVAL The mode provided to fopen(), fdopen(), or freopen() was invalid.
The fopen(), fdopen() and freopen() functions may also fail and set errno for any
of the errors specified for the routine malloc(3).
The fopen() function may also fail and set errno for any of the errors specified
for the routine open(2).
The fdopen() function may also fail and set errno for any of the errors specified
for the routine fcntl(2).
The freopen() function may also fail and set errno for any of the errors specified
for the routines open(2), fclose(3) and fflush(3).
CONFORMING TO
The fopen() and freopen() functions conform to C89. The fdopen() function con-
forms to POSIX.1-1990.
NOTES
Glibc Notes
The GNU C library allows the following extensions for the string specified in
mode:
c (since glibc 2.3.3)
Do not make the open operation, or subsequent read and write operations,
thread cancellation points.
e (since glibc 2.7)
Open the file with the O_CLOEXEC flag. See open(2) for more information.
m (since glibc 2.3)
Attempt to access the file using mmap(2), rather than I/O system calls
(read(2), write(2)). Currently, use of mmap(2) is only attempted for a
file opened for reading.
x Open the file exclusively (like the O_EXCL flag of open(2)). If the file
already exists, fopen() fails, and sets errno to EEXIST. This flag is
ignored for fdopen().
SEE ALSO
open(2), fclose(3), fileno(3), fmemopen(3), fopencookie(3)
COLOPHON
This page is part of release 3.22 of the Linux man-pages project. A description
of the project, and information about reporting bugs, can be found at
http://www.kernel.org/doc/man-pages/.
我们从上面的信息知道,
打开文件的函数的功能是open file,原型是:
FILE *fopen(const char *path, const char *mode);
需要包含的头文件是:
<stdio.h>
返回值:如果成功是返回文件指针,失败则是NULL。参数:path就是要打开文件的路径,mode是文件打开模式,例如可读可写。
fopen.c:
#include <stdio.h>
void main(){
FILE *fp;
fp = fopen("/home/wen","w+");
}
运行结果:
关闭文件:
关闭文件是fclose,man fopen的信息:
NAME
fclose - close a stream
SYNOPSIS
#include <stdio.h>
int fclose(FILE *fp);
DESCRIPTION
The fclose() function will flushes the stream pointed to by fp (writing any
buffered output data using fflush(3)) and closes the underlying file descriptor.
RETURN VALUE
Upon successful completion 0 is returned. Otherwise, EOF is returned and errno is
set to indicate the error. In either case any further access (including another
call to fclose()) to the stream results in undefined behavior.
ERRORS
EBADF The file descriptor underlying fp is not valid.
The fclose() function may also fail and set errno for any of the errors specified
for the routines close(2), write(2) or fflush(3).
CONFORMING TO
C89, C99.
NOTES
Note that fclose() only flushes the user space buffers provided by the C library.
To ensure that the data is physically stored on disk the kernel buffers must be
flushed too, for example, with sync(2) or fsync(2).
SEE ALSO
close(2), fcloseall(3), fflush(3), fopen(3), setbuf(3)
COLOPHON
This page is part of release 3.22 of the Linux man-pages project. A description
of the project, and information about reporting bugs, can be found at
http://www.kernel.org/doc/man-pages/.
函数fclose的功能是关闭一个打开的文件,函数的原型是:
int fclose(FILE *fp);
需要的头文件:
stdio.h
如果关闭成功则返回0,失败则返回EOF。
fclose.c:
#include <stdio.h>
void main(){
FILE *fp;
fp = fopen("/home/wen","w+");
fclose(fp);
}
运行结果:
读文件:
在命令行man fread:
NAME
fread, fwrite - binary stream input/output
SYNOPSIS
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb,
FILE *stream);
DESCRIPTION
The function fread() reads nmemb elements of data, each size bytes long, from the
stream pointed to by stream, storing them at the location given by ptr.
The function fwrite() writes nmemb elements of data, each size bytes long, to the
stream pointed to by stream, obtaining them from the location given by ptr.
For non-locking counterparts, see unlocked_stdio(3).
RETURN VALUE
fread() and fwrite() return the number of items successfully read or written
(i.e., not the number of characters). If an error occurs, or the end-of-file is
reached, the return value is a short item count (or zero).
fread() does not distinguish between end-of-file and error, and callers must use
feof(3) and ferror(3) to determine which occurred.
CONFORMING TO
C89, POSIX.1-2001.
SEE ALSO
read(2), write(2), feof(3), ferror(3), unlocked_stdio(3)
COLOPHON
This page is part of release 3.22 of the Linux man-pages project. A description
of the project, and information about reporting bugs, can be found at
http://www.kernel.org/doc/man-pages/.
fread函数是从文件中读取数据,函数的原型:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
需要的头文件:stdio.h
返回值:如果读取成功则返回读取到的数据量,失败则返回0.
Stream:指向要读取的文件。
ptr:指向读取出来后的数据保存的位置。
nmemb:是一次读取数据块的块数。
size:就是每一块的大小。
所以总的读取大小是nmemb*size。
fread.c的代码:
#include <stdio.h>
void main(){
FILE *fp;
char f_buf[17];
fp = fopen("/home/wen","w+");
fread(f_buf,2,8,fp);
f_buf[16] = ' ';
printf("fread is %s ",f_buf);
fclose(fp);
}}运行的结果是读出的内容为空:
这是为啥呢?其实问题出在fopen的w+参数,清空了内容。我们应该使用r+:
#include <stdio.h>
void main(){
FILE *fp;
char f_buf[17];
fp = fopen("/home/wen","r+");
fread(f_buf,2,8,fp);
f_buf[16] = ' ';
printf("fread is %s ",f_buf);
fclose(fp);
}
运行的结果:
这个程序中最核心的就是:fread(f_buf,2,8,fp);它的意思是从fd文件指针所指定的地方读取数据,每次读2个字节,读8次,读得的结果存到f_buf里面。
写文件:
在命令行执行man fwrite:
NAME
fread, fwrite - binary stream input/output
SYNOPSIS
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb,
FILE *stream);
DESCRIPTION
The function fread() reads nmemb elements of data, each size
bytes long, from the stream pointed to by stream, storing them
at the location given by ptr.
The function fwrite() writes nmemb elements of data, each size
bytes long, to the stream pointed to by stream, obtaining them
from the location given by ptr.
For non-locking counterparts, see unlocked_stdio(3).
RETURN VALUE
fread() and fwrite() return the number of items successfully
read or written (i.e., not the number of characters). If an
error occurs, or the end-of-file is reached, the return value
is a short item count (or zero).
fread() does not distinguish between end-of-file and error,
and callers must use feof(3) and ferror(3) to determine which
occurred.
CONFORMING TO
C89, POSIX.1-2001.
SEE ALSO
read(2), write(2), feof(3), ferror(3), unlocked_stdio(3)
COLOPHON
This page is part of release 3.22 of the Linux man-pages
project. A description of the project, and information about
reporting bugs, can be found at http://www.kernel.org/doc/man-
pages/.
fwrite函数是向文件中写入数据,函数的原型:
size_t fwrite(const void *ptr, size_t size, size_t nmemb,
FILE *stream);
需要的头文件:stdio.h
返回值:如果读取成功则返回读取到的数据量,失败则返回0.
Stream:指向要写入数据的文件的指针。
ptr:指向存放要写入文件的数据
nmemb:是一次写入数据块的块数。
size:就是每一块的大小。
所以总的读取大小是nmemb*size。
fwrite.c:
#include <stdio.h>
void main(){
FILE *fp;
char *f_buf="1234567890123456";
fp = fopen("/home/wen","r+");
//fread(f_buf,2,8,fp);
//f_buf[16] = ' ';
fwrite(f_buf,2,8,fp);
//printf("fread is %s ",f_buf);
fclose(fp);
}
运行的结果:
定位文件:
函数fseek,通过man fseek查看信息:
NAME
fgetpos, fseek, fsetpos, ftell, rewind - reposition a stream
SYNOPSIS
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
void rewind(FILE *stream);
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, fpos_t *pos);
DESCRIPTION
The fseek() function sets the file position indicator for the
stream pointed to by stream. The new position, measured in
bytes, is obtained by adding offset bytes to the position
specified by whence. If whence is set to SEEK_SET, SEEK_CUR,
or SEEK_END, the offset is relative to the start of the file,
the current position indicator, or end-of-file, respectively.
A successful call to the fseek() function clears the end-of-
file indicator for the stream and undoes any effects of the
ungetc(3) function on the same stream.
The ftell() function obtains the current value of the file
position indicator for the stream pointed to by stream.
The rewind() function sets the file position indicator for the
stream pointed to by stream to the beginning of the file. It
is equivalent to:
(void) fseek(stream, 0L, SEEK_SET)
except that the error indicator for the stream is also cleared
(see clearerr(3)).
The fgetpos() and fsetpos() functions are alternate interfaces
equivalent to ftell() and fseek() (with whence set to
SEEK_SET), setting and storing the current value of the file
offset into or from the object referenced by pos. On some
non-Unix systems an fpos_t object may be a complex object and
these routines may be the only way to portably reposition a
text stream.
RETURN VALUE
The rewind() function returns no value. Upon successful com-
pletion, fgetpos(), fseek(), fsetpos() return 0, and ftell()
returns the current offset. Otherwise, -1 is returned and
errno is set to indicate the error.
ERRORS
EBADF The stream specified is not a seekable stream.
EINVAL The whence argument to fseek() was not SEEK_SET,
SEEK_END, or SEEK_CUR.
The functions fgetpos(), fseek(), fsetpos(), and ftell() may
also fail and set errno for any of the errors specified for
the routines fflush(3), fstat(2), lseek(2), and malloc(3).
CONFORMING TO
C89, C99.
SEE ALSO
lseek(2), fseeko(3)
COLOPHON
This page is part of release 3.22 of the Linux man-pages
project. A description of the project, and information about
reporting bugs, can be found at http://www.kernel.org/doc/man-
pages/.
fseek函数是实现定位文件指针的功能,函数的原型:
int fseek(FILE *stream, long offset, int whence);
需要的头文件:stdio.h
返回值:返回值是移动后的文件指针距离文件头的位置的距离,失败则返回-1.
Stream:指向要定位的文件。
Whence: 它的取值有三种情况:SEEK_SET, SEEK_CUR,
or SEEK_END,
offset: 是偏移量,就是距离whence的距离。
fwrite.c:
#include <stdio.h>
void main(){
FILE *fp;
char *f_buf="1234567890123456";
fp = fopen("/home/wen","r+");
fseek(fp,4,SEEK_SET);
//fread(f_buf,2,4,fp);
//f_buf[8] = ' ';
fwrite(f_buf,2,4,fp);
//printf("fread is %s ",f_buf);
fclose(fp);
}
执行的结果: