linux 文件读写
2009-09-07 17:32
471 查看
两种I/O文件函数
fopen
ANSI 标准文件I/O,基于低层次I/O
open
低层次I/O
ANSI I/O本质
DOS/WINDOWS平台,MS DOS 文件读写, 汇编语言编写
LINUX平台,unix/linux文件读写,C语言编写
文件类型FILE
包含一个指针
包含一个stream (C语言把文件看成stream
)
file open
r
Open text file for reading
r+
Open for reading and writing
w Truncate
file to zero length or create text file for writing
w+
The file is created if it does not exist,
otherwise it is truncated
a
Open for
appending (writing at end of file).
The stream is positioned at the end of the file.
fopen三种基本模式r,w,a只允许针对文本文
件
C语言允许最大同时打开16个文件
实际只允许同时打开13个文件,因为有另外三个标准文件stdout,stdin,stderr
文件读写的基本语句
顺序读文件(按字符)
while((c=fgetc(stream))!=
EOF
)
printf("%c",c);
每读一个字符,文件指针会(自动)移动一格
顺序读文件(按字符串)-------从一个文件依次读一行,直到读到NULL
char record[100],*re;
while ((re=fgets(record,100
,stream))!=NULL
)
printf("%s",record);
读一行,以回车换行作为读一行的尾部标志
从文件中fgets的字符串是读一行,即包括了回车
所以printf("%s")即可,不用"%s/n",因为字符串里面带了回车了
这也是个漏洞,字符串里带了回车
所以非常不利于字符串比对strcmp
scanf读文件,文件指针不移动,需要手动fseek移指针
文件读写到文件末尾
文件指针会指到NULL
(而不是EOF,EOF不是地址,而是结尾字符
)
fput(),fgetc()会返回EOF
fgets()会返回NULL
linux和DOS对文件的结束判别是不同的
linux没有文件结束符
,是以目录项的文件长度做为文件结束的判别手段
DOS看0x1a文件结束符
linux 和DOS的换行符的区别
读文件时, 不能用unsigned char c作为返回值,
因为EOF不在unsigned范围内
char c;
c=getc(stream);
fscanf读文本文件里面的数字,既可以直接用%c,也可以用%d
只不过这两个3,1,一个是实际值3,1,一个是'3','1'
几个常见特殊字符的整型数字
TAB字符处理要小心,经过到记事本copy/paste后,TAB键被转化成几个空格
fgets字符串指针改成字符串数组,消灭了Segmentation
fault错误
一个普通的显示文件内容
的函数
按SED/AWK原理,读记录/行的函数——是从文件中取第recno行
按SED/AWK原理,读字段的函数——从字符串中取第valueno字段
fputs(stren,streamwrite)
写入的串不带回车,fprintf(strea,"%s",str)写入的串也不带回车,所以,要写入文件回车,必须写入/n
文件很难进行“修改写”,建议文件追加
最好的办法就是写到新文件
,或写到stdout再重定向入文件。然后把新文件覆盖旧文件
writefile(char *tmpfilename,char
*srcfilename,struct Filerecord *frs,int
frsi)-------修改文件的函数
实际是从 srcfile读出文件
把其中符合frs[j].recno的行,修改成frs[j].record
其他行不变,仍旧用srcfile读出的行
然后把这些行重新写入一个新文件tmpfile
fseek(stream,offset,mode)的三个mode
SEEK_SET:从开头数第几个offset
SEEK_CUR: 从当前数第几个offset
SEEK_END: 从结尾倒数第几个offset
文件指针位置是从0(文件头)开始算的
fseek(stream,0,SEEK_SET);
int ftell(FILE
*stream)
返回stream的当前指针位置
简单的取文件大小size的操作
取文件大小的操作对读写文件很有用,因为读写文件很不好判定文件结尾。
文件例子
fopen
ANSI 标准文件I/O,基于低层次I/O
open
低层次I/O
ANSI I/O本质
DOS/WINDOWS平台,MS DOS 文件读写, 汇编语言编写
LINUX平台,unix/linux文件读写,C语言编写
文件类型FILE
包含一个指针
包含一个stream (C语言把文件看成stream
)
file open
r
Open text file for reading
r+
Open for reading and writing
w Truncate
file to zero length or create text file for writing
w+
The file is created if it does not exist,
otherwise it is truncated
a
Open for
appending (writing at end of file).
The stream is positioned at the end of the file.
fopen三种基本模式r,w,a只允许针对文本文
件
C语言允许最大同时打开16个文件
实际只允许同时打开13个文件,因为有另外三个标准文件stdout,stdin,stderr
文件读写的基本语句
1 | #include <stdio.h> FILE *stream; 注意类型是大写 |
2 | if((stream=fopen("testtmp","r+"))==NULL) { printf("open file error/n"); return; } |
3 | int ret; if ((ret=fclose(stream))==-1) printf("close file error/n"); |
while((c=fgetc(stream))!=
EOF
)
printf("%c",c);
每读一个字符,文件指针会(自动)移动一格
顺序读文件(按字符串)-------从一个文件依次读一行,直到读到NULL
char record[100],*re;
while ((re=fgets(record,100
,stream))!=NULL
)
printf("%s",record);
读一行,以回车换行作为读一行的尾部标志
从文件中fgets的字符串是读一行,即包括了回车
所以printf("%s")即可,不用"%s/n",因为字符串里面带了回车了
这也是个漏洞,字符串里带了回车
所以非常不利于字符串比对strcmp
scanf读文件,文件指针不移动,需要手动fseek移指针
fseek(stream,3,SEEK_SET); fscanf(stream,"%c",&c[0]); fseek(stream,11,SEEK_SET); fscanf(stream,"%c",&c[1]); |
文件指针会指到NULL
(而不是EOF,EOF不是地址,而是结尾字符
)
fput(),fgetc()会返回EOF
fgets()会返回NULL
linux和DOS对文件的结束判别是不同的
linux没有文件结束符
,是以目录项的文件长度做为文件结束的判别手段
DOS看0x1a文件结束符
linux 和DOS的换行符的区别
linux | DOS |
0x0a 即 10 即’/n’ 即LF | CR,LF双码 |
因为EOF不在unsigned范围内
char c;
c=getc(stream);
fscanf读文本文件里面的数字,既可以直接用%c,也可以用%d
用%c(char)读,可以读出3,1 | 用%d(int)读,也可以读出3,1 |
fseek(stream,3,SEEK_SET); fscanf(stream,"%c",&c[0]); fseek(stream,11,SEEK_SET); fscanf(stream,"%c",&c[1]); | fseek(stream,ii,SEEK_SET); fscanf(stream,"%d",&ln[i].frame); fseek(stream,ii+8,SEEK_SET); fscanf(stream,"%d",&ln[i].line); |
几个常见特殊字符的整型数字
char | int |
空格' ' | 32 |
TAB键 | 9 |
回车 | 10 |
文件结束EOF | -1 |
字符串结束符号 | 数字0(不是字符‘0’) |
for(;str[i]==' '||str[i]==' ';i++); |
但经过到记事本copy/paste后,TAB键被转化成几个空格 所以系统总报warning: tmp.c:58: warning: comparison is always false due to limited range of data type tmp.c:59:27: warning: character constant too long for its type |
fault错误
char *re,*rec; re=fgets(rec,100,srcstream); 出Segmentation fault错误 |
改成 char *re,rec[100]; re=fgets(rec,100,srcstream); 错误消失 |
的函数
printfile(FILE *stream,char *filename,int or) { int i,re; char rec[100]; FILE *tmpstream; if (or) { if((tmpstream=fopen(filename,"r"))==NULL) { printf("open file error/n"); return 0; } for(i=0;(re=fgets(rec,100,tmpstream))!=NULL;i++) printf("[%d]:%s",i,rec); 显示文件内容时,每行加行号 if ((re=fclose(tmpstream))==-1) printf("close file error/n"); } else { fseek(stream,0,SEEK_SET); for(i=0;(re=fgets(rec,100,stream))!=NULL;i++) printf("[%d]:%s",i,rec); } } |
printfile(NULL,"testtmp.tmp",1 ); [0]:total 48 [1]:1 macg macg 3301 Jan 16 02:16 file.c [2]:-rw-rw-r-- 1 macg macg 52 Jan 16 02:19 Makefile [3]:1 macg macg 0 Jan 16 02:56 testtmp [4]:this is a testthis is a testthis is a testthis is a testthis is a testth [5]:-rw-rw-r-- 1 macg macg 1428 Jan 16 02:56 tmp.o |
if((stream=fopen("testtmp","r+"))==NULL) { printf("open file error/n"); return 0; } printfile(stream ,NULL,0 ); [0]:total 48 [1]:-rw-rw-r-- 1 macg macg 3301 Jan 16 02:16 file.c [2]:-rw-rw-r-- 1 macg macg 52 Jan 16 02:19 Makefile [3]: -rw-rw-r-- 1 macg macg 0 Jan 16 02:56 testtmp [4]:this is a testthis is a testthis is a testthis is a testthis is a testth [5]:-rw-rw-r-- 1 macg macg 1428 Jan 16 02:56 tmp.o |
int getrecord(char *rec,FILE *stream,int recno) { int i,ret; char *re; for(i=0;i<=recno;i++) re=fgets(rec,100,stream); 数行,并一边数一边读行 if(re==NULL) return 0; 如果所取行超过文件长度,则返回0 else return 1; } |
getrecord(record,stream,4); 取记录/行,取文件第四行 printf("record is %s/n",record); printf("/n/n/n"); |
$ ./tmp record is -rw-rw-r-- 1 macg macg 0 Jan 16 02:56 testtmp |
int getvalue(char *str,int valueno,char *value) { int i,j,vali; 数字段 for(i=0,vali=0;vali<valueno;vali++) { for(;str[i]==' '||str[i]==9;i++); for(;str[i]!=' '&&str[i]!=9&&str[i]!=0;i++); if(str[i]==0) return 0; } 取字段 for(;str[i]==' '||str[i]==9;i++); for(j=0;str[i]!=' '&&str[i]!=9&&str[i]!=0;i++,j++) { value[j]=str[i]; } value[j]=0; } |
for(i=0;i<20;i++) { if(getvalue(record,i,val)) printf("no %d is %s/n",i,val); } |
$ ./tmp record is -rw-rw-r-- 1 macg macg 0 Jan 16 02:56 testtmp 事先故意编辑过此行,加了几个TAB,连行尾也含TAB no 0 is -rw-rw-r-- no 1 is 1 no 2 is macg no 3 is macg no 4 is 0 no 5 is Jan no 6 is 16 no 7 is 02:56 no 8 is testtmp no 9 is |
写入的串不带回车,fprintf(strea,"%s",str)写入的串也不带回车,所以,要写入文件回车,必须写入/n
fputs(stren,streamwrite); cat aaa.txt 008421aa |
fprintf(streamwrite,"%s/n ",stren); cat aaa.txt 008421 aa |
最好的办法就是写到新文件
,或写到stdout再重定向入文件。然后把新文件覆盖旧文件
writefile(char *tmpfilename,char
*srcfilename,struct Filerecord *frs,int
frsi)-------修改文件的函数
实际是从 srcfile读出文件
把其中符合frs[j].recno的行,修改成frs[j].record
其他行不变,仍旧用srcfile读出的行
然后把这些行重新写入一个新文件tmpfile
writefile(char *tmpfilename,char *srcfilename,struct Filerecord *frs,int frsi o tmpfilename 新文件名 o srcfilename 旧文件名 o struct Filerecord *frs 放置要修改的行的结构体数组 struct Filerecord{ char record[100]; int recno; }; struct Filerecord fr[20]; o frsi 结构体数组的元素数量 |
writefile(char *tmpfilename,char *srcfilename,struct Filerecord *frs,int frsi) { int no,ret,i,j,bol; char *re,rec[100]; FILE *tmpstream,*srcstream; if((tmpstream=fopen(tmpfilename,"w+ "))==NULL) 写入一个新 { printf("open file error/n"); return 0; } if((srcstream=fopen(srcfilename,"r"))==NULL) { printf("open file error/n"); return 0; } for(no=0;(re=fgets(rec,100,srcstream))!=NULL;no++) { for(j=0,bol=1;j<frsi&&bol;j++) { if(no==frs[j].recno) { bol=0; strcpy(rec,frs[j].record); } } fputs(rec,tmpstream); } if ((ret=fclose(tmpstream))==-1) printf("close file error/n"); if ((ret=fclose(srcstream))==-1) printf("close file error/n"); } |
例子:去掉文件中行的TAB键和起首空格或TAB 执行: 读出原文件每行,checkinvaild() ,看是否含有TAB,起首空格/TAB 如果确实有,就对此行处理,重新组合,去掉TAB,起首空格/TAB,然后写入struct person fr[20]数组 writefile("testtmp.tmp","testtmp",fr,fri); ------------------the sick file---------------------------------------- [0]:total 48 [1]:-rw-rw-r-- 1 macg macg 3301 Jan 16 02:16 file.c [2]:-rw-rw-r-- 1 macg macg 52 Jan 16 02:19 Makefile [3]: -rw-rw-r-- 1 macg macg 0 Jan 16 02:56 testtmp [4]:this is a testthis is a testthis is a testthis is a testthis is a testth [5]:-rw-rw-r-- 1 macg macg 1428 Jan 16 02:56 tmp.o --------------------modify line-------------------------------------- fri is 2,the new line is following: [1]row:1 macg macg 3301 Jan 16 02:16 file.c [3]row:1 macg macg 0 Jan 16 02:56 testtmp -------------------new file--------------------------------------- [0]:total 48 [1]:1 macg macg 3301 Jan 16 02:16 file.c [2]:-rw-rw-r-- 1 macg macg 52 Jan 16 02:19 Makefile [3]:1 macg macg 0 Jan 16 02:56 testtmp [4]:this is a testthis is a testthis is a testthis is a testthis is a testth [5]:-rw-rw-r-- 1 macg macg 1428 Jan 16 02:56 tmp.o |
SEEK_SET:从开头数第几个offset
SEEK_CUR: 从当前数第几个offset
SEEK_END: 从结尾倒数第几个offset
文件指针位置是从0(文件头)开始算的
fseek(stream,0,SEEK_SET);
int ftell(FILE
*stream)
返回stream的当前指针位置
简单的取文件大小size的操作
fseek(stream,0,SEEK_END);先将指针指向文件尾部 ret=ftell(stream); 再获得指针所指的当前地址 这个指向文件尾部的指针地址就是文件大小 |
文件例子
$ cat tmp.c #define DEBUG 0 #include <stdio.h> #include <string.h> #include <unistd.h> struct Filerecord{ char record[100]; int recno; }; main() { char directory[100]; #ifdef SYST getcwd(directory,100); printf("current directory is %s/n",directory); #endif filemanage(); } filemanage() { int i,j,fri,ret; char record[100],val[50],modi_rec[100]; FILE *stream; struct Filerecord fr[20]; if((stream=fopen("testtmp","r+"))==NULL) { printf("open file error/n"); return 0; } printf("------------------the sick file-----------------------/n"); printfile(stream,NULL,0); for(i=0,fri=0;getrecord(record,stream,i);i++) { if (DEBUG) printf("no %d row is:%s/n",i,record); if(ret=findinvalid(record)) { for(j=0;getvalue(record,j,val);j++) { if (DEBUG) printf("no %d's val is %s %d/n",j,val,val[0]); if(j==1) strcpy(modi_rec,val); if(j>1) { strcat(modi_rec," "); strcat(modi_rec,val); } } fr[fri].recno=i; strcpy(fr[fri].record,modi_rec); if (DEBUG) printf("fr[%d] is %d %s/n",fri,fr[fri].recno,fr[fri].record); fri++; } if (DEBUG) printf("---------------------------------/n"); } printf("--------------------modify line--------------------/n"); printf("fri is %d,the new line is following: /n",fri); for(i=0;i<fri;i++) printf("[%d]row:%s",fr[i].recno,fr[i].record); if ((ret=fclose(stream))==-1) { printf("close file error/n"); return 0; } writefile("testtmp.tmp","testtmp",fr,fri); printf("-------------------new file-----------------/n"); printfile(NULL,"testtmp.tmp",1); } int findinvalid(char *str) { int i,ret; i=0; if(str[i]==' ') { if (DEBUG) printf("str[%d] == %d/n",i,str[i]); return 32; } for(i=0;str[i]!=9&&str[i]!=0;i++) ; if(str[i]==9) { if (DEBUG) printf("str[%d] == %d/n",i,str[i]); return 9; } else { if (DEBUG) printf("str[%d] == %d/n",i,str[i]); return 0; } } |
$ make gcc -g -c tmp.c tmp.c: In function 鈥榩rintfile鈥? tmp.c:158: warning: assignment makes integer from pointer without a cast tmp.c:158: warning: comparison between pointer and integer tmp.c:165: warning: assignment makes integer from pointer without a cast tmp.c:165: warning: comparison between pointer and integer gcc -o tmp tmp.o -g |
$ ./tmp ------------------the sick file---------------------- [0]:total 48 [1]:-rw-rw-r-- 1 macg macg 3301 Jan 16 02:16 file.c [2]:-rw-rw-r-- 1 macg macg 52 Jan 16 02:19 Makefile [3]: -rw-rw-r-- 1 macg macg 0 Jan 16 02:56 testtmp [4]:this is a testthis is a testthis is a testthis is a testthis is a testth [5]:-rw-rw-r-- 1 macg macg 1428 Jan 16 02:56 tmp.o --------------------modify line-------------------- fri is 2,the new line is following: [1]row:1 macg macg 3301 Jan 16 02:16 file.c [3]row:1 macg macg 0 Jan 16 02:56 testtmp -------------------new file------------------------- [0]:total 48 [1]:1 macg macg 3301 Jan 16 02:16 file.c [2]:-rw-rw-r-- 1 macg macg 52 Jan 16 02:19 Makefile [3]:1 macg macg 0 Jan 16 02:56 testtmp [4]:this is a testthis is a testthis is a testthis is a testthis is a testth [5]:-rw-rw-r-- 1 macg macg 1428 Jan 16 02:56 tmp.o |
相关文章推荐
- Linux系统如何查看及修改文件读写权限查看文件权限的语句:
- Linux/Unix C编程之系统函数文件读写 学习笔记
- linux 文件读写
- 关于linux和windows文件的读写
- linux内核读写文件
- Linux内存计数详解(读写文件时的缓存机制与windows不同,以致于读写大文件时cached值非常大且居高不下)
- Linux平台下利用系统接口函数按照行读写文件
- 文件I/O操作之文件的读写-基于Linux系统文件IO
- linux配置文件的读写及分析
- Linux文件定位读写—lseek、pread、pwrite
- linux读写文件速度测试
- Linux下文件读写操作一例(C标准库函数方式实现)
- Linux 服务器如何设置文件和文件夹的读写权限
- LINUX C 读写修改删除配置文件函数
- Linux系统下如何查看及修改文件读写权限
- linux创建文件的获取读写文件权限设置
- EXCEL文件读写 适用WINDOWS和LINUX
- Linux系统下如何查看及修改文件读写权限
- Linux 文件读写
- 【Linux】使用read、write、lseek函数实现文件读写操作