文件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 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 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++ 常用:>>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写入文件
vector data{1,2,3,4};
for(int i = 0; i < data.size(); i++){
  out << data[i] << endl;
}

附录

参考资料:
c++方式可以参考<>
c/system call可以参考<>

理解文件打开关系

参考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/

你可能感兴趣的:(文件IO:系统调用 VS C library VS C++)