ARTICLE DETAIL

资讯详情

深耕网站SEO优化与搜索引擎排名提升的一线实战洞察。

C/C++文件操作干货

C/C++文件操作干货 为什么使用文件程序运行结束后会释放内存,不会保留其中产生的数据,而文件可以把数据保存下来。文件的类型从功能上分类分为程序文件和数据文件.程序文件存储可以运行的程序,比如exe文件;数据文件储存程序运行时需要用到的数据。从储存方式上分类分为二进制文件和文本文件.不同储存方式的文件读取时需要不同类型的读取器.需要注意的是文本文件不是字面意思上储存的是文本内容,而是将其ASCLL储存下来,而其ASCLL码仍要转换成二进制。所以无论二进制文件还是文本文件存储的都是二进制只是由于存储时发生的转换不同可能会导致同样的数据以这两种方式存储得到不同的二进制。比如要存123这个数字:存储到文本文件: 123——49 50 51(实际上就是字符1 2 3的ASCLL码)——0011 0001 0011 0010 0011 0011(分别是49,50,51的二进制代码也是文件中真实存储的数据)存储到二进制文件: 123——0111 1011这是123的二进制也是文件中真实存储的数据C语言文件操作打开文件在对文件读写之前需要把文件打开。而c语言中打开文件主要用到的是fopen函数filename要打开的文件的文件名mode文件使用方式如果打开成功返回一个FILE类型的指针如果打开失败返回NULL。mode可能的取值如下:要注意的是,当使用方式是w,wb,wwb中的任意一种时文件原有内容会被清除。关于FILE指针FILE指针内存放fd和用户级缓存区等内容fd是操作系统的文件的用户入口举个例子#define _CRT_SECURE_NO_WARNINGS #includestdio.h int main() { FILE* p fopen(c.txt,w); if (p) { printf(打开成功\n); } }在上述例子中我尝试以“w”的方式打开名为“c.txt”的文件如果这个文件不存在就新建一个。注意如果filename仅仅是一个文件名的话那就表示在默认目录下查找。除此之外filename还可以是一条路径绝对路径/相对路径可以指定打开哪个位置的某文件。比如filename可以是“.../c.txt”或者“c:\yyy\xxx\c.txt”。在程序中顺序读写文件我们对文件的读写是通过函数来进行的下面是一些可以支持我们顺序读写的函数所谓所有输出(入)流可以浅薄的理解为你可以在显示器上输出(输入),也可以在文件中输出,当然,只有文件就表示只能输出(输入)到文件中.fgetc功能从输入流中读取一个字符包括换行空格等字符stream目标输入流返回值返回这个字母的ASCLL码,失败返回EOFeg#define _CRT_SECURE_NO_WARNINGS #includestdio.h int main() { FILE* p fopen(c.txt,r);//c.txt中只有1个字符 if (!p) { printf(打开失败\n); return -1; } printf(%c\n,fgetc(p)); printf(%d, fgetc(p)); return 0; }fputc功能在输出流中输出一个字符character要输出的字符的ASCLL码实际上传字符就行会自动转换stream目标输出流返回值返回charactereg#define _CRT_SECURE_NO_WARNINGS #includestdio.h int main() { FILE* p fopen(c.txt, w); if (!p) { printf(打开失败\n); return -1; } fputc(a,p); return 0; }fgets功能从一个输入流中读取一个字符串并在字符串结尾添加‘\0’str存放读取出来的字符串的位置num表示最多读取num-1个字符(剩下一个位置给\0)stream目标输入流返回值读取成功返回str读取失败或读取到文件结尾返回NULLfgets在遇到以下情况时会终止读取遇到换行符\n即读取到一行的末尾并且他会把换行符也读取到读取了n-1个字符遇到文件结束EOF即读取到文件末尾eg#define _CRT_SECURE_NO_WARNINGS #includestdio.h int main() { FILE* p fopen(c.txt, r); if (!p) { printf(打开失败\n); return -1; } char arr[100]; fgets(arr,5,p); printf(%s,arr); return 0; }fputs功能向一个输出流输出一个字符串不会输出末尾的‘\0’str要输出的字符串的首地址stream目标输出流返回值写入成功返回一个非负整数失败返回EOF-1eg:#define _CRT_SECURE_NO_WARNINGS #includestdio.h int main() { FILE* p fopen(c.txt, w); if (!p) { printf(打开失败\n); return -1; } fputs(abcdefg,p); return 0; }fscanf只比scanf多出一个stream参数与scanf基本一样功能从输入流中按照指定格式读取数据stream目标输入流format格式化字符串指定如何解析输入数据...可变参数用于存储读取到的数据类似scanf返回值表示成功匹配并赋值的参数个数如果文件结束或者读取失败返回EOFeg#define _CRT_SECURE_NO_WARNINGS #includestdio.h int main() { FILE* p fopen(c.txt, r); if (!p) { printf(打开失败\n); return -1; } int x 1; char y l; int num fscanf(p,%d,%c,x,y); printf(%d\n, x); printf(%c\n, y); printf(%d\n, num); return 0; }如上例显然x格式化读取成功了但是由于c.txt中的格式与format后面的格式,%c不匹配,所以没有读取成功因为只匹配到一个所以返回值是1。fprintf只比printf多出一个stream参数与printf基本一样功能将数据按指定格式写入输出流stream目标输出流format格式化字符串指定输出格式...可变参数输出的数据源类似 printf返回值表示成功写入流的数据的字节数如果写入失败返回EOFeg#define _CRT_SECURE_NO_WARNINGS #includestdio.h int main() { FILE* p fopen(c.txt, w); if (!p) { printf(打开失败\n); return -1; } int x 10; char y y; fprintf(p,%d,%c,x, y); return 0; }fread功能以二进制的方式读取文件中的数据ptr指向要存储读取数据的内存块的指针size每个数据项的字节大小count要读取的数据项数量stream文件指针指向要读取的文件返回值读取成功时返回成功读取到的数据数量即count读取失败或者读取到文件结尾时返回小于count的值。eg见fwritefwrite功能以二进制方式把数据写入文件ptr指向要写入数据的内存地址如数组、结构体等size每个数据项的字节大小通常用sizeof计算count要写入的数据项数量stream文件指针通过fopen打开返回值写入成功时返回成功写入的数据数量即count写入失败时返回小于count的值。eg:#define _CRT_SECURE_NO_WARNINGS #includestdio.h int main() { FILE* p fopen(c.txt, rb); if (!p) { printf(打开失败\n); return -1; } int arr[5] {1,5,2,3,7}; fwrite(arr,sizeof(arr[0]),5,p); fseek(p,0,SEEK_SET);//调整光标位置以便读取数据 int brr[5] {0}; fread(brr,sizeof(int),5,p); for(int i 0;i5;i) { printf(%d ,brr[i]); } return 0; }sscanf和sprintf功能对s指向的字符串进行格式化的读取。返回值返回成功匹配并赋值的参数个数如果到达字符串末尾而未匹配返回EOF。功能把格式化的数据转换为字符串并存放到str指向的内存块中。返回值成功时返回写入的字符数不包括结尾的 null 字符失败时返回负值。由于这两个函数及其类似于printf和scanf以及fprintffscanf只不过它们封装了输入/输出流所以不用入FILE流指针。在此举一个例子#define _CRT_SECURE_NO_WARNINGS #includestdio.h int main() { int a 0; char b 0; sscanf(ab1csd,ab%dc%cd,a,b); char* ptr[20] {0}; sprintf(ptr,a的值是:%d,b的值是:%c,a,b); printf(%s,ptr); return 0; }在程序中逆序读写文件光标也叫文件指针打开文件时光标会在文件的开始位置。所谓顺序读写就是输入输出时光标会随着输入输出的动作移动读写完一个数据光标就移动向下一个数据按顺序全部读写然而文件一旦关闭重开时光标会移动到起始位。所谓逆序读写就是在读写文件时在合理范围内改变光标位置想要读写哪儿就移动到哪儿去。这也是通过函数来控制。下面是文件光标控制函数fseek功能调整光标位置stream要调整光标位置的目标流origin规定偏移量为0的地方偏移起始位置有三种选择SEEK_SET(文件开头),SEEK_CUR目前光标的位置,SEEK_END文件末尾offset表示要移动到举例origin位置偏移量为offset的地方返回值成功返回0失败返回非0egfseekstream-8SEEK_CUR就是把光标从当前位置向前移动8位。fseekstream2SEEK_SET就是把光标移动到从文件开始位置向后2位的地方。ftell功能返回目前光标位置相对于起始位置的偏移量stream要查询的目标流返回值返回目前光标位置相对于起始位置的偏移量rewind功能直接将光标移动到文件起始位置stream要调整光标位置的目标流返回值无文件读取结果的判定函数用于判断文件流是否到达文件结尾。是返回非0值否返回0用于判断文件流是否发生错误。是返回非0值否返回0关闭文件关闭文件使用C语言库函数关闭成功返回0失败返回-1.后记c程序启动时,默认打开三个标准流其实就是打开若干文件stdin-标准输入流(大多数环境是从键盘输入)stdout-标准输出流(大多数环境是输出到显示器)stderr-标准错误流(大多数环境是输出到显示器)我们平时用到的scanf函数实际上就使用了stdin而printf使用了stdoutperror使用了stderr。C文件操作干货C中的文件操作相对于C语言来说是比较简单的因为其对复杂的过程做了封装。标准库提供了三种主要的文件流类来处理文件IO操作ofstream用于写入文件output file streamifstream用于读取文件input file streamfstream用于读写文件file stream打开文件每个流类都提供了open()方法也可以在构造函数中直接指定文件名和打开模式这时文件会直接被打开#define _CRT_SECURE_NO_WARNINGS #includefstream using namespace std; int main() { //使用构造函数打开文件 std::ofstream outFile(example.txt, std::ios::out);//可以省略std::ios::out因为默认就是这样 std::ifstream inFile(example.txt, std::ios::in);//可以省略std::ios::in因为默认就是这样 std::fstream ioFile(example.txt, std::ios::in | std::ios::out);//可以省略std::ios::in | std::ios::out //因为默认就是这样 //使用open函数打开文件 ofstream outFile2; outFile2.open(example.txt, std::ios::out);//std::ios::out可以省略,因为默认就是这样 //...... }文件的打开模式有如下几种多个打开模式使用“|”连接std::ios::in读取模式文件必须已存在否则打开失败std::ios::out写入模式如果文件存在截断文件清空内容如果文件不存在创建新文件std::ios::app追加模式如果文件不存在创建新文件std::ios::ate打开后定位到文件末尾std::ios::trunc打开时截断文件删除原有内容std::ios::binary二进制模式检查文件是否打开//通过类成员函数is_open()判断 if (!outFile.is_open()) { std::cerr 无法打开文件! std::endl; return 1; } //或者更简洁的方式 if (!outFile) { std::cerr 文件打开失败! std::endl; return 1; }通过对象实现文件读写ofstream对象实现文件写入#define _CRT_SECURE_NO_WARNINGS #includefstream #includeiostream #includestring int main() { //使用构造函数打开文件 std::ofstream outFile(example.txt, std::ios::out); if (!outFile) { std::cout 文件打开失败 std::endl; } //写入数值类型数据 outFile 1 5.55 std::endl; //写入字符串数据 outFile abcd std::endl; //写入自定义类型数据 std::string mystring i am a string; outFile mystring std::endl; }ifstream对象实现文件读取#define _CRT_SECURE_NO_WARNINGS #includefstream #includeiostream #includestring int main() { //使用构造函数打开文件 std::ifstream inFile(example.txt, std::ios::in); if (!inFile) { std::cout 文件打开失败 std::endl; } //读入数值类型数据 double x 0; inFile x; std::cout x std::endl; //读入字符串数据 char arr[20] {0}; inFile arr; std::cout arr std::endl; //读入自定义类型数据 std::string mystring; inFile mystring; std::cout mystring; }#include fstream #include iostream #include string int main() { // 打开文件 std::ifstream inFile(example.txt); if (inFile.is_open()) { // 逐行读取 std::string line; while (std::getline(inFile, line)) { std::cout line std::endl; } } else { std::cerr 无法打开文件进行读取! std::endl; } // 基础版本使用默认换行符分隔 //std::istream getline(std::istream is, std::string str); // 可指定分隔符版本 //std::istream getline(std::istream is, std::string str, char delim); return 0; }fstream对象实现文件读写#include fstream #include iostream #include string int main() { // 打开文件进行读写不截断 std::fstream ioFile(example.txt, std::ios::in | std::ios::out); if (ioFile.is_open()) { // 读取现有内容 std::string content; std::getline(ioFile, content); std::cout 读取的内容: content std::endl; // 定位到文件末尾进行追加 ioFile.seekp(0, std::ios::end); ioFile 这是追加的内容 std::endl; // 定位到文件开头重新读取 ioFile.seekg(0, std::ios::beg); while (std::getline(ioFile, content)) { std::cout content std::endl; } ioFile.close(); } return 0; }二进制读写二进制读写使用的是成员函数write和read而不再是或者运算符重载。#include fstream #include iostream //ostream write(const char* s, streamsize count);//写二进制数据 //istream read(char* s, streamsize count);//读二进制数据 int main() { // 写入二进制数据 { std::ofstream outFile(binary.bin, std::ios::binary);//这里不用|std::ios::out因为无论 //传入什么都会自动|上std::ios::out int numbers[] { 1, 2, 3, 4, 5 }; outFile.write(reinterpret_castchar*(numbers), sizeof(numbers)); } // 读取二进制数据 { std::ifstream inFile(binary.bin, std::ios::binary); int readNumbers[5]; inFile.read(reinterpret_castchar*(readNumbers), sizeof(readNumbers)); for (int i 0; i 5; i) { std::cout readNumbers[i] ; } std::cout std::endl; } return 0; }文件光标定位成员函数tellg() 是 tell get 的缩写用于返回输入文件指针的当前位置对于ifstream等输入流。tellp() 是 tell put 的缩写用于返回输出文件指针的当前位置对于ofstream等输出流。seekg()是 seek get 的缩写用于设置输入文件指针的位置对于ifstream等输入流。seekp() 是 seek put 的缩写用于设置输出文件指针的位置对于ofstream等输出流。eg:// 移动到绝对位置 file.seekg(offset); // 从文件开头偏移offset字节 // 移动到相对位置 file.seekg(offset, std::ios_base::beg); // 从开头偏移 file.seekg(offset, std::ios_base::cur); // 从当前位置偏移 file.seekg(offset, std::ios_base::end); // 从结尾偏移 // 移动到绝对位置 file.seekp(offset); // 移动到相对位置 file.seekp(offset, std::ios_base::beg); file.seekp(offset, std::ios_base::cur); file.seekp(offset, std::ios_base::end);值得一提的是tellg和tellp的返回值以及seekp和seekg的第一个参数的类型不是整型而是一个自定义类型std::streampos但它可以用整型去构造。状态检查成员函数good()检查流是否正常eof()检查是否到达文件末尾fail()检查是否发生非致命错误bad()检查是否发生致命错误clear()清除错误标志文件关闭使用文件流类的close函数例如inFile.close()。文章参考C 中文件 IO 操作详解_c文件io-CSDN博客
返回列表