【问题标题】:ANSI C - Text File: Modify Line?ANSI C - 文本文件:修改行?
【发布时间】:2021-05-03 13:43:27
【问题描述】:

我有这个文本文件:

Line 1. "house"
Line 2. "dog"
Line 3. "mouse"
Line 4. "car"
...

我想更改第 2 行。新第 2 行中的“狗”。“卡片”

我该怎么办?

谢谢!

(对不起我的英语不好)

【问题讨论】:

  • 通常的方法是打开文件进行输入,并打开一个新文件进行输出。然后处理输入文件并根据需要创建新文件。关闭这两个文件后,删除原始输入文件并重命名输出文件。

标签: c file text ansi


【解决方案1】:

您不能内联编辑磁盘文件。您必须遵循以下流程:

  • 读取文件数据到缓冲区,(fopen() -> fread()/fgets())

  • 然后删除旧文件,(unlink()/remove())

  • 然后修改缓冲区中的数据,

  • 将缓冲区写回新文件,(fwrite)

  • 将其重命名为原始文件。 (rename())

【讨论】:

  • @gda2it :我不相信提供工作代码。代码将为 OP 解决问题,但他可能会选择不环顾/研究“外星人”函数的用法(例如unlink),这对他将来没有用处。他可能会回到这里再次问同样的问题。
  • 通常情况下,不需要删除旧文件,而且您不应该明确这样做。只需从一个文件中读取,写入一个新的临时文件,完成后,用新文件自动重命名/替换原始文件。通过等到新文件完全填充,您可以避免(大部分)丢失/损坏数据的风险;原始文件仍然存在(并且正确/完整),或者已被新文件原子替换(在替换发生之前是正确/完整的)。
【解决方案2】:

你的程序可能是这样的:

#include <stdio.h>
#include <stdlib.h>

#define MAX_LINE_LENGTH 1000

int main()
{
  FILE * fp_src, *fp_dest;
  char line[MAX_LINE_LENGTH];

  fp_src = fopen("PATH_TO_FILE\\test.txt", "r"); // This is the file to change
  if (fp_src == NULL)
    exit(EXIT_FAILURE);

  fp_dest = fopen("PATH_TO_FILE\\test.txt_temp", "w"); // This file will be created
  if (fp_dest == NULL)
    exit(EXIT_FAILURE);


  while (fgets(line, 1000, fp_src) != NULL) {

    if (strncmp(line, "Line 2.", 7) == 0) {
      fputs("Line 2. \"cards\"\n", fp_dest);
      printf("Applied new content: %s", "Line 2. \"cards\"\n");
    }
    else {
      fputs(line, fp_dest);
      printf("Took original line: %s", line);
    }

  }

  fclose(fp_src);
  fclose(fp_dest);

  unlink("PATH_TO_FILE\\test.txt");
  rename("PATH_TO_FILE\\test.txt_temp", "PATH_TO_FILE\\test.txt");

  exit(EXIT_SUCCESS);
}

将此解决方案应用于某些生产系统时应考虑以下事项:

  • 最大行长 1000 是否满足您的需求 - 也许您想提出一种解决方案,使用 malloc() 为一行动态分配内存
  • 您应该使用一些 random-filename-generator 来生成临时文件并确保它不存在,因此您不会覆盖现有文件
  • 对于大文件,这种方法可能不是最好的,因为您有效地将文件内容两次保存在内存中

【讨论】:

  • 我会放弃unlink; POSIX rename 已经保证了原子替换,因此明确地unlinking 首先引入了一个(简短的)窗口,在该窗口中程序可能会死掉,并且旧文件将消失,其中既没有旧数据也没有新数据。如果你在 Windows 上,你会跳过 rename (这违反了 POSIX 不进行原子替换)并使用 MoveFileExMOVEFILE_REPLACE_EXISTING 标志来获得相同的行为。
猜你喜欢
  • 2014-06-13
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
相关资源
最近更新 更多