【问题标题】:How to efficiently remove last line in a file and append new text for large file?如何有效地删除文件中的最后一行并为大文件附加新文本?
【发布时间】:2019-10-07 20:37:31
【问题描述】:

替换文件中最后一行的有效方法是什么?

我希望我的文件以“]”结尾,我想将“]”替换为将再次以“]”结尾的新数据。

这只是一个文件非常大的例子......

Old:
[
a
b
c
]

新:

[
a
b
c
d
e
]

我可以完全控制文件的编写和创建方式。

编辑:

    // mockData.json
    //[
    //    a
    //    b
    //    c
    //]

    var fileName = "mockData.json";
    var origData = File.ReadAllLines(fileName);
    origData[origData.Length - 1] = " d\n e\n]";
    File.WriteAllLines(fileName, origData);

【问题讨论】:

  • I have full control of how files are written, created. 如果是这样,为什么你不告诉我们你是怎么做的,你做了什么。
  • 我没做好。 “我有完全的控制权”意味着如果有人建议特定的编码它不会是障碍。我没有从第三方获得初始文件。
  • 所以向我们展示你的低效方法,然后我们可以从那里开始。

标签: c# .net string file


【解决方案1】:

对于下面的这段代码,例程非常简单,因为您已经知道文件中的最后一个字符是 ]。因此,您所要做的就是读取文件的最后一个字符,如果它是 char ],那么您就得到了该文件。如果发生这种情况,您将截断文件中的最后一个字节并将文本附加到该文件中。然后添加 char ] 以保留格式。请注意,这是针对 ASCII 编码的,如果您的最后一个字符是大于一个字节的其他字符,那么您将不得不稍微修复代码。

using System;
using System.IO;
using System.Text;

public class FSSeek
{
    public static void Main()
    {
        string fileName = "test.txt";
        char lastChar = ']';
        string toBeAppend = "d\ne\n";

        using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite))
        {
            fs.Seek(-1, SeekOrigin.End);
            if ( Convert.ToChar(fs.ReadByte()) == lastChar ){
                fs.SetLength(fs.Length - 1);
                fs.Write(Encoding.ASCII.GetBytes(toBeAppend));
                fs.WriteByte(Convert.ToByte(lastChar));
            }            

        }
    }
}

test.txt 内容:

[
a
b
c
]

【讨论】:

  • 我正在使用 .Net Core,对缺少签名的小修改: var toBeAppendBytes = Encoding.ASCII.GetBytes(toBeAppend); fs.Write(toBeAppendBytes, 0, toBeAppendBytes.Length);,做得好,我开始调查这个问题,因为有人将问题标记为重复写入字节到特定位置
【解决方案2】:

我的建议是这样的:

读取文件,删除内容的最后一个字符,然后再次将其写入文件。

string fileContent = File.ReadAllText("file.path");
// Remove the last character
fileContent = fileContent.Remove(fileContent.Length - 1);
string newContent = "Your new content";
fileContent += newContent;
// Write content back to the file
File.WriteAllText("file.path", fileContent);

【讨论】:

  • 这看起来会完成请求的任务,但我认为它不满足问题的“有效”条件。问题表明要修改的文件“非常大”,虽然不清楚这意味着什么(千字节?兆字节?千兆字节?)如果我们假设file.path 是,比如说,1 GB,那么我相信这段代码将会结束使用多于 3 GB 的内存。代码短,但内存占用大。
【解决方案3】:

您可以像这样通过InsertRange() 将范围插入列表,lines.Count - 1 将确保您在最后一行之前插入。

var linesToAdd = new List<string>() { "d", "e" };
var lines = File.ReadAllLines(path).ToList();
lines.InsertRange(lines.Count - 1, linesToAdd);
File.WriteAllLines(path, lines);

显然这需要错误处理,例如您的原始文件末尾没有]

【讨论】:

  • 能有更好的方法吗,我可以看到有向后读取文件的解决方案,但是应该正确设置编码以便无错误地导航,如果读取“]”我可以使用该信息将其替换为新数据...
  • 您的问题没有明确定义,并且您拒绝共享正确的代码。什么定义了“更好”?更好取决于情况,编程中没有包罗万象的“更好”。
  • 放弃,所以 Up + Down = 0 :),因为您实际上发布的版本几乎与我得到的版本完全相同
  • 我没有投反对票,但问题要求一种“有效方式”在终止 ] 之前插入新行。将整个文件存储在内存中(实际上是两次:首先使用ReadAllLines(),然后再次使用ToList()),就像这段代码一样,在我看来效率不高,但公平地说,这个问题并没有定义什么方式“效率”是衡量的,也不是这个“大文件”有多大。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-11
相关资源
最近更新 更多