2015-08-27 3 views
0

Я пытаюсь очистить некоторые файлы, которые я получаю ежеквартально. У них есть куча повторяющихся заголовков, и я хотел бы заменить несколько значений строк за один раз. Я могу удалить одну строку за раз, но я не понимаю, как я могу передать файл и посмотреть на каждую строку и удалить, если это строка 1 или строка 2.Замена нескольких строковых значений в файлах

Каждый файл имеет не менее 100-300 тысяч строк и я получаю от 10 до 50 файлов каждый раз, когда данные сбрасываются мне примерно раз в квартал ... Было бы проще, если бы они не добавляли эти строки, но это не вариант.

Извините за вопрос новичков, но я не получаю код очень часто. Любая помощь приветствуется ...

static void Main(string[] args) 
{ 
    string tempFile = Path.GetTempFileName(); 
    string t1 = "-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"; 

    string fName = "C:\\PoC\\test\\test.txt"; 
    using (var sr = new StreamReader(fName)) 
    using (var sw = new StreamWriter(tempFile)) 
    { 
     string line; 

     while ((line = sr.ReadLine()) != null) 
     { 

      if (line.Contains(t1) == false) 
      { 
       sw.WriteLine(line); 
      } 
     } 
     sr.Close(); 
     sw.Close(); 
    } 

    File.Delete(fName); 
    File.Move(tempFile, fName); 
} 
+0

Помните, что каждый раз, когда вы читаете, вы перемещаете позицию потока в последнем байтовом методе чтения и записи, который будет писать из этой позиции.Мой совет здесь следит за стартовой позицией и новой позицией после прочтения строки и перезаписывает этот диапазон с пустым пространством в вашем условии if. Это, если вы хотите сделать это напрямую, если не можете также создать новый файл в памяти и переопределить весь файл. – mijail

ответ

1

Вызов string.Contains() почти так же дорого, как вызов string.replace(), потому что в любом случае вся строка должна быть отсканированы для подстроки. В случае Replace() найти совпадение создает и возвращает новую строку, представляющую результат замены, в противном случае возвращает исходную строку. Изменение

if (line.Contains(t1) == false) 
    sw.WriteLine(line); 

в

sw.WriteLine(line.Replace(t1, whatYouWantToReplaceWith)); 

При замене нескольких значений в одной строке, вы можете написать

sw.WriteLine(
    line 
    .Replace(t1, whatYouWantToReplaceWith1) 
    .Replace(t2, whatYouWantToReplaceWith2) 
    .Replace(t3, whatYouWantToReplaceWith3) 
); 

Обратите внимание, что использование нескольких .Привернуть() вызовет линию сканироваться для совпадений несколько раз. Хотя это немного снижает производительность, большая часть вашего времени обработки, вероятно, все еще будет файлом IO.

Если вы знаете, что замена будет когда-либо происходить, например. в первой строке вы можете добавить счетчик для отслеживания номера строки, на которой вы находитесь, и применять код Replace() только к соответствующим строкам.

Обратите внимание, что вы могли бы получить дополнительные улучшения в большом файле на using a BufferedStream.

UPDATE

Основываясь на утверждении, что вы просто хотите удалить строку, я предлагаю вам идти с ответом @ Eşer в.

+0

Хорошо, это действительно простой способ сделать это ... Спасибо. Один вопрос, строки нужно просто удалить. Итак, что я должен использовать, чтобы заменить линию? Я попробовал «линию», что и раньше (честно говоря, я не знаю почему). Я тоже пробовал ». Но это оставило пустую строку, где я хочу полностью удалить строку. –

+0

Используйте 'string.Replace (t1," ")' –

+0

Эрик, потерял меня там. Вы говорите, что line.replace для string.replace? Извините за немой вопрос. –

1

Я хотел бы заменить несколько значений строк за один раз.

Использование Linq может сделать ваш код проще

string[] stringsToRemove = new[] { "str1", "str2", "str2" }; 

var query = File.ReadLines(fName) 
       .Where(line => !stringsToRemove.Any(s => line.Contains(s))); 

File.WriteAllLines(tempFile, query); 
+0

Он пояснил в комментарии, что он хочет удалить всю строку, а не заменять токены, поэтому ваш вопрос на вопрос правильный. –

+0

Я получаю необработанную ошибку исключения. Любые мысли? System.IO.IOException был необработанным HResult = -214702486 Сообщение = Процесс не может получить доступ к файлу 'C: \ Users \ xxxx \ AppData \ Local \ Temp \ tmpB784.tmp', потому что он используется другим процессом , Источник = mscorlib –

+0

@StuRyan Закрыть/Открыть свой VS и повторить попытку .... Кажется, это не связано с кодом, который вы пишете – Eser

1

Я знаю, что вы работаете на C# программы, если цель состоит в том, чтобы просто удалить строки, которая соответствует скороговоркой, то я хотел бы использовать что-то вроде Редактор Unix Stream sed, см. sed for Windows stand alone command, или cygwin, и вы можете просто использовать эту команду, чтобы удалить все строки, соответствующие шаблону и строкам, следующим за ним, вы можете написать сценарий .bat для копирования, переименования и удаления строк, чем один образец. Это очень быстро.

sed -i '/^---------/d' filepath 
+0

Это действительно интересно ... Мне придется заглянуть в него. Спасибо. –

+0

sed - отличный вариант, если программа C# будет самостоятельной. Если это часть программного пакета, который уже развернут, я бы не установил что-то дополнительное. –

+0

Это просто способ упростить мою жизнь. Я загружаю файлы на свой компьютер (1-5 ГБ), очищаю, а затем загружаю в базу данных. Его уродливые, но это то, что есть ... Файлы - это дампы журнальных файлов, и мое управление хочет получить отчет о них. Человек, который передо мной использовал, нашел в блокноте и провел день или два, делая это ... просто пытаясь быть умным здесь. Так что интересно создать файл bat, чтобы позаботиться об этом ... Я также хочу узнать больше о кодировании, так что оба они великолепны прямо сейчас. Это первый шаг, следующий - несколько файлов, а затем автоматизация загрузки в базу данных ... –