Редактирование текстового файла на месте через C # - PullRequest
14 голосов
/ 23 июня 2010

У меня огромный текстовый файл, размер> 4 ГБ, и я хочу заменить текст в нем программно. Я знаю номер строки, по которой мне нужно заменить текст, но проблема в том, что я не хочу копировать весь текст (вместе с моей замененной строкой) во второй файл. Я должен сделать это в исходном файле. Есть ли способ сделать это в C #?

Текст, который должен быть заменен, точно такого же размера, как и исходный текст (если это помогает).

Ответы [ 4 ]

14 голосов
/ 23 июня 2010

Поскольку файл настолько велик, вы можете взглянуть на поддержку .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);
        }
    }
5 голосов
/ 23 июня 2010

Если новый текст не имеет точно такой же размер, как старый текст, вам придется переписать файл.Обойти это невозможно.Вы можете по крайней мере сделать это, не сохраняя весь файл в памяти.

2 голосов
/ 24 июня 2010

Здравствуйте. Я протестировал следующее -работает хорошо. Это обслуживает строки переменной длины, разделенные Environment.NewLine. если у вас есть строки фиксированной длины, вы можете сразу искать их. Для преобразования байтов в строку и наоборот вы можете использовать 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);

            }

        }
0 голосов
/ 23 июня 2010

Я предполагаю, что вы захотите использовать класс FileStream и искать ваше положение и размещать обновленные данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...