通过 C# 就地编辑文本文件

发布于 2024-09-06 22:19:41 字数 156 浏览 2 评论 0原文

我有一个巨大的文本文件,大小> 4GB,我想以编程方式替换其中的一些文本。我知道必须替换文本的行号,但问题是我不想将所有文本(以及替换的行)复制到第二个文件。我必须在源文件中执行此操作。有没有办法在 C# 中做到这一点?

必须替换的文本与源文本的大小完全相同(如果这有帮助)。

I have a huge text file, size > 4GB and I want to replace some text in it programmatically. I know the line number at which I have to replace the text but the problem is that I do not want to copy all the text (along with my replaced line) to a second file. I have to do this within the source file. Is there a way to do this in C#?

The text which has to be replaced is exactly the same size as the source text (if this helps).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

小傻瓜 2024-09-13 22:19:41

由于文件太大,您可能需要查看 .NET 4.0 对 内存映射文件。基本上,您需要将文件/流指针移动到文件中的位置,覆盖该位置,然后将文件刷新到磁盘。您不需要将整个文件加载到内存中。

例如,在不使用内存映射文件的情况下,以下内容将覆盖 ascii 文件的一部分。 Args 是输入文件、从零开始的起始索引和新文本。

    static void Main(string[] args)
    {
        string inputFilename = args[0];
        int startIndex = int.Parse(args[1]);
        string newText = args[2];

        using (FileStream fs = new FileStream(inputFilename, FileMode.Open, FileAccess.Write))
        {
            fs.Position = startIndex;
            byte[] newTextBytes = Encoding.ASCII.GetBytes(newText);
            fs.Write(newTextBytes, 0, newTextBytes.Length);
        }
    }

Since the file is so large you may want to take a look at the .NET 4.0 support for memory mapped files. Basically you'll need to move the file/stream pointer to the location in the file, overwrite that location, then flush the file to disk. You won't need to load the entire file into memory.

For example, without using memory mapped files, the following will overwrite a part of an ascii file. Args are the input file, the zero based start index and the new text.

    static void Main(string[] args)
    {
        string inputFilename = args[0];
        int startIndex = int.Parse(args[1]);
        string newText = args[2];

        using (FileStream fs = new FileStream(inputFilename, FileMode.Open, FileAccess.Write))
        {
            fs.Position = startIndex;
            byte[] newTextBytes = Encoding.ASCII.GetBytes(newText);
            fs.Write(newTextBytes, 0, newTextBytes.Length);
        }
    }
眼藏柔 2024-09-13 22:19:41

除非新文本与旧文本的大小完全相同,否则您将必须重新写入文件。没有办法解决这个问题。您至少可以在不将整个文件保留在内存中的情况下执行此操作。

Unless the new text is exactly the same size as the old text, you will have to re-write the file. There is no way around it. You can at least do this without keeping the entire file in memory.

往日 2024-09-13 22:19:41

您好,我测试了以下内容 - 效果很好。这迎合了由 Environment.NewLine 分隔的可变长度行。如果您有固定长度的行,您可以直接查找它。要将字节转换为字符串,反之亦然,您可以使用编码。

 static byte[] ReadNextLine(FileStream fs)
        {
            byte[] nl = new byte[] {(byte) Environment.NewLine[0],(byte) Environment.NewLine[1] };
            List<byte> ll = new List<byte>();
            bool lineFound = false;
            while (!lineFound)
            {
                byte b = (byte)fs.ReadByte();
                if ((int)b == -1) break;
                ll.Add(b);
                if (b == nl[0]){
                    b = (byte)fs.ReadByte();
                    ll.Add(b);
                    if (b == nl[1]) lineFound = true;
                }
            }
          return  ll.Count ==0?null: ll.ToArray();
        }
       static void Main(string[] args)
       {

            using (FileStream fs = new FileStream(@"c:\70-528\junk.txt", FileMode.Open, FileAccess.ReadWrite))
            {
               int replaceLine=1231;
               byte[] b = null;
               int lineCount=1;
               while (lineCount<replaceLine && (b=ReadNextLine(fs))!=null ) lineCount++;//Skip Lines

               long seekPos = fs.Position;
               b = ReadNextLine(fs);
               fs.Seek(seekPos, 0);
              string line=new string(b.Select(x=>(char)x).ToArray());
              line = line.Replace("Text1", "Text2");
                b=line.ToCharArray().Select(x=>(byte)x).ToArray();
                fs.Write(b, 0, b.Length);

            }

        }

Hello I tested the following -works well.This caters to variable length lines separated by Environment.NewLine. if you have fixed length lines you can straightaway seek to it.For converting bytes to string and vice versa you can use Encoding.

 static byte[] ReadNextLine(FileStream fs)
        {
            byte[] nl = new byte[] {(byte) Environment.NewLine[0],(byte) Environment.NewLine[1] };
            List<byte> ll = new List<byte>();
            bool lineFound = false;
            while (!lineFound)
            {
                byte b = (byte)fs.ReadByte();
                if ((int)b == -1) break;
                ll.Add(b);
                if (b == nl[0]){
                    b = (byte)fs.ReadByte();
                    ll.Add(b);
                    if (b == nl[1]) lineFound = true;
                }
            }
          return  ll.Count ==0?null: ll.ToArray();
        }
       static void Main(string[] args)
       {

            using (FileStream fs = new FileStream(@"c:\70-528\junk.txt", FileMode.Open, FileAccess.ReadWrite))
            {
               int replaceLine=1231;
               byte[] b = null;
               int lineCount=1;
               while (lineCount<replaceLine && (b=ReadNextLine(fs))!=null ) lineCount++;//Skip Lines

               long seekPos = fs.Position;
               b = ReadNextLine(fs);
               fs.Seek(seekPos, 0);
              string line=new string(b.Select(x=>(char)x).ToArray());
              line = line.Replace("Text1", "Text2");
                b=line.ToCharArray().Select(x=>(byte)x).ToArray();
                fs.Write(b, 0, b.Length);

            }

        }
隱形的亼 2024-09-13 22:19:41

我猜您会想要使用 FileStream 类并寻找您的位置,并放置更新的数据。

I'm guessing you'll want to use the FileStream class and seek to your positon, and place your updated data.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文