代码之家  ›  专栏  ›  技术社区  ›  Aamir

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

  •  14
  • Aamir  · 技术社区  · 14 年前

    我有一个巨大的文本文件,大小为4GB,我想用编程方式替换其中的一些文本。我知道必须替换文本的行号,但问题是我不想将所有文本(连同替换的行)复制到第二个文件。我必须在源文件中这样做。有没有一种方法可以用C来做到这一点?

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

    4 回复  |  直到 14 年前
        1
  •  14
  •   Shea    14 年前

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

    例如,如果不使用内存映射文件,以下内容将覆盖ASCII文件的一部分。参数是输入文件、从零开始的索引和新文本。

        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);
            }
        }
    
        2
  •  5
  •   Joel Coehoorn    14 年前

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

        3
  •  2
  •   josephj1989    14 年前

    你好,我测试了下面的-很好地工作。这迎合了由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);
    
                }
    
            }
    
        4
  •  0
  •   Nate CSS Guy    14 年前

    我猜你会想使用filestream类并找到你的位置,然后放置你更新的数据。