使用c ++同时读取和写入相同的文件

时间:2017-06-08 21:31:29

标签: c++ file fstream getline

我试图读取和写入文件,因为我循环了它的行。在每一行,我将进行一次评估,以确定是否要将其写入文件或跳过它并转到下一行。这基本上是我到目前为止的骨架。

void readFile(char* fileName)
{
    char line[1024];
    fstream file("test.file", ios::in | ios::out);

    if(file.is_open())
    {
        while(file.getline(line,MAX_BUFFER))
        {

            //evaluation

            file.seekg(file.tellp());
            file << line;
            file.seekp(file.tellg());
        }
    }
}

当我读到这些内容时,我似乎遇到了复制到行变量中的字符串起始索引的问题。例如,我可能期望行变量中的字符串为&#34; 000/123 / FH /&#34;但它实际上是作为&#34; 123 / FH /&#34;。我怀疑我有file.seekg(file.tellp())和file.seekp(file.tellg())的问题,但我不确定它是什么。

3 个答案:

答案 0 :(得分:3)

从您的代码 [1] 和问题描述中不清楚文件中的内容以及您期望的原因&#34; 000/123 / FH /&#34;,但我可以声明getline函数是缓冲输入,并且您没有代码来访问缓冲区。通常,不建议同时使用缓冲和非缓冲的i / o,因为它需要深入了解缓冲机制,然后依赖于该机制,不会随着库的升级而改变。

您似乎想要执行字节或字符 [2] 级别操作。对于小文件,您应该将整个文件读入内存,操作它,然后覆盖原始文件,需要打开,读取,关闭,打开,写入,关闭序列。对于大型文件,您需要使用fread和/或其他一些较低级别的C库函数。

这样做的最好方法是,因为你正在使用C ++,就是创建你自己的类来处理读取并包括行分隔符 [3] 到其中一个架式循环缓冲区(使用malloc或插件分配器,就像类似STL的容器一样)或循环缓冲区,作为模板在静态分配的字节数组上开发(如果你想要高速度和低资源利用率) 。尺寸必须至少与后一种情况下的最长线一样大。 [4]

无论哪种方式,您都希望添加到类中以二进制模式打开文件,并公开所需的方法以对任意行进行行级操作。有人说(我个人同意)在C ++中利用Bjarne Stroustrup的类封装是类更容易仔细测试。这样的行操作类将封装随机访问C函数和无缓冲的i / o,并留下最大化速度的机会,同时允许在系统和应用程序中使用即插即用。

备注

[1]寻找当前位置只是测试函数,并且在代码的当前状态下还没有重新定位当前文件指针。

[2]请注意,在当今的计算环境中,字符和字节级操作之间存在差异,其中utf-8或其他一些unicode标准现在在许多域中比ASCII更常见,尤其是网络

[3]请注意,行分隔符取决于操作系统,版本,有时还取决于设置。

[4]循环缓冲区在速度方面的优势在于,您可以一次使用fread读取多行,并使用快速迭代查找下一行。

答案 1 :(得分:0)

您正在阅读和写入您可能最终在文件中出现重复行的文件。

你可以发现this非常有用。想象你第一次到达while循环。并从文件的开头file.getline(line,MAX_BUFFER)开始。现在get指针(用于读取)将MAX_BUFFER个位置移动到文件的开头(起点)

在“您确定”后写回文件seekp()有助于针对参考点指定您要写入的位置,语法:file.seekp(num_bytes,"ref");其中{{1}将是ref

在阅读后的代码中

ios::beg(beginning), ios::end, ios::cur(current possition in file)

找到一种方法,使用 while(file.good()) { file.getline(line,MAX_BUFFER); ... if(//for some reasone you want to write back) { // set put-pointer to location for writing file.seekp(num_bytes, "ref"); file << line; } //set get-pointer to desired location for the next read file.seekg(num_bytes, "ref"); } 来引用与引用相关的位置。

答案 2 :(得分:0)

从Douglas Daseeco的回复中获取灵感,我通过简单地读取现有文件,将其行写入新文件,然后重命名新文件以覆盖原始文件来解决我的问题。下面是我的解决方案的骨架。

char line[1024];

ifstream inFile("test.file");
ofstream outFile("testOut.file");

if(inFile.is_open() && outFile.is_open())
{               
    while(inFile.getline(line,1024))
    {

        // do some evaluation

        if(keep)
        {
            outFile << line;
            outFile << "\n";
        }
    }
    inFile.close();
    outFile.close();
    rename("testOut.file","test.file");
}