zoukankan      html  css  js  c++  java
  • 文件读写

    1、文件的基本内容

    (1)文件和流的关系

    可以将顺序文件看作一个有限字符构成的顺序字符流,然后像对
    cin, cout 一样的读写。

    (2)创建文件

    方式一:创建时直接关联文件(初始化)

    #include <fstream> // 包含头文件
    	ofstream outFile(“clients.dat”, ios::out|ios::binary);//创建文件
    

    参数:

    • clients.dat”
      要创建的文件的名字
    • 文件打开方式:
      • ios:out:输出到文件, 删除原有内容。
      • ios::app:输出到文件, 保留原有内容,总是在尾部添加。
    • ios::binary 以二进制文件格式打开文件

    方式二:先创建ofstream对象,再用 open函数打开

    	ofstream fout;
    	fout.open("test.out",ios::out|ios::binary);
    
    (3)判断是否成功打开文件
    if(!fout){
    	cout << “File open error!<<endl;
    }
    
    (4)文件名的绝对路径和相对路径
    • 文件名可以给出绝对路径,也可以给相对路径。
    • 没有交代路径信息,就是在当前文件夹下找文件。
    • C++的文件分隔符为 ,例如:“c: mpmydirsome.txt”
    (5)文件的读写指针
    • 对于输入文件,有一个读指针;
    • 对于输出文件,有一个写指针;
    • 对于输入输出文件,有一个读写指针;
    • 文件指针的作用:标识文件操作的当前位置, 该指针在哪里,读写操作就在哪里进行。

    注意: 文件指针不同于普通的指针,它不是指针类型的,但是其功能与普通指针一样,都是指出某一位置。

    文件指针举栗子:

    void main(){
    //写指针
    	ofstream fout("a1.out",ios::app); 	//以添加方式打开
    	long location = fout.tellp();		//取得写指针的位置
    	location = 10;
    	fout.seekp(location);				// 将写指针移动到第10个字节处
    	fout.seekp(location,ios::beg);		//从头数location
    	fout.seekp(location,ios::cur); 		//从当前位置数location
    	fout.seekp(location,ios::end); 		//从尾部数location
    
    //读写指针
    	ifstream fin(“a1.in”,ios::ate);	//打开文件,定位文件指针到文件尾
    	long location = fin.tellg();		//取得读指针的位置
    	location = 10L;
    	fin.seekg(location); 				// 将读指针移动到第10个字节处
    	fin.seekg(location,ios::beg); 		//从头数location
    	fin.seekg(location,ios::cur); 		//从当前位置数location
    	fin.seekg(location,ios::end); 		//从尾部数location
    }
    

    注意:location可以为负数。
    C++ 获取文件长度的方式:
    将文件指针置于末尾,获取文件指针的位置。这个获取位置函数返回的值就是文件的长度,即文件的字节数。

    (6)显式关闭文件

    为什么要关闭文件?

    • 避免不能打开其他文件
      有些操作系统打开文件的数量是一定的,如果每打开一个文件不关闭的话,可能造成打不开其它任何文件问题。

    • 避免数据丢失
      直接向硬盘写入数据的话,硬盘的访问速度很慢。因此现在的操作系统一般先将数据写入到内存缓冲区中,达到一定的条件后( 刷新缓冲区或者缓冲区满了,或者其他条件),再写入硬盘中的文件内。此时才是真正的访问硬盘。如果没有关闭文件,如果我们是向硬盘中的文件写入数据的话,那么就有可能还有一部分数据在内存缓冲区中,没有写入到文件上。

    void main(){
    	ifstream fin(“test.dat”,ios::in);
    	fin.close();
    	
    	ofstream fout(“test.dat”,ios::out);
    	fout.close();
    }
    

    2、文件读写函数

    (1) ifstream 和 fstream的成员函数
    istream& read (char* s, long n);
    

    功能: 将文件读指针指向的地方的n个字节内容,读入到内存地址s,然后将文件读指针向后移动n字节 (以ios::in方式打开文件时,文件读指针开始指向文件开头) 。

    (2) ofstream 和 fstream的成员函数:
    istream& write (const char* s, long n);
    

    功能: 将内存地址s处的n个字节内容,写入到文件中写指针指向的位置,然后将文件写指针向后移动n字节(以ios::out方式打开文件时,文件写指针开始指向文件开头, 以ios::app方式打开文件时,文件写指针开始指向文件尾部 ) 。

    注意: 因为文件流也是流,所以流的成员函数和流操作算子也同样适用于文件流。

    3、字符文件读写

    写一个程序,将文件 in.txt 里面的整数排序后,输出到out.txt

    例如,若in.txt 的内容为:
    1 234 9 45 6 879
    则执行本程序后,生成的out.txt的内容为:
    1 6 9 45 234 879

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    int main() {
    	vector<int> v;
    	ifstream srcFile("in.txt",ios::in);
    	ofstream destFile("out.txt",ios::out);
    	int x;
    	while( srcFile >> x )
    		v.push_back(x);
    	sort(v.begin(),v.end());
    	for( int i = 0;i < v.size();i ++ )
    		destFile << v[i] << " ";
    	destFile.close();
    	srcFile.close();
    	return 0;
    }
    

    3、二进制文件读写

    (1)在文件中写入和读取一个整数
    #include <iostream>
    #include <fstream>
    using namespace std;
    int main() {
    	ofstream fout("some.dat", ios::out | ios::binary);	//写方式、二进制方式打开
    	int x=120;
    	fout.write( (const char *)(&x), sizeof(int) );		//写入
    	fout.close();										//关闭文件
    	ifstream fin("some.dat",ios::in | ios::binary); 	//读方式、二进制方式打开
    	int y;
    	fin.read((char * ) & y,sizeof(int));				//读出
    	fin.close();										//关闭文件
    	cout << y <<endl;									//显示
    	return 0;
    }
    
    (2)从键盘输入几个学生的姓名的成绩,并以二进制文件形式保存
    #include <iostream>
    #include <fstream>
    using namespace std;
    struct Student {
    	char name[20];
    	int score;
    };
    int main() {
    	Student s;
    	ofstream OutFile( "c:\tmp\students.dat",ios::out|ios::binary);
    	while( cin >> s.name >> s.score )
    	OutFile.write( (char * ) & s, sizeof( s) );
    	OutFile.close();
    	return 0;
    }
    /*
    输入:
    Tom 60
    Jack 80
    Jane 40
    ^Z+回车
    
    则形成的 students.dat 为 72字节,用 记事本打开,呈现:
    Tom 烫烫烫烫烫烫烫烫< Jack 烫烫烫烫烫烫烫蘌 Jane 烫烫烫烫烫
    烫烫?
    
    */
    
    (3)将 students.dat 文件的内容读出并显示
    int main() {
    	Student s;
    	ifstream inFile("students.dat",ios::in | ios::binary );
    	if(!inFile) {
    		cout << "error" <<endl;
    		return 0;
    	}
    	while( inFile.read( (char* ) & s, sizeof(s) ) ) {
    		int readedBytes = inFile.gcount(); //看刚才读了多少字节
    		cout << s.name << " " << s.score << endl;
    	}
    	inFile.close();
    	return 0;
    }
    /*输出:
    Tom 60
    Jack 80
    Jane 40
    */
    
    (4)将 students.dat 文件的Jane的名字改成Mike
    int main()
    {
    	Student s;
    	fstream iofile( "c:\tmp\students.dat",
    	ios::in|ios::out|ios::binary);
    	if( !iofile) {
    		cout << "error" ;
    		return 0;
    	}
    	iofile.seekp( 2 * sizeof(s),ios::beg); //定位写指针到第三个记录
    	iofile.write("Mike",strlen("Mike")+1);//这里要多写入一个字节''
    	iofile.seekg(0,ios::beg); //定位读指针到开头
    	while( iofile.read( (char* ) & s, sizeof(s)) )
    		cout << s.name << " " << s.score << endl;
    	iofile.close();
    	return 0;
    }
    
    (5)文件拷贝程序mycopy 示例
    /*用法示例:
    mycopy src.dat dest.dat
    即将 src.dat 拷贝到 dest.dat 如果 dest.dat 原来就有,则原来的文件会被覆
    盖 */
    #include <iostream>
    #include <fstream>
    using namespace std;
    int main(int argc, char * argv[])
    {
    	if( argc != 3 ) {
    		cout << "File name missing!" << endl;
    		return 0;
    	}
    
    	ifstream inFile(argv[1],ios::binary|ios::in); //打开文件用于读
    	if( ! inFile ) {
    		cout << "Source file open error." << endl;
    		return 0;
    	}
    	ofstream outFile(argv[2],ios::binary|ios::out); //打开文件用于写
    	if( !outFile) {
    		cout << "New file open error." << endl;
    		inFile.close(); //打开的文件一定要关闭
    		return 0;
    	}
    	char c;
    	while( inFile.get(c)) //每次读取一个字符
    		outFile.put(c);//每次写入一个字符
    	outFile.close();
    	inFile.close();
    	return 0;
    }
    /*
    输出:
    Tom 60
    Jack 80
    Mike 40
    */
    

    4、字符文件与二进制文件的区别

    文件格式指的是创建文件和使用文件的人的一个约定,即约定文件的每一部分内容是什么形式的(二进制的、字符串的等),一起其他一些约定。本质上,不同格式的数据最终都是二进制串。只是格式不同(数据的约定不同),解析的方式就不同。比如二进制文件就不能采用记事本取解析。

    字符格式文件,存储数据的格式就是字符串的格式,此时我们用记事本打开的话,我们是可以看懂的。二进制格式文件,其中的字符部分我们还是能够看懂的,但是其他数据类型是二进制的形式,只有知道这些数据是怎么排布的人,才能够知道怎么使用这些数据。(通过类型强转)。因此如果用字符编码进行解码的话就会出现乱码现象。 而记事本一般就是采用字符编码进行解析数据,因而我们使用记事本打开二进制文件,就会显示乱码。

    (1)二种格式的内存差异:

    一般二进制文件比纯文本文件更加节约内存。因为纯文本文件需要将空格、换行符存入。另一方面,对于比较大整型数字,比如1000000000,使用纯文本文件需要存10个字节,而使用二进制形式只需要存4个字节。

    (2)查找差异:

    二进制文件可以以固定空间进行存储,可以采用二分查找,查找速度更快。而文本文件,不行样本信息差异大,空间上不固定,查找麻烦。 (空间固定才可以使用二分查找)

    不同的平台,有些操作的符号是不同的,因此处理同一类型的文件,代码上可能会有差异,下面是平台差异。

    (3)不同平台的换行符差异
    • Linux,Unix下的换行符号:' ' (ASCII码: 0x0a)
    • Windows 下的换行符号:' ' (ASCII码: 0x0d0a) (endl 就是 ' ')
    • Mac OS下的换行符号: ' ' (ASCII码:0x0d)

    上述不同导致 Linux, Mac OS 文本文件在Windows 记事本中打开时不换行。

    (4)不同平台下打开文件方式有所差异
    • Unix/Linux下打开文件,用不用 ios::binary 没区别。
    • Windows下打开文件,如果不用 ios::binary,则:读取文件时,所有的 ' ’会被当做一个字符' '处理,即少读了一个字符' '。写入文件时,写入单独的' '时,系统自动在前面加一个' ',即多写了一个' '。(有时这样违背我们的本意,例如图像处理里面,也许数据本身就真的是 或者 。)

    注意: 我们处理的大部分文件都是二进制文件,而不是文本文件。

  • 相关阅读:
    统计创建对象个数
    动手动脑
    开学第一周心得
    放假第五周总结
    放假第四周总结
    第一周总结
    04-异常处理-动手动脑
    03-继承与多态-动手动脑
    02-类和对象-跟踪类对象创建个数
    02-类和对象-动手动脑
  • 原文地址:https://www.cnblogs.com/lasnitch/p/12764237.html
Copyright © 2011-2022 走看看