最近几天在做一个简易的社交系统’/*其实是数据结构大作业*/’,频繁地用到文件操作。其中比较捉急的是对于文件内容的改写。

文件修改

我觉得修改可以分为两种,一种是定长修改,一种是长度发生变化的修改。两种修改都有一种通用的修改方法,不过这个方法非常没有效率,那就是建立一个tmp文件,把修改过后的内容放到里面,然后删掉原文件把tmp文件改成原文件的名字。这个方法显然不是很科学,而且如果文件内容很大,那么时间可能会挺长的。

探索定长修改

抛去上面的方法不说,定长修改的方法很简单,就是同时以ios::inios::out打开文件,不过其中还是有些需要注意的。

在进行文件写的时候(非二进制),文件指针很成问题。举个例子:比如文件的内容是”100100100”,写入了三个int类型的变量,值为100。接下来我如果想改变第二个100,使其变成200,文件指针需要移动3位,因为前面有三个字符。这时候指针是一个字符一个字符的移动的

#include < iostream > 
#include < fstream >
using namespace std;

int main() {
    ofstream ofs("cece.txt", ios::out);
    int x = 100;
    ofs << x << x << x;
    ofs.close();
    ofs.open("cece.txt", ios::out | ios:: in );
    x = 200;
    ofs.seekp(3);
    ofs << x;
}

而如果把文件换成二进制的写,那么情况就会有些变化,如果还是想改写第二个100的内容,那么文件指针就需要指向sizeof(int)。指针是一个byte一个byte地移动。 int存入的方式就是以int类型,将其原封写入文件,所以二进制的读写比较简单。

#include <iostream> 
#include <fstream> 
using namespace std;  

int main()  
{  
    ofstream ofs("cece.txt", ios::out | ios::binary);  
	int x = 100;  
	ofs.write((char *)&x, sizeof(x));  
	ofs.write((char *)&x, sizeof(x));  
	ofs.write((char *)&x, sizeof(x));  
	ofs.close();  

    ofs.open("cece.txt", ios::out | ios::in | ios::binary);  
    x = 200;  
    ofs.seekp(sizeof(int));  
    ofs.write((char *)&x, sizeof(x));  
   }

经实验表明,ios::app Mode下是不能移动文件指针的,而且这个时候tellp()是0。此模式下只能在后面追加着写。

另外,如果想要获得指向末尾的位置指针,需要以下写法,这个时候如果文件内没有内容,那么pointer的值会是-1。

ofs.seekp(0, ios::end);  
pointer = ofs.tellp();  

不等长修改

等长修改就是这样,不等长修改的话,如果长度小于原来,可以写进去,然后添0,或者别的,大于原来的,目前只会tmp覆盖原文件的方法。

就是这样,嗯。本来是一定要用不等长修改的,但是后来删除没有实现,也就没有做。

评论