文件IO:系统调用 VS C library VS C++

概要

本文将从文件IO的几个方面来总结操作文件的方式:

打开文件

方式 头文件 调用 参数说明 返回值 功能 注意点
system call sys/types.h
sys/stat.h
fcntl.h
int open(const char* name, int flags, mode_t mode); name:文件名
flags:访问文件方式
mode:文件许可
int : file descriptor(fd),若打开成功则返回文件句柄,失败则返回-1并设置errno为相应值 打开文件并赋以相应模式和许可操作 figureerrno
system call creat
c stdio.h FILE* fopen(const char* path, const char* mode); path:文件路径
mode:打开模式
FILE*:file pointer,若打开成功则返回FILE*,失败则返回NULL并设置errno mode指定方式打开文件 FILE*fd区别
c++ fstream std::ofstream(const char* filename, ios_base::openmode mode = ios_base::out)
or
ifstream (const char* filename, ios_base::openmode mode = ios_base::in);
filename:文件名
openmode:打开方式
非函数调用,而是通过构造函数生成一个fstream对象 生成一个指定openmode的文件对象 好的风格要指定openmode,虽然有默认值

读文件

方式 头文件 调用 参数说明 返回值 功能 注意点
system call <unistd.h> ssize_t read(int fd, void* buf, size_t len); fd:文件句柄
buf:将数据读入指针值指向的位置
len:读入lenBytes
1.若成功读入lenBytes返回值等于len
2.返回值大于0但小于len,产生信号中断,或读到EOF(即没有剩余数据可读)
3.返回0,即该次read已经读到EOF处
4.返回-1,若errnoEINTRorEAGAIN可reissue,否则发生错误。
从文件当前position开始向buf读入lenBytes 注意return valueerrno的处理.
C <stdio.h> int fgetc(FILE* stream); stream:file pointer 将读入的一个unsigned charint返回 读入当前位置的后一个Byte 返回值要用int去接而不是char
C 同上行 char* fgets(char* str, int size, FILE* stream); str:数据读入的字符串
size:读入Bytes
stream:file pointer
若成功读size-1Bytes或者读到newline返回str指针,但返回NULL如果遇到EOF或发生错误 可读取整行数据,如果size足够大,超过行字节数。 实际上读size-1Bytes,最后一字节为'\0',如果读到新的一行,\n也会被存入str,同时注意若读到EOF是返回NULL
C 同上行 size_t fread(void* buf, size_t size, size_t nr, FILE* stream); 两个关键:
nr:最多读nr"块"
size:每"块"读sizeBytes
返回值为一个小于等于nr的值 可用于读取struct结构 1.注意返回值,若小于nr则需要用ferror()feof()判断是属于哪种情况
2.尽量符合内存对齐原则
C++ <fstream> 常用:>>getline等(见附录)

写文件

方式 调用 参数说明 返回值 功能 注意点
system call ssize_t write(int fd, const void* buf, size_t count); buf:写入的数据,注意const保护
fd:文件句柄
count:写入的字节数
若成功,返回成功写入字节数并且更新文件当前position,失败则返回-1,也可返回0代表未写入任何数据 buf中的countBytes数据写入文件 注意对bufconst保护,以及count存在上限SSIZE_MAX
C int fputc(int c, FILE* stream); c:要存入的一个Byte(cast to unsigned char)
stream:file pointer
若成功则返回c,失败则返回EOF 向文件写入一个字节的数据 虽然参数是int,但实际转化为unsigned char存入
C int fputs(const char* str, FILE* stream); str:要写入的字符串 成功返回一个非负整数,失败则返回EOF 向文件写入字符串 返回值为整数
C size_t fwrite(void* buf, size_t size, size_t nr, FILE* stream); nr:最多写nr"块"
size:每"块"写入sizeBytes
返回成功写入的块数,若失败则返回一个小于nr的值 向文件写入每块为sizenr块数据 注意返回值check
C++ 常用<<操作符

关闭文件

方式 调用 参数说明 返回值 功能 注意点
system call int close(int fd); 成功则返回0,失败返回-1 关闭以fd为句柄的文件 每次系统调用都要check error value
C int fclose(FILE* fp); 成功关闭则返回0,否则返回-1 关闭文件 同上
C++ 成员函数close()

各种用法demo

第一部分:system call

若文件存在则清空,不存在则以0644许可创建(owner可读可写,其他只可读)
int fd;
fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if(-1 == fd){
  //error
}
读指定Bytes
unsigned long word;
ssize_t nr;
nr = read(fd, &word, sizeof(unsigned long));
if(-1 == nr){
  //error
}
读所有bytes
//fstat()获取文件长度(C library)
struct stat st;
if(fstat(fd, &st)){
  //error
}
size_t len = st.st_size;
//read all bytes
ssize_t ret;
while(len != 0 && (ret = read(fd, buf, len)) != 0){
  if(-1 == ret){
    if(EINTR == errno) continue;
    perror("read");
    break;
  }
  len -= ret;
  buf += ret;
}
写一些bytes
unsigned long word = 1720;
size_t count = 0;
ssize_t nr = 0;

count = sizeof(word);
nr = write(fd, &word, count);
if(-1 == nr){
  //error,and check errno
}
else if(nr != count){
  //only write part bytes
}
ssize_t ret = 0, nr = 0;
while(0 != len && (ret = write(fd, buf, len)) != 0){
  if(-1 == ret){
    if(EINTR == errno) continue;
    perror("write");
    break;
  }
  len -= ret;
  buf += ret;
}

第二部分:C语言

通过FILE*打开文件
FILE* stream = nullptr;
stream = fopen(path, "r");
if(!stream){
  //error
}
通过File Descriptor打开文件
FILE* stream = nullptr;
stream = fdopen(fd, "r");
if(!stream){
  //error
}
读写一个字节
//read
int c = 0;
c = fgetc(stream);
if(EOF == c){
  //error
}

//write
if(fputc(c, stream) == EOF){
  //error
}
读写一个字符串
//read
char buf[BUFFER_SIZE];
if(!fgets(buf, BUFFER_SIZE, stream)){
  //error
}
//write
if(fputs(buf, stream) == EOF){
  //error
}

读写binary data

//read
char buf[64];
size_t nr;
nr = fread(buf, sizeof(buf), 1, stream);
if(0 == nr){
  //error
}

//write
struct pirate{
  char name[100];
  unsigned long booty;
  unsigned int beard_len;
}blackbeard = {"JACK", 950, 48};

if(!fwrite(&blackbeard, sizeof(struct pirate), 1, stream)){
  //error
}

第三部分:C++

打开文件
//打开可读文件
ifstream in(path, ios::in);
if(!in){
  //error
}

//打开可写文件
ofstream out(path, ios::out);
if(!out){
  //error
}
读写文件
//读
//用相应数据类型以及>>组合使用
//学号 姓名 课程 成绩
int id, score;
string name, course;
while(in >> id >> name >> course >> score){
  //do
}
//写
//将vector<int>写入文件
vector<int> data{1,2,3,4};
for(int i = 0; i < data.size(); i++){
  out << data[i] << endl;
}

附录

参考资料:
c++方式可以参考<<c++ primer(第五版)>>
c/system call可以参考<<Linux System Programming,第二版>>

理解文件打开关系

参考link/文献/引用

fstat() : https://www.go4expert.com/articles/understanding-linux-fstat-example-t27449/
ifstream:http://www.cplusplus.com/reference/fstream/ifstream/
ofstream:http://www.cplusplus.com/reference/fstream/ofstream/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容