在文件中间进行覆盖写入

5
问题是我正在使用fseek在文件中间,下一步存在长度为m的一些字节,我想用长度为n的字节替换它们。简单的write会保留m-n个字节。如果m > n,如果m < n,一些(n-m)我不想改变的字节将被覆盖。

我只想用可变长度的字节替换已知的startPos到endPos字节流。最好的解决方案是什么?

--编辑-- 虽然可以通过备份来完成,但是否存在直接解决方案? 这太混乱了?而且编码质量很差。

o = fopen(original, 'r')
b = fopen(backup, 'w')
while(fpos(o) <= startPos){
    buffer += fgetc(o)
}
fwrite(b, buffer)
fwrite(b, replaceMentBytes)
buffer = ""
fseek(o, endPos)
while(!feof(o)){
    buffer += fgetc(o)
}
fwrite(b, buffer)

//现在将备份复制到原始文件中

@user256007,我觉得你的标点符号和一些字母大小写让我感到困惑。 - Yantao Xie
请查看http://blogs.msdn.com/b/oldnewthing/archive/2010/12/01/10097859.aspx。 - MSalters
2个回答

5

最可靠的解决方案是从头开始重新编写整个文件。大多数操作系统只允许您覆盖字节,而不是插入或删除它们,因此为了实现这一点,您必须基本上复制文件,在复制过程中替换目标字节。


就像@Thanatos所说的那样,您只能覆盖或追加字节。如果您需要插入,则通常必须创建一个新文件,向其中写入内容,然后将其移动到原始位置。 - Justin Spahr-Summers

0
使用fstream库,这里是一个简单的实现,可能是其他人正在说的。
/**
 * Overwrite a file while replacing certain positions
 */

#include <iostream>
#include <fstream>

using namespace std;

int readFile(char* filename,int& len,char*& result)
{
    ifstream in(filename); // Open the file
    if(!in.is_open())
        return 1;

    // Get file length
    in.seekg(0,ios::end);
    len = (int)in.tellg();
    in.seekg(0,ios::beg);

    // Initialize result
    result = new char[len+1];

    // Read the file and return its value
    in.read(result,len);

    // Close the file
    in.close();

    return 0;
}

void writeFile(char* filename,char* data,int from,int to,int origdata,int trunc)
{
    ofstream out;
    (trunc == 1) ? out.open(filename,ios::trunc) : out.open(filename,ios::app); // Simple ternary statement to figure out what we need to do

    // Find position if we're not starting from the beginning
    if(trunc == 1)
        out.seekp(from);
     else // Otherwise send us to the beginning
        out.seekp(0,ios::beg);

    if(origdata == 1) // If we need to start in the middle of the data, let's do so
        for(int i=0;i<(to-from);++i)
            data[i] = data[from+i]; // Reverse copy

    out.write(data,(to-from));

    out.close();
}

int main()
{
    char* read;
    int len = 0;
    if(readFile("something.txt",len,read) != 0)
    {
        cout<< "An error occurred!" << endl;
        return 0;
    }

    // Example to make this work
    cout<< "Writing new file...\r\n";
    writeFile("something.txt",read,0,20,1,1); // Initial write
    writeFile("something.txt","\r\nsome other mumbo jumbo",21,45,0,0);
    writeFile("something.txt",read,46,100,1,0); // Replace the rest of the file back

    cout<< "Done!\r\n";
    cin.get(); // Pause
    delete [] read;
    return 0;
}

你可以在readFile函数中完成所有的查找,或者直接在字符数组(在这种情况下是read)中进行。从那里开始,你可以存储位置并适当地使用writeFile()函数。

祝你好运!
Dennis M.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接