03Linux输入输出与文件.docx
- 文档编号:4687006
- 上传时间:2022-12-07
- 格式:DOCX
- 页数:45
- 大小:45.47KB
03Linux输入输出与文件.docx
《03Linux输入输出与文件.docx》由会员分享,可在线阅读,更多相关《03Linux输入输出与文件.docx(45页珍藏版)》请在冰豆网上搜索。
03Linux输入输出与文件
LINUX输入输出与文件
1.基于文件指针的文件操作(缓冲)
linux的文件和文件描述符
linux中对目录和设备的操作都是文件操作,文件分为普通文件,目录文件,链接文件和设备文件。
普通文件:
也称磁盘文件,并且能够进行随机的数据存储(能够自由seek定位到某一个位置);
管道:
是一个从一端发送数据,另一端接收数据的数据通道;
目录:
也称为目录文件,它包含了保存在目录中文件列表的简单文件。
设备:
该类型的文件提供了大多数物理设备的接口。
它又分为两种类型:
字符型设备和块设备。
字符型设备一次只能读出和写入一个字节的数据,包括调制解调器、终端、打印机、声卡以及鼠标;块设备必须以一定大小的块来读出或者写入数据,块设备包括CD-ROM、RAM驱动器和磁盘驱动器等,一般而言,字符设备用于传输数据,块设备用于存储数据。
符号链接:
类似于Windows的快捷方式和Linux里的别名,指包含到达另一个文件路径的文件。
:
在Linux中,套接字也可以当作文件来进行处理。
基于文件指针的文件操作函数是ANSI标准函数库的一部分。
1.1.文件的创建,打开与关闭
原型为:
#include
FILE*fopen(constchar*pach,constchar*mode);//文件名模式
intfclose(FILE*stream);
fopen以mode的方式打开或创建文件,如果成功,将返回一个文件指针,失败则返回NULL.
fopen创建的文件的访问权限将以0666与当前的umask结合来确定。
mode的可选模式列表
模式
读
写
位置
截断原内容
创建
rb
Y
N
文件头
N
N
r+b
Y
Y
文件头
N
N
wb
N
Y
文件头
Y
Y
w+b
Y
Y
文件头
Y
Y
ab
N
Y
文件尾
N
Y
a+b
Y
Y
文件尾
N
Y
在Linux系统中,mode里面的’b’(二进制)可以去掉,但是为了保持与其他系统的兼容性,建议不要去掉。
ab和a+b为追加模式,在此两种模式下,无论文件读写点定位到何处,在写数据时都将是在文件末尾添加,所以比较适合于多进程写同一个文件的情况下保证数据的完整性。
1.2.读写文件
基于文件指针的数据读写函数较多,可分为如下几组:
数据块读写:
#include
size_tfread(void*ptr,size_tsize,size_tnmemb,FILE*stream);
size_tfwrite(void*ptr,size_tsize,size_tnmemb,FILE*stream);
fread从文件流stream中读取nmemb个元素,写到ptr指向的内存中,每个元素的大小为size个字节。
fwrite从ptr指向的内存中读取nmemb个元素,写到文件流stream中,每个元素size个字节。
所有的文件读写函数都从文件的当前读写点开始读写,读写完以后,当前读写点自动往后移动size*nmemb个字节。
格式化读写:
#include
intprintf(constchar*format,...);//相当于fprintf(stdout,format,…);
intscanf(constchar*format,…);
intfprintf(FILE*stream,constchar*format,...);
intfscanf(FILE*stream,constchar*format,…);
intsprintf(char*str,constchar*format,...);//eg:
sprintf(buf,”thestringis;%s”,str);
intsscanf(char*str,constchar*format,…);
以f开头的将格式化后的字符串写入到文件流stream中
以s开头的将格式化后的字符串写入到字符串str中
单个字符读写:
使用下列函数可以一次读写一个字符
#include
intfgetc(FILE*stream);
intfputc(intc,FILE*stream);
intgetc(FILE*stream);等同于fgetc(FILE*stream)
intputc(intc,FILE*stream);等同于fputc(intc,FILE*stream)
intgetchar(void);等同于fgetc(stdin);
intputchar(intc);等同于fputc(intc,stdout);
getchar和putchar从标准输入输出流中读写数据,其他函数从文件流stream中读写数据。
字符串读写:
char*fgets(char*s,intsize,FILE*stream);
intfputs(constchar*s,FILE*stream);
intputs(constchar*s);等同于fputs(constchar*s,intsize,stdout);
char*gets(char*s);等同于fgets(constchar*s,intsize,stdin);
fgets和fputs从文件流stream中读写一行数据;
puts和gets从标准输入输出流中读写一行数据。
fgets可以指定目标缓冲区的大小,所以相对于gets安全,但是fgets调用时,如果文件中当前行的字符个数大于size,则下一次fgets调用时,将继续读取该行剩下的字符,fgets读取一行字符时,保留行尾的换行符。
fputs不会在行尾自动添加换行符,但是puts会在标准输出流中自动添加一换行符。
文件定位:
文件定位指读取或设置文件当前读写点,所有的通过文件指针读写数据的函数,都是从文件的当前读写点读写数据的。
常用的函数有:
#include
intfeof(FILE*stream);//通常的用法为while(!
feof(fp))
intfseek(FILE*stream,longoffset,intwhence);//设置当前读写点到偏移whence长度为offset处
longftell(FILE*stream);//用来获得文件流当前的读写位置
voidrewind(FILE*stream);//把文件流的读写位置移至文件开头fseek(fp,0,SEEK_SET);
feof判断是否到达文件末尾的下一个(注意到达文件末尾之后还会做一次)
fseek设置当前读写点到偏移whence长度为offset处,whence可以是:
SEEK_SET(文件开头0)
SEEK_CUR(文件当前位置1)
SEEK_END(文件末尾2)
ftell获取当前的读写点
rewind将文件当前读写点移动到文件头
注:
基于文件指针的文件操作请参考《C语言文件操作常用函数详解.doc》
1.3.目录操作
改变目录或文件的访问权限
#include
intchmod(constchar*path,mode_tmode);//mode形如:
0777
path参数指定的文件被修改为具有mode参数给出的访问权限。
获取、改变当前目录:
原型为:
#include
char*getcwd(char*buf,size_tsize);//获取当前目录,相当于pwd命令
intchdir(constchar*path);//修改当前目录,即切换目录,相当于cd命令
其中getcwd()函数:
将当前的工作目录绝对路径复制到参数buf所指的内存空间,参数size为buf的空间大小.在调用此函数时,buf所指的内存空间要足够大,若工作目录绝对路径的字符串长度超过参数size大小,则回值NULL,errno的值则为ERANGE。
倘若参数buf为NULL,getcwd()会依参数size的大小自动配置内存(使用malloc()),如果参数size也为0,则getcwd()会依工作目录绝对路径的字符串程度来决定所配置的内存大小,进程可以在使用完此字符串后自动利用free()来释放此空间。
所以常用的形式:
getcwd(NULL,0);
chdir()函数:
用来将当前的工作目录改变成以参数path所指的目录
Example:
#include
main()
{
chdir(“/tmp”);
printf(“currentworkingdirectory:
%s\n”,getcwd(NULL,0));
}
创建和删除目录:
原型为:
#include
#include
#include
intmkdir(constchar*pathname,mode_tmode);//创建目录,mode是目录权限,没用
intrmdir(constchar*pathname);//删除空目录
获取目录信息:
原型为:
#include
#include
DIR*opendir(constchar*name);//打开一个目录
structdirent*readdir(DIR*dir);//读取目录的一项信息,并返回该项信息的结构体指针
voidrewinddir(DIR*dir);//重新定位到目录文件的头部
voidseekdir(DIR*dir,off_toffset);//用来设置目录流目前的读取位置
off_ttelldir(DIR*dir);//返回目录流当前的读取位置
intclosedir(DIR*dir);//关闭目录文件
读取目录信息的步骤为:
●用opendir函数打开目录;
●使用readdir函数迭代读取目录的内容,如果已经读取到目录末尾,又想重新开始读,则可以使用rewinddir函数将文件指针重新定位到目录文件的起始位置;
●用closedir函数关闭目录
opendir()用来打开参数name指定的目录,并返回DIR*形态的目录流,和文件操作函数open()类似,接下来对目录的读取和搜索都要使用此返回值。
函数失败则返回NULL;
readdir()函数用来读取目录的信息,并返回一个结构体指针,该指针保存了目录的相关信息。
有错误发生或者读取到目录文件尾则返回NULL;dirent结构体如下:
structdirent
{
ino_td_ino;/*inodenumber(此目录进入点的inode)*/
off_td_off;/*offsettothenextdirent(目录开头到进入点的位移*/
unsignedshortd_reclen;/*lengthofthisrecord(目录名的长度)*/
unsignedchard_type;/*typeoffile(所指的文件类型)*/
chard_name[256];/*filename(文件名)*/
};
seekdir()函数用来设置目录流目前的读取位置,再调用readdir()函数时,便可以从此新位置开始读取。
参数offset代表距离目录文件开头的偏移量。
telldir()函数用来返回目录流当前的读取位置。
示例:
#include
#include
#include
intmain(intargc,char*argv[])
{
structdirent*pDirInfo;
DIR*pDir;
if(argc<2)
pDir=opendir(".");
else
pDir=opendir(argv[1]);
if(NULL==pDir)
{
perror("opendirfail!
");
return-1;
}
while((pDirInfo=readdir(pDir))!
=NULL)
printf("%s\n",pDirInfo->d_name);
closedir(pDir);
return0;
}
Example:
以树形结构的形式输出指定目录下面的所有文件
#include
#include
#include
#include
#include
#include
voidprintdir(char*dir,intdepth)
{
DIR*dp=opendir(dir);
if(NULL==dp)
{
fprintf(stderr,"cannotopendirectory:
%s\n",dir);
return;
}
chdir(dir);
structdirent*entry;
structstatstatbuf;
while((entry=readdir(dp))!
=NULL)
{
stat(entry->d_name,&statbuf);
if(S_ISDIR(statbuf.st_mode))
{
if(strcmp(".",entry->d_name)==0||strcmp("..",entry->d_name)==0)
continue;
printf("%*s%s/\n",depth,"",entry->d_name);
printdir(entry->d_name,depth+4);
}
else
printf("%*s%s\n",depth,"",entry->d_name);
//printf(“%*s”,4,”*”);该函数表示输出“___*”,前面输出3个空格。
//如果是printf(“%*s”,4,“**”);则表示输出“__**”,前面输出2个空格。
}
chdir("..");
closedir(dp);
}
intmain(intargc,char*argv[])
{
char*topdir,pwd[2]=".";
if(argc<2)
topdir=pwd;
else
topdir=argv[1];
printf("Directoryscanof%s\n",topdir);
printdir(topdir,0);
printf("done.\n");
exit(0);
}
1.4.标准输入/输出流
在进程一开始运行,就自动打开了三个对应设备的文件,它们是标准输入、输出、错误流,分别用全局文件指针stdin、stdout、stderr表示,stdin具有可读属性,缺省情况下是指从键盘的读取输入,stdout和stderr具有可写属性,缺省情况下是指向屏幕输出数据。
示例:
#include
#include
intmain()
{
charszBuf[32];
printf("Inputstring:
");//向屏幕输出一字符串
fgets(szBuf,sizeof(szBuf),stdin);//从键盘读入一行字符串
fprintf(stdout,"Thestringis:
%s",szBuf);//向屏幕输出一行字符串
return0;
}
2.基于文件描述符的文件操作(非缓冲)
2.1.文件描述符
内核为每个进程维护一个已打开文件的记录表,文件描述符是一个较小的正整数(0—1023),它代表记录表的一项,通过文件描述符和一组基于文件描述符的文件操作函数,就可以实现对文件的读、写、创建、删除等操作。
常用基于文件描述符的函数有open(打开)、creat(创建)、close(关闭)、read(读取)、write(写入)、ftruncate(改变文件大小)、lseek(定位)、fsync(同步)、fstat(获取文件状态)、fchmod(权限)、flock(加锁)、fcntl(控制文件属性)、dup(复制)、dup2、select和ioctl。
基于文件描述符的文件操作并非ANSIC的函数。
如果不清楚某个函数的具体实现形式,可以通过下面的方式查询
man函数名查看该函数的帮助。
如果要复制里面的内容,按Ctrl+Insert键,再粘贴的话用:
Shift+Insert键。
2.2.打开、创建和关闭文件
open和creat都能打开和创建函数,原型为
#include
#include
#include
intopen(constchar*pathname,intflags);//文件名打开方式
intopen(constchar*pathname,intflags,mode_tmode);//文件名打开方式权限
intcreat(constchar*pathname,mode_tmode);//文件名权限//现在已经不常用了
creat函数等价于open(pathname,O_CREAT|O_TRUNC|O_WRONLY,mode);
open()函数出错时返回-1,相关参数如下:
flags和mode都是一组掩码的合成值,flags表示打开或创建的方式,mode表示文件的访问权限。
flags的可选项有
掩码
含义
O_RDONLY
以只读的方式打开
O_WRONLY
以只写的方式打开
O_RDWR
以读写的方式打开
O_CREAT
如果文件不存在,则创建文件
O_EXCL
仅与O_CREAT连用,如果文件已存在,则强制open失败
O_TRUNC
如果文件存在,将文件的长度截至0
O_APPEND
已追加的方式打开文件,每次调用write时,文件指针自动先移到文件尾,用于多进程写同一个文件的情况。
O_NONBLOCK
非阻塞方式打开,无论有无数据读取或等待,都会立即返回进程之中。
O_NODELAY
非阻塞方式打开
O_SYNC
同步打开文件,只有在数据被真正写入物理设备设备后才返回
mode的可选项有:
S_IRWXU00700权限,代表该文件所有者具有可读、可写及可执行的权限。
S_IRUSR或S_IREAD,00400权限,代表该文件所有者具有可读取的权限。
S_IWUSR或S_IWRITE,00200权限,代表该文件所有者具有可写入的权限。
S_IXUSR或S_IEXEC,00100权限,代表该文件所有者具有可执行的权限。
S_IRWXG00070权限,代表该文件用户组具有可读、可写及可执行的权限。
S_IRGRP00040权限,代表该文件用户组具有可读的权限。
S_IWGRP00020权限,代表该文件用户组具有可写入的权限。
S_IXGRP00010权限,代表该文件用户组具有可执行的权限。
S_IRWXO00007权限,代表其他用户具有可读、可写及可执行的权限。
S_IROTH00004权限,代表其他用户具有可读的权限
S_IWOTH00002权限,代表其他用户具有可写入的权限。
S_IXOTH00001权限,代表其他用户具有可执行的权限。
但是通常采用直接赋数值的形式,如:
intfd=open(“1.txt”,O_WRONLY|O_CREAT,0755);//表示给755的权限
if(-1==fd)
{
perror("openfailed!
\n");
exit(-1);
}
注意:
LINUX中基于文件描述符的open函数,对于一个不存在的文件,不能通过O_WRONLY的方式打开,必须加上O_CREAT选项。
close用于文件的关闭:
intclose(intfd);//fd表示文件描述词,是先前由open或creat创建文件时的返回值。
文件使用完毕后,应该调用close关闭它,一旦调用close,则该进程对文件所加的锁全都被释放,并且使文件的打开引用计数减1,只有文件的打开引用计数变为0以后,文件才会被真正的关闭。
2.3.读写文件
读写文件的函数原型为:
#include
ssize_tread(intfd,void*buf,size_tcount);//文件描述词缓冲区长度
ssize_twrite(intfd,constvoid*buf,size_tcount);
对于read和write函数,出错返回-1,读取完了之后,返回0,其他情况返回读写的个数。
Example:
将aaa.txt中的内容复制到bbb.txt中,其中bbb.txt起初不存在。
#include
#include
#include
#include
#include
#include
#include
#defineFILENAME1"./aaa.txt"//用宏定义文件的路径,可以实现一改都改
#defineFILENAME2"./bbb.txt"
main()
{
charbuf[512]={0};
intfo1=open(FILENAME1,O_RDONLY);//fo1,fo2都是文件描述词
intfo2=creat(FILENAME2,0755);//创建文件
//intfo2=open(FILENAME2,O_WRONLY|O_CREAT);
if((-1==fo1)||(-1==fo2))
{
perror("openfailed!
\n");
//用于输出错误信息.类似于:
fputs(”openfailed\n”,stderr);
exit(-1);
}
intfr=0;
while((fr=read(fo1,buf,sizeof(buf)))>0)
//如果rea
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 03 Linux 输入输出 文件