2010-06-23 81 views
12

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

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

回答

12

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

例如,如果不使用内存映射文件,以下内容将覆盖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); 
     } 
    } 
+0

我正在使用.NET 3.5。所以,我担心,这可能不是一个选择。感谢您的建议。 – Aamir 2010-06-23 18:23:05

+1

@Aamir:seek/write/flush可以用典型的文件I/O来完成;内存映射不是必需的。但如果你想在3.5中使用内存映射,你不需要任何特殊的对象库,你可以通过System.Runtime.Interopservices和DLLImport直接调用本地win dll接口(CreateFileMapping/MapViewOfFile/etc)。 – 2010-06-23 18:31:58

+0

此代码项目在.NET 3.5中执行内存映射。他使用的是数组,但我敢打赌,翻译成文件并不困难。 http://www.codeproject.com/KB/recipes/MemoryMappedGenericArray.aspx – 2010-06-23 18:40:26

5

除非新文本与旧文本大小完全一样,否则您将不得不重新编写该文件。没有其他办法了。至少可以做到这一点,而不必将整个文件保存在内存中。

+0

乔尔,新文本是完全相同的大小。在这种情况下做这件事的方法是什么? – Aamir 2010-06-23 18:21:58

+0

打开文件流,找到文本开始的位置,然后将新文本写入流。 – 2010-06-23 18:33:33

0

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

1

你好我测试了下面的工程well.This迎合不同长度的行由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); 

      } 

     }