以只读方式打开文件,可移植性忠告...

作者: 编程  发布:2019-09-26

open, creat, close和unlink

除了暗中认可的科公输子入、标准输出和行业内部错误文件外,另外文件都必得在读或写在此之前显式地开垦。系统调用open与creat用于贯彻该作用。
open与眼下商议的fopen相似,分化的是,前面一个再次回到三个文书描述符,它仅仅只是多个int类型的数值。而后人重返一个文本指针。假如发生错误,open将回到-l。
#include <fcntl.h>
int fd;
int open(char *name, int flags, int perms);
fd = open(name, flags, perms);
与fopen一样,参数name是叁个分包文件名的字符串,第二个参数flags是多个int类型的值,它表达以何种方法张开文件,主要的多少个值如下所示:
O_LX570DONLY 以只读格局展开文件
O_WRONLY 以只写情势张开文件
O_途观DW奥德赛 以读写方式打开文件
在此地研究的open第多少个参数始终为0。

采纳create创立或遮盖已存在的旧文件:
int creat(char *name, int perms);
fd = creat(name, perms);
假如creat成功地创造了文件,它将回来三个文本描述符,不然重回-1。假设此文件已存在,creat将把该公文的尺寸截断为0,进而遗弃原先己有的始末使用creat创造二个已存在的文书不会招致错误
万一要开创的文件子虚乌有,则creat用参数pems钦定的权杖创制文件。在UNIX文件系统中,每一个文件对应贰个9比特的权力消息,它们各自我调控制文件的全部者、全体者组和其余成员对文件的读、写和实践访谈。由此,通过二个3位的八进制数就可方便地印证差别的权杖,举例,0755认证文件的持有者能够对它实行读、写和实践操作,而全部者组和其余成员只可以进展读和实行操作。

上面通过一个简化UNIX程序cp表达creat的用法,该程序将三个文本复制到另三个文本。目的文件的权位不是经过复制获得的,而是重新定义的:
#include<stdio.h>
#include<fcntl.h>
#include<stdarg.h>
#include"syscalls.h"
#define PERMS 0666 /* RW for owner, group, others */
void error(char *, ...);
/* cp: copy f1 to f2 */
main(int argc, char *argv[]) {
int f1, f2, n;
char buf[BUFSIZ];
if (argc != 3)
error("Usage: cp from to");
if ((f1 = open(argv[1], O_RDONLY, 0)) == 1)
error("cp: can't open %s", argv[1]);
if ((f2 = creat(argv[2], PERMS)) == 1)
error("cp: can't create %s, mode %03o", argv[2], PERMS);
while ((n = read(f1, buf, BUFSIZ)) > 0)
if (write(f2, buf, n) != n)
error("cp: write error on file %s", argv[2]);
return 0;
}
void error(char *fmt, ...) {
va_list args;
va_start(args, fmt);
fprintf(stderr, "error: ");
vprintf(stderr, fmt, args);
fprintf(stderr, "n");
va_end;
exit;
}
该程序成立的输出文件具备固定的权位0666,也可使用stat系统调用,能够赢得多少个已存在文件的格局,并将此方式赋值给它的别本。标准库函数vprintf数与printf函数类似,所例外的是,它用贰个参数取代了变长参数表,因而参数通过调用va_start宏进行开首化。一样,vfprintfvsprintf函数分别与fprintf和sprintf函数类似。

函数close 用来断开文件呈报符和已开荒文件之间的连天,并释放此文件描述符,以供其余文件使用。close函数与规范库中的fclose函数相呼应,但它无需排除缓冲区。

函数unlink(char *name)将文件name从文件系统中除去,它对应高璇规库函数remove

UNIX系统接口

在此间文件都以从头最先读的,那么一旦自身想从有个别地方比方第N个字节起始读取的时候该怎么操作呢,这里就必要选拔文件定位函数lseek

函数原型

函数原型告诉编写翻译器函数再次来到的数据类型,函数所要接收的参数个数,参数类型和参数顺序,编写翻译器用函数原型校验函数调用。
int maxinum(int, int, int);
这边大约了参数名,也能够带上参数名

函数原型另四个至关心爱慕要特色是强制调换参数类型,如正式库函数sqrt函数原型钦点了参数为double类型,但在调用时得以传递整型,这是因为编写翻译器依照函数原型,调用前将整型调换为double型了。借使不依照C语言的门类“提高法则”,参数类型转变大概会导致不科学的结果。

open, creat, close和unlink

    除了暗许的标准输入、标准输出和标准错误文件外,其它文件都必得在读或写此前显式地开采。系统调用open与creat用于完结该意义。
    open与这两天商酌的fopen相似,不一样的是,前面二个重返二个文书描述符,它仅仅只是一个int类型的数值。而前面一个再次回到三个文本指针。借使发生错误,open将重回-l。
#include <fcntl.h>
int fd;
int open(char *name, int flags, int perms);
fd = open(name, flags, perms);
与fopen一样,参数name是三个蕴含文件名的字符串,首个参数flags是二个int类型的值,它表明以何种措施展开文件,首要的多少个值如下所示:
    O_LacrosseDONLY                以只读格局打开文件
     O_WRONLY               以只写形式张开文件
    O_奇骏DW奥迪Q5          以读写格局展开文件
 在此间斟酌的open第1个参数始终为0。
 
动用create创造或掩盖已存在的旧文件:
int creat(char *name, int perms);
fd = creat(name, perms);
一旦creat成功地开创了文本,它将再次来到二个文书描述符,不然重返-1。假诺此文件已存在,creat将把该文件的长度截断为0,进而甩掉原先己有的剧情使用creat创造三个已存在的文件不会导致错误
假定要开创的公文不设有,则creat用参数pems钦定的权限创立文件。在UNIX文件系统中,每一种文件对应叁个9比特的权杖音讯,它们分别调控文件的主人、全部者组和别的成员对文本的读、写和推行访谈。由此,通过三个3位的八进制数就可惠及地证实分裂的权限,比方,0755(八进制)表明文件的持有者能够对它进行读、写和实行操作,而全部者组和别的成员只好进展读和实践操作。
 
下边通过二个简化UNIX程序cp表明creat的用法,该程序将二个文书复制到另多个文本。目标文件的权能不是经过复制获得的,而是重新定义的:
#include<stdio.h>
#include<fcntl.h>
#include<stdarg.h>
#include"syscalls.h"
#define PERMS 0666 /* RW for owner, group, others */
void error(char *, ...);
/* cp: copy f1 to f2 */
main(int argc, char *argv[]) {
    int f1, f2, n;
    char buf[BUFSIZ];
    if (argc != 3)
       error("Usage: cp from to");
    if ((f1 = open(argv[1], O_RDONLY, 0)) == 1)
       error("cp: can't open %s", argv[1]);
    if ((f2 = creat(argv[2], PERMS)) == 1)
       error("cp: can't create %s, mode %03o", argv[2], PERMS);
    while ((n = read(f1, buf, BUFSIZ)) > 0)
       if (write(f2, buf, n) != n)
           error("cp: write error on file %s", argv[2]);
    return 0;
}
void error(char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    fprintf(stderr, "error: ");
    vprintf(stderr, fmt, args);
    fprintf(stderr, "n");
    va_end(args);
    exit(1);
}
该程序制造的输出文件具有一定的权能0666,也可利用stat系统调用,能够拿走三个已存在文件的形式,并将此情势赋值给它的别本。标准库函数vprintf数与printf函数类似,所不一致的是,它用三个参数代替了变长参数表,由此参数通过调用va_start宏进行开端化。同样,vfprintfvsprintf函数分别与fprintf和sprintf函数类似。
 
函数close (int fd)用来断开文件呈报符和已展开文件之间的连接,并释放此文件描述符,以供别的文件使用。close函数与规范库中的fclose函数相呼应,但它无需破除(flush)缓冲区。
 
函数unlink(char *name)将文件name从文件系统中去除,它对应柳盈瑄规库函数remove

{

可移植性忠告

利用标识常量EOF并非使用-1可选拔程序有所更加好的可移植性。ANSI标准规定EOF是二个负整数,但不是必得为-1。因而,在分化的系统中,EOF恐怕有两样的值。

因为int类型的整数值在分裂的连串中保有差别的限量,所以假如要拍卖 -32768 ~ +32767限制之外的整数值而且要力所能致使用程序在不一致的Computer种类中运作,使用long数据类型。

底层I/O — read和write

    输入与输出是透过现read和write系统调用实现的。在C语言程序中,能够通过函数read和write访问那多少个系统调用。那五个函数中,第贰个参数是文本描述符,第4个参数是程序中存放读和写的数额的字符数组,第多少个参数是要传输的字节数:
int n_read = read(int fd, char *buf, int n);
int n_written = write(int fd, char *buf, int n);
各类调用重回实际传输(读或写)的字节数。在读文件时,函数的重回值大概会低于须要的字节数,假诺返回值为0,则象征已达到文件的最后;如若重临值为-1,则代表发生了某种错误。在写文件时,重临值是事实上写入的字节数,假如重临值与需要写入的字节数不对等,则证实发生了不当。
    在三回调用中,读出或写入的数指标字节数可认为随机大小。最常用的值为1,即每一回读出或写入1个字符(无缓冲),或是类似于1024~4096如此的与外围设备的物理块大小相应的值。用越来越大的值调用该函数能够收获越来越高的成效,因为系统调用的次数收缩了。
#include"syscalls.h"
main() /*将输入复制到输出*/
{
    char buf[BUFSIZ];
    int n;
    while ((n = read(0, buf, BUFSIZ)) > 0)
       write(1, buf, n);
    return 0;
}
本章中的程序都将蕴涵该头文件syscalls.h,可是,该公文的名字不是正式的。参数BUFSIZ已经在syscalls.h头文件中定义了。对于所使用的操作系统来讲,该值是一个较适宜的数值。借使文件大小不是BUFSIZ的翻番,则对read的某次调用会再次来到三个比较小的字节数,write再按这些字节数写。
 
结构类似于getchar高档函数: 从正式输入读入四个字符来达成无缓冲输入(第八个版本)
#include"syscalls.h"
int getchar(void) {
    char c;
    return (read(0, &c, 1) == 1) ? (unsignedchar) c : EOF;
}
其次个本子:二次读入一组字符,但每一遍只输出贰个字符
#include"syscalls.h"
int getchar(void) {
    staticchar buf[BUFSIZ];
    staticchar *bufp = buf;
    staticint n = 0;
    if (n == 0) { /* buffer is empty */
       n = read(0, buf, sizeof buf);
       bufp = buf;
    }
    return (n >= 0) ? (unsignedchar) *bufp++ : EOF;
}
假诺要在含有头文件始<stdio.h>的情形下编写翻译那么些本子的getchar函数,就有不能缺少用#-undef预处理指令撤销名字getchar的宏定义,因为在头文件中,getchar是以宏格局完结的。

SEEK_END: 从文件的结尾开头总括偏移量

UNIX系统接口

可移植性忠告

应用标识常量EOF而不是采取-1可选用程序有所更加好的可移植性。ANSI规范规定EOF是多少个负整数,但不是必得为-1。由此,在不相同的系统中,EOF恐怕有例外的值。
 
因为int类型的整数值在分歧的类别中颇具差别的限制,所以一旦要拍卖 -32768 ~ +32767限量之外的整数值何况要能够运用程序在不一样的Computer种类中运作,使用long数据类型。  

{

实例-fopen和getc函数的贯彻

规范库中的文件不是因而文件呈报符描述的,而是使用文件指针描述的文件指针是二个对准包蕴文件各样音讯的协会的指针,该组织包含下列内容:几个针对缓冲区的指针,通过它能够贰回读入文件的一大块内容;一个记下缓冲区中多余的字符数的计数器;二个针对缓冲区中下一个字符的指针;文件陈述符;描述读/写方式的标识;描述失实状态的评释等。
——相关宏定义——
#define NULL 0
#define EOF
#define BUFSIZ 1024
#define OPEN_MAX 20 /* 三遍允许展开的最大文件数 */
typedefstruct _iobuf {
intcnt; /* 剩余字符数 */
char *ptr; /* 下八个字符的岗位 */
char *base; /* 缓冲区的职位 */
intflag; /* 文件访谈形式与失误标示 */
intfd; /* 文件陈说符 */
} FILE;

externFILE _iob[OPEN_MAX]; //用来存储打开的公文结构数据
#define stdin (&_iob[0]) //第一个用作专门的学业输入
#define stdout (&_iob[1]) //第三个用作专门的学问输出
#define stderr (&_iob[2]) //第三个用作错误输出
enum _flags {
/* 使用了5位来标示文件的看望格局与公事访问时出错标示: 00 011 111,
以位来标示便于使用位运算符&来决断文件的开采后所处的景色,如剖断展开
文件是或不是出错:(fp -> flag & (_EOF | _ERR)) != 0 */
_READ = 01, /* 以读方式打开文件 */
_WRITE = 02, /* 以写情势展开文件 */
_UNBUF = 04, /* 不对文件进行缓冲 */
_EOF = 010, /* 已到文件尾 */
_ERR = 020 /* 该文件发出错误 */
};

int _fillbuf(FILE *);
int _flushbuf(int, FILE *);

#define feof->flag & _EOF) != 0)
#define ferror->flag & _ERR) != 0)
#define fileno->fd)
/* 先将计数器cnt减一,再将指针移到下二个职位,然后重临字符,
* 假若小于0,则就填允缓冲区,重新开端化结构的剧情,并赶回
* 三个字符*/
#define getc->cnt >= 0
? (unsignedchar) *->ptr++ : _fillbuf
/* 缓冲区满后刷新缓冲到文件中*/
#define putc ->cnt >= 0
? *->ptr++ = : _flushbuf
#define getchar() getc
#define putcher putc, stdout)

——fopen实现——
#include<fcntl.h>
#include"syscalls.h"
#define PERMS 0666 /* RW for owner, group, others */
FILE *fopen(char *name, char *mode) {
int fd;
FILE *fp;
if (*mode != 'r' && *mode != 'w' && *mode != 'a')
return NULL;
for (fp = _iob; fp < _iob + OPEN_MAX; fp++)
if ((fp -> flag & (_READ | _WRITE)) == 0)
break; /* 找寻多少个空地方,即让fp指向_iob数据还未利用的要素
,要是协会数据未赋值,则_READ | _W奇骏ITE位所在的
位为0,则(_READ | _WRITE)就为0 */
if (fp >= _iob + OPEN_MAX) /* 最大文件个数超限 */
return NULL;
if (*mode == 'w')
fd = creat(name, PERMS);
elseif (*mode == 'a') {
//借使以写的诀窍展开文件后赶回的文本汇报符为1,
//则重新创造三个文书
if ((fd = open(name, O_WRONLY, 0)) == 1)
fd = creat(name, PERMS);
lseek(fd, 0L, 2);//定位到文件结尾
} else
fd = open(name, O_RDONLY, 0);
if
/* 不能够访谈文件 */
return NULL;
/* 平常展开文件后,将相应的文书结构数据存款和储蓄到_iob结构数组中相应空闲成分的职位中,
_iob结构数组首要的是多个大局的,用来记录当前程序已开垦文件,那样就足以界定打开的
最多文本数*/
fp -> fd = fd;
fp -> cnt = 0;
fp -> base = NULL;
fp -> flag = (*mode == 'r') ? _READ : _WRITE;
return fp;
}

——缓冲函数的兑现——
#include"syscalls.h"
/* _fillbuf: 分配并填允缓冲区 */
int _fillbuf(FILE *fp) {
int bufsize;
if ((fp -> flag & (_READ | _EOF | _ERR)) != _READ)
return EOF;
bufsize = (fp -> flag & _UNBUF) ? 1 : BUFSIZ;
if (fp -> base == NULL) /* 还未分配缓冲区时 */
if ((fp -> base = (char *) malloc == NULL)
return EOF; /* 不可能分配缓冲区 */
fp -> ptr = fp -> base;
fp -> cnt = read(fp -> fd, fp -> ptr, bufsize);
if (fp -> cnt < 0) {
if (fp -> cnt == 1)
fp -> flag |= _EOF;
else
fp -> flag |= _ERR;
fp -> cnt = 0;
return EOF;
}
return (unsignedchar) *fp -> ptr++;
}

/* 最后大家还必得定义和最早化数组_iob中的stdin, stdout, stderr*/
FILE _iob[OPEN_MAX] = {
{ 0, (char *) 0, (char *) 0, _READ, 0},
{ 0, (char *) 0, (char *) 0, _WRITE, 1},
{ 0, (char *) 0, (char *) 0, _WRITE | _UNBUF, 2}/* 标准错误输出不用缓冲的 */
};

[C程序设计语言]第五部分,c程序设计第五有个别

声明:原创文章,转发时请表明小说来源SAP师太博客,并以超链接情势申明作品原本出处,不然将钻探法律权利!  UNIX系统接口... 1
个性忠告... 7
可移植性忠告... 8
函数原型... 8  

rewind函数的功力是使地方指针重新再次来到文件的上马,函数未有重临值。

性子忠告

在内部存款和储蓄器紧张和须要运转速度的图景下,最棒使用数值范围相当小的卡尺头数据类型。

在证明时就赋值大概增进程序运营时间。

c +=5 比 c = c + 5要快,原因是前面五个中c只深入分析三遍,而前面一当中c要剖析一遍。

在采纳运算符&&的表明式中,把最恐怕为假的基准放在最左侧。在行使运算符||的表达式中,把最恐怕为真正条件放在最左侧,这样能减少程序的实践时间。

天性忠告

在内部存款和储蓄器恐慌和供给运维速度的场馆下,最好使用数值范围十分的小的卡尺头数据类型。
 
在注明时就赋值恐怕增加程序运转时间。
 
c +=5 比 c = c + 5要快,原因是前面两在那之中c只深入分析叁次,而后人中c要分析四次。
 
在利用运算符&&的表明式中,把最恐怕为假的尺度放在最右侧。在运用运算符||的表达式中,把最或许为确实条件放在最侧面,那样能减小程序的实行时间。

i=lseek(fd,11,SEEK_SET);

随便拜访-lseek

系统调用lseek能够在文件中专擅运动地点而不实际读写任何数据:
long lseek(int fd, long offset, int origin);
将文件叙述符为fd的文件的此时此刻职责设置为offset,在那之中,offset是相对于orgin钦定的岗位来说的。随后开展的读写操作将从此地方上马,origin的值可以为0、1或2,分别用于钦赐offset从文件早先、从当下岗位或从文件甘休处开首算起。例如,为了向三个文本的后面部分增加内容(在UNIX shell前后相继中运用重定向符>>或在系统调用fopen中央银行使参数“a”):
lseek(fd, 0L, 2);


#include"syscalls.h"
/*get: read n bytes from position pos 从文件的任性地方读入任性数指标字节,它回到读入的字节数,若发生错误重返-1*/
int get(int fd, long pos, char *buf, int n) {
if (lseek(fd, pos, 0) >= 0) /* get to pos 先移动到钦定的义务*/
returnread(fd, buf, n); /* 再读取*/
else
return 1;
}

lseek系统调用重回long类型的值,此值表示文件的新职责,若产生错误,则赶回-1。标准库函数fseek与系统调用lseek类似,不一样的是,前面一个第三个参数为FILE *类型,並且爆发错误时回来二个非0值。

实例-fopen和getc函数的落实

标准库中的文件不是经过文件陈说符描述的,而是选用文件指针描述的文本指针是三个对准富含文件各个音信的结构的指针,该协会包涵下列内容:三个针对缓冲区的指针,通过它能够贰回读入文件的第一次全国代表大会块内容;贰个记下缓冲区中多余的字符数的计数器;一个针对缓冲区中下二个字符的指针;文件陈述符;描述读/写情势的标识;描述失实状态的表明等。
——相关宏定义——
#define NULL 0
#define EOF (1)
#define BUFSIZ 1024
#define OPEN_MAX 20 /* 三回允许打开的最大文件数 */
typedefstruct _iobuf {
    intcnt; /* 剩余字符数 */
    char *ptr; /* 下二个字符的职位 */
    char *base; /* 缓冲区的岗位 */
    intflag; /* 文件访谈情势与失误标示 */
    intfd; /* 文件呈报符 */
} FILE;
 
externFILE _iob[OPEN_MAX]; //用来存款和储蓄打开的文件结构数据
#define stdin (&_iob[0]) //第叁个用作职业输入
#define stdout (&_iob[1]) //第四个用作专门的职业输出
#define stderr (&_iob[2]) //第两个用作错误输出
enum _flags {
    /*  使用了5位来标示文件的探望格局与公事访问时出错标示: 00 011 111,
       以位来标示便于使用位运算符&来判断文件的开垦后所处的情景,如判别张开
       文件是还是不是出错:(fp -> flag & (_EOF | _ERR)) != 0 */
    _READ = 01, /* 以读格局张开文件 */
    _WRITE = 02, /* 以写情势展开文件 */
    _UNBUF = 04, /* 不对文件举办缓冲 */
    _EOF = 010, /* 已到文件尾 */
    _ERR = 020 /* 该文件发出错误 */
};
 
int _fillbuf(FILE *);
int _flushbuf(int, FILE *);
 
#define feof(p) ((p)->flag & _EOF) != 0)
#define ferror(p) ((p)->flag & _ERR) != 0)
#define fileno(p) ((p)->fd)
/* 先将计数器cnt减一,再将指针移到下多个岗位,然后重临字符,
* 假设小于0,则就填允缓冲区,重新伊始化结构的剧情,并赶回
* 多个字符*/
#define getc(p) (--(p)->cnt >= 0
       ? (unsignedchar) *(p)->ptr++ : _fillbuf(p))
/* 缓冲区满后刷新缓冲到文件中*/
#define putc(x,p) (--(p)->cnt >= 0
       ? *(p)->ptr++ = (x) : _flushbuf((x),p))
#define getchar() getc(stdin)
#define putcher(x) putc((x), stdout)
 
——fopen实现——
#include<fcntl.h>
#include"syscalls.h"
#define PERMS 0666 /* RW for owner, group, others */
FILE *fopen(char *name, char *mode) {
    int fd;
    FILE *fp;
    if (*mode != 'r' && *mode != 'w' && *mode != 'a')
       return NULL;
    for (fp = _iob; fp < _iob + OPEN_MAX; fp++)
       if ((fp -> flag & (_READ | _WRITE)) == 0)
           break; /* 搜索三个空位置,即让fp指向_iob数据还未利用的要素
,假若组织数据未赋值,则_READ | _WRITE位所在的
位为0,则(_READ | _WRITE)就为0 */
    if (fp >= _iob + OPEN_MAX) /* 最大文件个数超过限度 */
       return NULL;
    if (*mode == 'w')
       fd = creat(name, PERMS);
    elseif (*mode == 'a') {
       //假若以写的艺术张开文件后赶回的文件叙述符为1(标准输出),
       //则重新创制贰个文本
       if ((fd = open(name, O_WRONLY, 0)) == 1)
           fd = creat(name, PERMS);
       lseek(fd, 0L, 2);//定位到文件结尾
    } else
       fd = open(name, O_RDONLY, 0);
    if (fd == -1)
       /* 不能访问文件 */
       return NULL;
    /* 平常张开文件后,将相应的文件结构数据存储到_iob结构数组中相应空闲成分的职分中,
  _iob结构数组主要的是一个大局的,用来记录当前前后相继已张开文件,这样就能够限制展开的
最多文本数*/
    fp -> fd = fd;
    fp -> cnt = 0;
    fp -> base = NULL;
    fp -> flag = (*mode == 'r') ? _READ : _WRITE;
    return fp;
}
 
——缓冲函数的兑现——
#include"syscalls.h"
/* _fillbuf: 分配并填允缓冲区 */
int _fillbuf(FILE *fp) {
    int bufsize;
    if ((fp -> flag & (_READ | _EOF | _ERR)) != _READ)
       return EOF;
    bufsize = (fp -> flag & _UNBUF) ? 1 : BUFSIZ;
    if (fp -> base == NULL) /* 还未分配缓冲区时 */
       if ((fp -> base = (char *) malloc(bufsize)) == NULL)
           return EOF; /* 无法分红缓冲区 */
    fp -> ptr = fp -> base;
    fp -> cnt = read(fp -> fd, fp -> ptr, bufsize);
    if (fp -> cnt < 0) {
       if (fp -> cnt == 1)
           fp -> flag |= _EOF;
       else
           fp -> flag |= _ERR;
       fp -> cnt = 0;
       return EOF;
    }
    return (unsignedchar) *fp -> ptr++;
}
 
/* 最后大家还必得定义和起先化数组_iob中的stdin, stdout, stderr*/
FILE _iob[OPEN_MAX] = {
    {   0, (char *) 0, (char *) 0, _READ, 0},
    {   0, (char *) 0, (char *) 0, _WRITE, 1},
    {   0, (char *) 0, (char *) 0, _WRITE | _UNBUF, 2}/* 标准错误输出不用缓冲的 */
};  

S_IXUSEnclave 00100 设置文件全体者的施行权限

底层I/O — read和write

输入与输出是通过现read和write系统调用达成的。在C语言程序中,能够经过函数read和write访问那四个系统调用。那三个函数中,第叁个参数是文本描述符,第1个参数是程序中寄放读和写的数据的字符数组,第五个参数是要传输的字节数:
int n_read = read(int fd, char *buf, int n);
int n_written = write(int fd, char *buf, int n);
每一个调用重回实际传输的字节数。在读文件时,函数的再次回到值恐怕会小于央求的字节数,借使重临值为0,则意味着已到达文件的末段;如若再次来到值为-1,则意味爆发了某种错误。在写文件时,重返值是实在写入的字节数,倘诺重返值与央求写入的字节数不对等,则印证产生了不当。
在一遍调用中,读出或写入的多少的字节数可以为随便大小。最常用的值为1,即每一回读出或写入1个字符,或是类似于1024~4096那样的与外围设备的物理块大小相应的值。用更加大的值调用该函数能够拿走更加高的频率,因为系统调用的次数减弱了。
#include"syscalls.h"
main() /*将输入复制到输出*/
{
char buf[BUFSIZ];
int n;
while ((n = read(0, buf, BUFSIZ)) > 0)
write(1, buf, n);
return 0;
}
本章中的程序都将包涵该头文件syscalls.h,然则,该公文的名字不是行业内部的。参数BUFSIZ已经在syscalls.h头文件中定义了。对于所选择的操作系统来讲,该值是三个较适合的数值。要是文件大小不是BUFSIZ的倍数,则对read的某次调用会重回八个异常的小的字节数,write再按那些字节数写。

组织类似于getchar高等函数: 从标准输入读入八个字符来完成无缓冲输入
#include"syscalls.h"
int getchar(void) {
char c;
return (read(0, &c, 1) == 1) ? (unsignedchar) c : EOF;
}
第一个版本:二次读入一组字符,但老是只输出二个字符
#include"syscalls.h"
int getchar(void) {
staticchar buf[BUFSIZ];
staticchar *bufp = buf;
staticint n = 0;
if { /* buffer is empty */
n = read(0, buf, sizeof buf);
bufp = buf;
}
return (n >= 0) ? (unsignedchar) *bufp++ : EOF;
}
如若要在蕴藏头文件始<stdio.h>的气象下编写翻译这个本子的getchar函数,就有须求用#-undef预管理指令撤消名字getchar的宏定义,因为在头文件中,getchar是以宏格局完结的。

轻巧访问-lseek

系统调用lseek能够在文书中任性运动地方而不实际读写任何数据:
    long lseek(int fd, long offset, int origin);
将文件陈说符为fd的文书的此时此刻任务设置为offset,在那之中,offset是绝对于orgin钦点的岗位来讲的。随后开展的读写操作将从此地方上马,origin的值可感觉0、1或2,分别用于钦命offset从文件早先、从当下地点或从文件截止处早先算起。比如,为了向三个文本的后面部分增添内容(在UNIX shell前后相继中运用重定向符>>或在系统调用fopen中行使参数“a”):
    lseek(fd, 0L, 2);
 
#include"syscalls.h"
/*get: read n bytes from position pos 从文件的随飞机地方置读入大肆数指标字节,它回到读入的字节数,若爆发错误重返-1*/
int get(int fd, long pos, char *buf, int n) {
    if (lseek(fd, pos, 0) >= 0) /* get to pos 先移动到钦定的岗位*/
       returnread(fd, buf, n); /* 再读取*/
    else
       return 1;
}
 
lseek系统调用再次来到long类型的值,此值表示文件的新义务,若发生错误,则赶回-1。规范库函数fseek与系统调用lseek类似,分歧的是,前面一个第2个参数为FILE *类型,并且发生错误时回来七个非0值。

whence代表用于偏移时的相对地方,能够取如下的多少个值

UNIX系统接口... 1
属性忠告... 7
可移植性忠告... 8
函数原型... 8

函数原型

函数原型告诉编写翻译器函数再次回到的数据类型,函数所要接收的参数个数,参数类型和参数顺序,编写翻译器用函数原型校验函数调用。
int maxinum(int, int, int);
这里大概了参数名,也足以带上参数名
 
函数原型另四个至关心保护要特点是胁迫调换参数类型,如正式库函数sqrt函数原型钦赐了参数为double类型,但在调用时得以传递整型,这是因为编写翻译器依照函数原型,调用前将整型调换为double型了。如若不根据C语言的类型“提高法规”,参数类型转变也许会导致不得法的结果。    

申明: 原创小说 , 转发时请阐明小说来源 SAP师太 博客 , 并以超链接方式申明小说原本出...

}

文件陈述符

在UNIX操作系统中,全数的外围设备(包涵键盘和荧屏)都被看作是文件系统中的文件,因而,全部的输入/输出都要透过读文件或写文件落成。
因为半数以上的输入/输出是经过键盘和显示器来落到实处的,为了便于起见,UNIX对此做了特地的配置。当命令解释程序(即“shell”)运维三个程序的时候,它将展开3个公文,对应的文本汇报符分别为0, 1, 2,依次表示行业内部输入,规范输出和正式错误。即使程序从文件0中读,对1和2举办写,就足以开展输/输出而不必关怀张开文件的标题。
程序的使用者可透过<和>重定向程序的I/O:
prog <输入文件名 >输出文件名
这种状态下,shell把公文陈述符0和l的暗中认可赋值改动为钦点的文书。平日,文件呈报符2仍与显示器相关联,那样,出错音讯会输出到显示器上。在别的悄况下,文件赋值的更换都不是程序完结的,而是由shell实现的。只要程序选择文件0作为输入,文件l和2作为出口,它就不会知程序的输入从哪个地方来,并出口到什么地方去。

文件叙述符

在UNIX操作系统中,全部的外围设备(满含键盘和显示器)都被看成是文件系统中的文件,由此,全数的输入/输出都要通过读文件或写文件完毕。
    因为大多数的输入/输出是由此键盘和显示屏来促成的,为了便利起见,UNIX对此做了特地的布局。当命令解释程序(即“shell”)运转二个前后相继的时候,它将张开3个文件,对应的文件呈报符分别为0, 1, 2,依次表示行业内部输入,标准输出和行业内部错误。假如程序从文件0中读,对1和2进展写,就足以扩充输/输出而不用关怀张开文件的难点。
    程序的使用者可通过<和>重定向程序的I/O:
    prog <输入文件名 >输出文件名
这种景况下,shell把文件陈述符0和l的暗中认可赋值改变为钦点的公文。经常,文件陈说符2仍与荧屏相关联,那样,出错音讯会输出到显示屏上。在任何悄况下,文件赋值的改观都不是程序实现的,而是由shell实现的。只要程序行使文件0作为输入,文件l和2作为出口,它就不会知程序的输入从何地来,并出口到哪儿去。

int open(const char *pathname,int flags,mode_t mode)

char *path="/home/zhf/zhf/c_prj/c_test.txt";

一律的依赖流操作的也许有文件的定势操作函数分别是fseek函数和rewind函数

if ((ch=fgetc(fp)) != EOF)

printf("%sn",str);

Char *fgets(char *s,int size, FILE *stream);

open 是系统调用 重返的是文本句柄,文件的句柄是文件在文件汇报副表里的目录,fopen是C的库函数,重返的是一个针对文件结构的指针。
linux中的系统函数是open,fopen是其封装函数。fopen能够移植,open不能够

缓冲文件系统的特征是:在内部存款和储蓄器开拓贰个“缓冲区”,为顺序中的每一个文本使用,当推行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”, 装满后再从内部存款和储蓄器“缓冲区”依此读入接收的变量。实践写文件的操作时,先将数据写入内部存款和储蓄器“缓冲区”,待内部存款和储蓄器“缓冲区”装满后再写入文件。因此可以看出,内存“缓冲区”的轻重,影响着实操外部存款和储蓄器的次数,内部存款和储蓄器“缓冲区”越大,则操作外部存款和储蓄器的次数就少,施行进程就快、效用高。一般的话,文件“缓冲区”的大大小小随机器 而定。首要有fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等
2.非缓冲文件系统
缓冲文件系统是依赖文件结构体指针来对文本举行管理,通过文件指针来对文件进行访谈,既可以够读写字符、字符串、格式化数据,也能够读写二进制数 据。非缓冲文件系统注重于操作系统,通过操作系统的效果对文本实行读写,是系统级的输入输出,它不设文件结构体指针,只好读写二进制文件,但功用高、速度 快,由于ANSI标准不再包含非缓冲文件系统,因而建议咱们最为不要挑选它。本书只作简介。open, close, read, write, getc, getchar, putc, putchar 等。

S_IWOTH 00002 设置别的客商的写权限

for(i=0;i<5;i++)

此间offset表示移动的字节数,供给位移量是long型数据。以便在文件长度超越64Kb不会出错

int fseek(FILE *stream,long offset,int whence)

函数调用成功,再次回到为读取的字节数,不然再次回到-1

whence和前边介绍的完全一样。

S_IEscortWXU 00700 设置文件全部者的读,写,实施权限

S_IXOTH 00001 设置其余用户的实行权限

}

mode代表文件的张开药情势。有 r,r+,w,w+,a,a+等方法

char ch;

函数修改如下: 首先选择lseek函数将文件定位到从第十个字节开首,然后read将从第拾二个字节初叶读取。

printf("%c",ch);

O_NONBLOCK:用于非堵塞接口i/o

Linux系统中提供了系统调用函数open()和close()用于打开和关闭叁个留存的公文

文本的读操作:

void fopen_file()

char result[100];

{

fputc和fgetc函数只可以三遍性的读取只怕写入一个字节,假如想读取也许写入贰个字符串则必要用到fgets()和fputs()函数。

fd=open(path,O_RDWR);

fgetc()函数:从文件读取1个字节 int fgetc(FILE *stream). 如若出错恐怕读到文件末尾,则赶回EOF

O_WRONLY:以只写的主意展开文件

printf("the content is %sn",buf);

ssize_t read(int fd,void *buf,size_t count);

char buf[100];

n=read(fd,buf,20);

str=fgets(result,20,fp);

int fputs(const char *s, FILE *stream);

{

S_IWGRP 00020 设置顾客组的写权限

char *path="/home/zhf/zhf/c_prj/c_test.txt";

void fopen_file()

}

char *path="/home/zhf/zhf/c_prj/c_test.txt";

S_IWUSRAV4 00200 设置文件全部的写权限

char buf[100];

fd代表文件描述符,buf代表读取的数量寄放的buf指针所指向的缓冲区,count代表读取数据的字节数

里头flag代表文件的张开药方式

SEEK_SET: 从文件的发端地方计算偏移量

fp=fopen(path,"r");

读取到’n’转移字符为了却,并在该行末尾增添二个’’组成达成的字符串。在size字节范围内未有读到’n’停止符,则增加八个’’

实例代码:

{

O_NODELAY

off_t lseek(int fildes,off_t offset,int whence);

char *str;

void open_and_read_file()

int fd,n;

fd=open(path,O_RDWR);

int open(const char *pathname,int flags)

}

O_SportageDONLY: 以只读格局张开文件

FILE *fp;

int open(const char *pathname,mode_t mode)

O_CREAT:若张开的文本海市蜃楼,则创立该公文

眼下介绍的操作都是依靠文件呈报符的公文操作,下边来介绍基于流的文件操作。两个有啥样区别呢:

n=read(fd,buf,20);

对此写操作也是同样的。

S_I库罗德WXO 00007 设置别的客商的读,写,实施权限

fputc()函数:向钦命的文书写入1个文本 int fputc(int c,FILE *stream);

int i;

S_IRUSENVISION 00400 设置文件全体者的读权限

close(fd);

O_应用软件END:追加的方法展开文件

char *path="/home/zhf/zhf/c_prj/c_test.txt";

O_SYNC:当数码被写入外部存款和储蓄器只怕另外设施后,操作才回到。

fclose(fp);

S_I翼虎WXG 00070 设置文件所在客商组的读,写,推行权限

int i;

int i;

}

printf("the content is %sn",buf);

S_IROTH 00004 设置其余客户的读权限

S_I阿斯顿·马丁DB11GRP 00040 设置顾客组的读权限

O_LacrosseDW库罗德:以读写的点子展开文件

path代表文件名路线

文件读和写的例子

int fd,n;

O_EXCL:如若展开文件是安装了O_CREAT,可是该公文存在,则导致调用失利

char ch;

O_TRUNC:假诺以只写或只读方式展开贰个已存在的公文,将该文件截止0

FILE *fp;

void open_and_read_file()

来看fopen函数:FILE *fopen(const char *path,const char *mode)

里面mode是开垦的权限

SEEK_CUEnclave: 从近日的地方上马图谋偏移量

fp=fopen(path,"r");

S_IXGRP 00010 设置顾客组的实施权限

fildes是文本陈述符

{

offset是偏移量

}

本文由9159.com发布于编程,转载请注明出处:以只读方式打开文件,可移植性忠告...

关键词:

上一篇:没有了
下一篇:没有了