是否可以在 C# 中读取和写入同一个文本文件

Is it possible to read from and write to the same text file in C#

情况是这样的。我有超过 1500 个 SQL(文本)文件,其中包含“在 CREATE TABLE 语句后向某些用户授予某些 table 某些特权。我需要将它们从原始文件中删除并将 GRANT 语句放在它们自己的文件中。有时 GRANT 在一行上,有时它们分成多行。例如:

  GRANT SELECT ON XYZ.TABLE1 TO MYROLE1 ;
  GRANT
  SELECT ON XYZ.TABLE1 TO MYROLE2 ;
  GRANT
  DELETE,
  INSERT,
  SELECT,
  UPDATE ON XYZ.TABLE1 TO MYROLE3;

我通读文件直到到达 GRANT,然后构建一个字符串,其中包含从 GRANT 到分号的文本,然后我将其写到另一个文件。我有一个用 Delphi (Pascal) 编写的应用程序,这部分效果很好。我想做的是在阅读并处理完我想要的行之后,我想从原始文本文件中删除该行。我无法在 Delphi 中执行此操作。唯一的解决方案是逐行读取文件并将文件写回另一个文件,不包括我不想要的行,同时将 GRANTS 写入另一个文件。然后删除原来的并重命名新的。太多的处理和风险。

我查看了在 C# 中使用 StreamReader 和 StreamWriter,但情况似乎与 Delphi 类似。我可以读取或写入,但我不能同时对同一个文件执行这两项操作。

如果有任何意见或建议,我将不胜感激。

谢谢

如果您认为 "way too much processing and risk" 在 生成一个新的临时文件而没有您不想要的行并替换原始文件: 那么请考虑您的替代方案'重新希望实现。

    Line 1
    Line 2
    Delete this line
+-->Line 4
|   Line 5
|
+- Read position marker after reading line to be deleted

如果在阅读时立即删除该行,则后面的行必须移回删除第 3 行后留下的 "empty space"。为了确保您下次阅读 "Line 4",您必须 回溯 您的 read-position-marker。回溯的正确数量是多少? 可变长度的"line",或删除行的字符数

你认为的"risky"选项实际上是安全选项!


如果你想在处理时删除,你可以使用给你那种印象的抽象。但是您失去了流处理的好处,并没有真正消除您最初担心的任何风险。

例如将整个文件加载到字符串列表中;例如数组、向量或 TStringList(在 Delphi 中)。迭代列表并删除不需要的项目。最后将列表保存回文件。

这种方法有以下缺点:

  • 潜在的高内存开销,因为您加载整个文件而不是流的小缓冲区。
  • 您有 mid-process 失败且无法恢复的风险,因为您的工作是 all-or-nothing.
  • 您必须处理您选择用来保存字符串列表的特定容器的细微差别。
    • 在某些情况下(例如 TStringList),您可能仍需要以与之前描述类似的方式回溯您的位置标记。
    • 对于数组,每次删除内容时都必须将所有行复制回 1 个位置,这会带来巨大的性能成本。 (同样的事情发生在 TStringList 中,尽管它对你隐藏了。)
    • 只要您修改列表,某些容器的迭代器就会失效。这意味着您在任何情况下都必须复制到没有 'deleted lines' 的新列表。 更多内存开销。

总之,采取安全选项。使用单独的读写流;写入临时文件,完成后重命名。 它会让你省去头痛。