Linux下的文件编程
2012-07-13 16:28
162 查看
Linux 提供的虚拟文件系统为多种文件系统提供了统一的接口,Linux 的文件编程有两种途径:基于Linux 系统调用;基于C 库函数。这两种编程所涉及到文件操作有新建、打开、读写和关闭,对随机文件还可以定位。
通常,一个进程打开时,都会打开3 个文件:标准输入、标准输出和标准出错处理。这3 个文件分别对应文件描述符为0 、1
和2 (也就是宏替换STDIN_FILENO 、STDOUT_FILENO 和STDERR_FILENO )。
一、Linux 系统调用
不带缓存的文件I/O 操作,这里指的不带缓存是指每一个函数只调用系统中的一个函数。主要用到5 个函数:open 、read 、write 、lseek 和close
。
1 、open 函数语法要点:
所需头文件:#include<sys/types.h>// 提供类型pid_t 的定义
#include<sys/stat.h>
#include<fcntl.h>
函数原型:int open(const char *pathname,flags,int perms)
函数传入值:
path :被打开文件名(可包括路径名)
flag :文件打开的方式,参数可以通过“|” 组合构成,但前3 个参数不能互相重合。
O_REONLY :只读方式打开文件
O_WRONLY :可写方式打开文件
O_RDWR :读写方式打开文件
O_CREAT :如果文件不存在时就创建一个新文件,并用第三个参数为其设置权限。
O_EXCL :如果使用O_CREAT 时文件存在,则可返回错误信息。这一参数可测试文件是否存在。
O_NOCTTY :使用本参数时,如文件为终端,那么终端不可以作为调用open ()系统调用的那个进程的控制终端。
O_TRUNC :如文件已经存在,并且以只读或只写成功打开,那么会先全部删除文件中原因数据。
O+APPEND :以添加方式打开文件,在打开文件的同时,文件指针指向文件末尾。
perms :被打开文件的存取权限,为8 进制表示法。
函数返回值:成功:返回文件描述符 失败:-1
2 、Close 语法要点:
所需头文件:#include<uniste.h>
函数原型:int close (int fd )
函数输入值:fd :文件描述符
函数返回值:成功:0 出错:-1
3 、Read 函数语法要点
所需头文件:#include<unistd.h>
函数原型:ssize_t read(int fd,void *buf,size_t count)
函数传入值
fd: 文件描述符
Buf :指定存储器读出数据的缓冲区
Count :指定读出的字节数
函数返回值:成功:读出的字节数 0 :已到达文件尾 -1 :出错
在读普通文件时,若读到要求的字节数之前已达到文件的尾部,则返回字节数会小于希望读出的字节数。
4 、Write 函数语法要点
所需头文件:#include<unistd.h>
函数原型: ssize_t write(int fd,void *buf,size_t count)
函数传入值:
fd: 文件描述符
Buf :指定存储器写入数据的缓冲区
Count :指定读出的字节数
函数返回值:成功:已写的字节数 -1 :出错
5 、Lseek 函数语法要点:
所需头文件
4000
:#include<unistd.h>
#include<sys/types.h>
函数原型:off_t lseek(int fd,off_t offset,int whence)
函数传入值:
fd: 文件描述符
Offset :偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)
Whence :当前位置的基点:
SEEK_SET :当前位置为文件开头,新位置为偏移量的大小
SEEK_CUR :当前位置为文件指针位置,新位置为当前位置加上偏移量
SEEK_END :当前位置为文件的结尾,新位置为文件的大小加上偏移量大小
函数使用实例:
/**/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char *buf="Hello! I'm writing to this file!";
char buf_r[11];
int fd,size,len;
len = strlen(buf);
buf_r[10] = '/0';
/* 首先调用open 函数,并指定相应的权限*/
if ((fd = open("hello.c", O_CREAT | O_TRUNC | O_RDWR,0666 ))<0) {
perror("open:");
exit(1);
} else
printf("open and create file:hello.c %d OK/n",fd);
/* 调用write 函数,将buf 中的内容写入到打开的文件中*/
if ((size = write( fd, buf, len)) < 0){
perror("write:");
exit(1);
} else
printf("Write:%s OK/n",buf);
/* 调用lseek 函数将文件指针移动到文件起始,并读出文件中的10 个字节
*/
lseek(fd, 0, SEEK_SET );
if ((size = read( fd, buf_r, 10))<0) {
perror("read:");
exit(1);
} else
printf("read form file:%s OK/n",buf_r);
if ( close(fd) < 0 ) {
perror("close:");
exit(1);
} else
printf("Close hello.c OK/n");
return 0;
}
二、C 语言库函数
C 库函数的文件操作实际上是独立于具体的操作系统平台的,不管是在DOS 、Windows 、Linux 还是在VxWorks 中都是这些函数:
创建和打开
fopen() 实现打开指定文件filename ,其中的mode 为打开模式,C 语言中支持的打开模式如下表:
其中b 用于区分二进制文件和文本文件,这一点在DOS 、Windows 系统中是有区分的,但Linux 不区分二进制文件和文本文件。
读写
C 库函数支持以字符、字符串等为单位,支持按照某中格式进行文件的读写,这一组函数为:
fread() 实现从流stream 中读取加n 个字段,每个字段为size 字节,并将读取的字段放入ptr 所指的字符数组中,返回实际已读取的字段
数。在读取的字段数小于num 时,可能是在函数调用时出现错误,也可能是读到文件的结尾。所以要通过调用feof() 和ferror() 来判断。
write() 实现从缓冲区ptr 所指的数组中把n 个字段写到流stream 中,每个字段长为size 个字节,返回实际写入的字段数。
另外,C 库函数还提供了读写过程中的定位能力,这些函数包括
关闭
利用C 库函数关闭文件依然是很简单的操作:
例程:将第2 节中的例程用C 库函数来实现。
#include <stdio.h>
#define LENGTH 100
main()
{
FILE *fd;
char str[LENGTH];
fd = fopen("hello.txt", "w+"); /* 创建并打开文件 */
if (fd)
{
fputs("Hello, Everyone!", fd); /* 写入Hello,
Everyone!"
字符串 */
fclose(fd);
}
fd = fopen("hello.txt", "r");
fgets(str, LENGTH, fd); /* 读取文件内容 */
printf("%s/n", str);
fclose(fd);
}
三、
<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-f
d0bb
ont-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt;
text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} /* Page Definitions */ @page {mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->
f c n t l
函数有五种功能:
n
复制一个现存的描述符
, 新文件描述符作为函数值返
(c m d =
F_DUPFD )。
n
获得
/ 设置文件描述符标记
, 对应于 filedes
的文件描述符标志作为函数值返回.(
c m d = F_GETFD
或 F_SETFD
)。
n
获得
/ 设置文件状态标志,对应于 filedes
的文件状态标志作为函数值返回。(
c m d = F_GETFL 或
F_SETFL )。
n
获得
/ 设置异步
I / O 有权(
c m d = F_GETOWN 或
F_SETOWN )。
n
获得
/ 设置记录锁(
c m d = F_SETLK , F_SETLKW )。
#include <sys/types.h>
#include <unistd.h>
#include <fcnt1.h>
int fcnt1(int
filedes , int cmd ,... struct flock flockptr ) ;
struct flock
结构
ioctl
函数是
I / O 操作的杂物箱。不能用本章中其他函数表示的
I / O
操作通常都能用 i o c t l
表示。终端 I / O
是 ioctl 的最大使用方面,主要用于设备的
I / O
控制。
#include <unistd.h> /* SVR4 */
#include <sys/ioctl.h> /* 4.3+BSD * /
int ioctl(int
filedes , int request , . . . ) ;
返回:若出错则为
- 1
,若成功则为其他值
I/O
处理的五种模型
①
阻塞
I/O 模型:若所调用的
I/O 函数没有完成相关的功能就会使进程挂起,直到相关数据到达才会返回。如:终端、网络设备的访问。
②
非阻塞模型:当请求的
I/O 操作不能完成时,则不让进程休眠,而且返回一个错误。如:
open
、 read
、 write
访问。
③
I/O
多路转接模型:如果请求的 I/O 操作阻塞,且他不是真正阻塞
I/O
,而且让其中的一个函数等待,在这期间, I/O
还能进行其他操作。如: select
函数。
④
信号驱动
I/O 模型:在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动
I/O
。
⑤
异步
I/O 模型:在这种模型下,当一个描述符已准备好,可以启动
I/O
时,进程会通知内核。由内核进行后续处理,这种用法现在较少
#include <sys/types.h>/* fd_set data type */
#include <sys/time.h> /* struct timeval */
#include <unistd.h> /* function prototype might be here */
int select (int
numfds , fd_set *readfds ,
fd_set *writefds , fd_set *exceptfds , struct timeval *
timeout ) ;
返回:准备就绪的描述符数,若超时则为
0
,若出错则为 - 1
。
通常,一个进程打开时,都会打开3 个文件:标准输入、标准输出和标准出错处理。这3 个文件分别对应文件描述符为0 、1
和2 (也就是宏替换STDIN_FILENO 、STDOUT_FILENO 和STDERR_FILENO )。
一、Linux 系统调用
不带缓存的文件I/O 操作,这里指的不带缓存是指每一个函数只调用系统中的一个函数。主要用到5 个函数:open 、read 、write 、lseek 和close
。
1 、open 函数语法要点:
所需头文件:#include<sys/types.h>// 提供类型pid_t 的定义
#include<sys/stat.h>
#include<fcntl.h>
函数原型:int open(const char *pathname,flags,int perms)
函数传入值:
path :被打开文件名(可包括路径名)
flag :文件打开的方式,参数可以通过“|” 组合构成,但前3 个参数不能互相重合。
O_REONLY :只读方式打开文件
O_WRONLY :可写方式打开文件
O_RDWR :读写方式打开文件
O_CREAT :如果文件不存在时就创建一个新文件,并用第三个参数为其设置权限。
O_EXCL :如果使用O_CREAT 时文件存在,则可返回错误信息。这一参数可测试文件是否存在。
O_NOCTTY :使用本参数时,如文件为终端,那么终端不可以作为调用open ()系统调用的那个进程的控制终端。
O_TRUNC :如文件已经存在,并且以只读或只写成功打开,那么会先全部删除文件中原因数据。
O+APPEND :以添加方式打开文件,在打开文件的同时,文件指针指向文件末尾。
perms :被打开文件的存取权限,为8 进制表示法。
函数返回值:成功:返回文件描述符 失败:-1
2 、Close 语法要点:
所需头文件:#include<uniste.h>
函数原型:int close (int fd )
函数输入值:fd :文件描述符
函数返回值:成功:0 出错:-1
3 、Read 函数语法要点
所需头文件:#include<unistd.h>
函数原型:ssize_t read(int fd,void *buf,size_t count)
函数传入值
fd: 文件描述符
Buf :指定存储器读出数据的缓冲区
Count :指定读出的字节数
函数返回值:成功:读出的字节数 0 :已到达文件尾 -1 :出错
在读普通文件时,若读到要求的字节数之前已达到文件的尾部,则返回字节数会小于希望读出的字节数。
4 、Write 函数语法要点
所需头文件:#include<unistd.h>
函数原型: ssize_t write(int fd,void *buf,size_t count)
函数传入值:
fd: 文件描述符
Buf :指定存储器写入数据的缓冲区
Count :指定读出的字节数
函数返回值:成功:已写的字节数 -1 :出错
5 、Lseek 函数语法要点:
所需头文件
4000
:#include<unistd.h>
#include<sys/types.h>
函数原型:off_t lseek(int fd,off_t offset,int whence)
函数传入值:
fd: 文件描述符
Offset :偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)
Whence :当前位置的基点:
SEEK_SET :当前位置为文件开头,新位置为偏移量的大小
SEEK_CUR :当前位置为文件指针位置,新位置为当前位置加上偏移量
SEEK_END :当前位置为文件的结尾,新位置为文件的大小加上偏移量大小
函数使用实例:
/**/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char *buf="Hello! I'm writing to this file!";
char buf_r[11];
int fd,size,len;
len = strlen(buf);
buf_r[10] = '/0';
/* 首先调用open 函数,并指定相应的权限*/
if ((fd = open("hello.c", O_CREAT | O_TRUNC | O_RDWR,0666 ))<0) {
perror("open:");
exit(1);
} else
printf("open and create file:hello.c %d OK/n",fd);
/* 调用write 函数,将buf 中的内容写入到打开的文件中*/
if ((size = write( fd, buf, len)) < 0){
perror("write:");
exit(1);
} else
printf("Write:%s OK/n",buf);
/* 调用lseek 函数将文件指针移动到文件起始,并读出文件中的10 个字节
*/
lseek(fd, 0, SEEK_SET );
if ((size = read( fd, buf_r, 10))<0) {
perror("read:");
exit(1);
} else
printf("read form file:%s OK/n",buf_r);
if ( close(fd) < 0 ) {
perror("close:");
exit(1);
} else
printf("Close hello.c OK/n");
return 0;
}
二、C 语言库函数
C 库函数的文件操作实际上是独立于具体的操作系统平台的,不管是在DOS 、Windows 、Linux 还是在VxWorks 中都是这些函数:
创建和打开
FILE *fopen(const char *path, const char *mode); |
标志 | 含义 |
r, rb | 以只读方式打开 |
w, wb | 以只写方式打开。如果文件不存在,则创建该文件,否则文件被截断 |
a, ab | 以追加方式打开。如果文件不存在,则创建该文件 |
r+, r+b, rb+ | 以读写方式打开 |
w+, w+b, wh+ | 以读写方式打开。如果文件不存在时,创建新文件,否则文件被截断 |
a+, a+b, ab+ | 以读和追加方式打开。如果文件不存在,创建新文件 |
读写
C 库函数支持以字符、字符串等为单位,支持按照某中格式进行文件的读写,这一组函数为:
int fgetc(FILE *stream); int fputc(int c, FILE *stream); char *fgets(char *s, int n, FILE *stream); int fputs(const char *s, FILE *stream); int fprintf(FILE *stream, const char *format, ...); int fscanf (FILE *stream, const char *format, ...); size_t fread(void *ptr, size_t size, size_t n, FILE *stream); size_t fwrite (const void *ptr, size_t size, size_t n, FILE *stream); |
数。在读取的字段数小于num 时,可能是在函数调用时出现错误,也可能是读到文件的结尾。所以要通过调用feof() 和ferror() 来判断。
write() 实现从缓冲区ptr 所指的数组中把n 个字段写到流stream 中,每个字段长为size 个字节,返回实际写入的字段数。
另外,C 库函数还提供了读写过程中的定位能力,这些函数包括
int fgetpos(FILE *stream, fpos_t *pos); int fsetpos(FILE *stream, const fpos_t *pos); int fseek(FILE *stream, long offset, int whence); 等。 |
利用C 库函数关闭文件依然是很简单的操作:
int fclose (FILE *stream); |
#include <stdio.h>
#define LENGTH 100
main()
{
FILE *fd;
char str[LENGTH];
fd = fopen("hello.txt", "w+"); /* 创建并打开文件 */
if (fd)
{
fputs("Hello, Everyone!", fd); /* 写入Hello,
Everyone!"
字符串 */
fclose(fd);
}
fd = fopen("hello.txt", "r");
fgets(str, LENGTH, fd); /* 读取文件内容 */
printf("%s/n", str);
fclose(fd);
}
三、
<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-f
d0bb
ont-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt;
text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} /* Page Definitions */ @page {mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->
f c n t l
函数有五种功能:
n
复制一个现存的描述符
, 新文件描述符作为函数值返
(c m d =
F_DUPFD )。
n
获得
/ 设置文件描述符标记
, 对应于 filedes
的文件描述符标志作为函数值返回.(
c m d = F_GETFD
或 F_SETFD
)。
n
获得
/ 设置文件状态标志,对应于 filedes
的文件状态标志作为函数值返回。(
c m d = F_GETFL 或
F_SETFL )。
n
获得
/ 设置异步
I / O 有权(
c m d = F_GETOWN 或
F_SETOWN )。
n
获得
/ 设置记录锁(
c m d = F_SETLK , F_SETLKW )。
#include <sys/types.h>
#include <unistd.h>
#include <fcnt1.h>
int fcnt1(int
filedes , int cmd ,... struct flock flockptr ) ;
struct flock
结构
ioctl
函数是
I / O 操作的杂物箱。不能用本章中其他函数表示的
I / O
操作通常都能用 i o c t l
表示。终端 I / O
是 ioctl 的最大使用方面,主要用于设备的
I / O
控制。
#include <unistd.h> /* SVR4 */
#include <sys/ioctl.h> /* 4.3+BSD * /
int ioctl(int
filedes , int request , . . . ) ;
返回:若出错则为
- 1
,若成功则为其他值
I/O
处理的五种模型
①
阻塞
I/O 模型:若所调用的
I/O 函数没有完成相关的功能就会使进程挂起,直到相关数据到达才会返回。如:终端、网络设备的访问。
②
非阻塞模型:当请求的
I/O 操作不能完成时,则不让进程休眠,而且返回一个错误。如:
open
、 read
、 write
访问。
③
I/O
多路转接模型:如果请求的 I/O 操作阻塞,且他不是真正阻塞
I/O
,而且让其中的一个函数等待,在这期间, I/O
还能进行其他操作。如: select
函数。
④
信号驱动
I/O 模型:在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动
I/O
。
⑤
异步
I/O 模型:在这种模型下,当一个描述符已准备好,可以启动
I/O
时,进程会通知内核。由内核进行后续处理,这种用法现在较少
#include <sys/types.h>/* fd_set data type */
#include <sys/time.h> /* struct timeval */
#include <unistd.h> /* function prototype might be here */
int select (int
numfds , fd_set *readfds ,
fd_set *writefds , fd_set *exceptfds , struct timeval *
timeout ) ;
返回:准备就绪的描述符数,若超时则为
0
,若出错则为 - 1
。
相关文章推荐
- Linux中.a,.la,.o,.so文件的意义和编程实现
- Linux 系统应用编程——文件I/O
- linux-C编程-文件操作
- linux历程--文件编程(系统调用)
- linux编程--将十六进制数据输出到指定文件里
- 文件编程(Linux---C)
- Linux下的C编程实战之文件系统编程
- Linux下一个C(编程入门.h档,.c档,而路多文件的调用)
- Linux系统编程_2_文件I/O(系统调用&库函数)
- Linux的那些事儿(6)----Linux编程之文件和目录
- Linux-C高级编程(1)文件操作(二)
- linux系统编程之文件IO
- Linux 内核编程之文件系统(一)
- Linux系统编程---文件I/O思想
- Linux学习记录--文件管理相关系统编程
- Linux下C编程-----IO/文件操作/内存映射 实现简单记录存储(3)
- Linux:文件编程
- LinuxI/O文件编程终端控制
- UNIX/LINUX编程学习之文件I/O
- LInux 编程基础学习笔记 持续ing 文件读写