1

我在重写前 2,5KB 文件时遇到了小问题。我的代码应该读取 2KB 和 512 字节来动态分配内存,然后重写更大文件的特定字节。

f = fopen(argv[2], "rb");
if(f==NULL)
    printf("File doesn't exist!");
fseek(f, 0, SEEK_SET);
data = calloc(2*1024+512, 1);
fread(data, 1, 2*1024+512, f);
fclose(f);

f = fopen(argv[1], "ab");
if(f==NULL)
    printf("File doesn't exist!");
fseek(f, 0, SEEK_SET);
fwrite(data, 1, 446, f);
fseek(f, 512, SEEK_SET);
fwrite(((char*)data)+512, 1, 2*1024, f);
fclose(f);

当我尝试使用wb模式时,它会删除第二个文件的内容。当我使用ab模式并寻找文件的开头时,以前的内容会附加在末尾。

有没有办法(使用标准 C 库)重写文件内容而不附加和复制写入文件的剩余内容?请帮忙。

4

2 回答 2

3

你想要ab++表示更新模式。如果文件存在,它只会被打开并且内容不会改变。wb它本身只会删除原始文件并创建一个新文件。

于 2013-08-16T15:32:38.193 回答
2

"rb"模式打开位于开头的文件;初始fseek()是多余的。

第二个 open with"ab"打开文件以追加模式写入。fseek()无论您事先执行什么操作,所有写入都将发生在文件末尾。

您可以明智地使用模式"rb+"打开文件一次以进行读取和写入:

if ((f = fopen(argv[2], "rb+")) != 0)
{
    char *data = calloc(2*1024+512, 1);   // Missing error check
    fread(data, 1, 2*1024+512, f);        // Missing error check
    // Modify data?
    fseek(f, 0, SEEK_SET);
    fwrite(data, 1, 446, f);
    fseek(f, 512, SEEK_SET);
    fwrite(((char*)data)+512, 1, 2*1024, f);
    fclose(f);
}

代码应该在使用之前检查是否calloc()成功data;它还应该错误检查fread()以确保它得到了预期的数据。据推测,中间的某些东西会修改从文件中读取的数据。


ISO/IEC 9899:2011(当前的 C 标准)对模式有这样的说法——除了C11 中新增的标志fopen()外,之前的标准也有同样的说法:x

§7.21.5.3fopen功能

¶3参数mode指向一个字符串。如果字符串是以下之一,则文件以指示的模式打开。否则,行为未定义。271)

  • r打开文本文件以供阅读
  • w截断为零长度或创建文本文件进行写入
  • wx创建用于写作的文本文件
  • a附加; 打开或创建文本文件以在文件末尾写入
  • rb打开二进制文件进行读取
  • wb截断为零长度或创建二进制文件进行写入
  • wbx创建用于写入的二进制文件
  • ab附加; 打开或创建二进制文件以在文件末尾写入
  • r+打开文本文件进行更新(读取和写入)
  • w+截断为零长度或创建文本文件进行更新
  • w+x创建用于更新的文本文件
  • a+附加; 打开或创建文本文件以进行更新,在文件末尾写入
  • r+brb+打开二进制文件进行更新(读写)
  • w+bwb+截断为零长度或创建二进制文件进行更新
  • w+bxwb+x创建二进制文件进行更新
  • a+bab+附加;打开或创建二进制文件进行更新,在文件末尾写入

271)如果字符串以上述序列之一开始,则实现可能会选择忽略剩余的字符,或者它可能会使用它们来选择不同类型的文件(其中一些可能不符合 §7.21.2 中的属性)。

于 2013-08-16T16:12:20.810 回答