Существует ли язык конструкции C / Framework для применения функции к каждой строке файла?

2

То, что я ищу, - это что-то в этом роде:

var f = UsefulFileObject(@"c:\temp.log");
f.ForEachLine( (line) => line.Trim() );

После этого я ожидаю, что каждая строка в файле будет обрезана.

Есть ли такой объект в структуре уже или я должен начать создавать свой собственный?

Теги:

4 ответа

9
Лучший ответ

После просмотра нескольких неправильных решений с использованием ForEach в неизменяемом типе, например string, я предполагаю, что опубликую мои собственные.

Это будет фактически читать и записывать упомянутый файл. Тем не менее, это для небольших файлов, так как все содержимое будет в памяти *.

string filename = @"C:\testfile.txt";
string[] fileLines = File.ReadAllLines(filename);
fileLines = Array.ConvertAll(fileLines, l => l.Trim());
File.WriteAllLines(filename, fileLines);

В реальном мире вы, вероятно, захотите сначала записать в другой файл и переименовать его в исходный файл после завершения операции. В противном случае части файла могут быть потеряны, если что-то пошло не так, как на полпути.

Использование памяти объявлений:
Фактически, файл будет в памяти дважды на мгновение. Вы можете решить это, используя обычный цикл for вместо любых причудливых методов расширения и лямбда-выражений. Я пропущу это упражнение и перейду к "правильному" способу сделать это для больших файлов:

using (StreamReader reader = new StreamReader(@"D:\infile.txt"))
using (StreamWriter writer = new StreamWriter(@"D:\outfile.txt"))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        writer.WriteLine(line.Trim());
    }
}

// Some File.Move(..) usage to rename the files

Реализация "ForEachLine" :
Если вы хотите реализовать вспомогательный метод, который делает то, что вы описали, вы можете скрыть уродливую логику переименования.

Подпись метода будет выглядеть примерно так:

public void ForEachLine(Func<string, string> func)

и строка, выполняющая запись, будет выглядеть следующим образом:

writer.WriteLine(func(line));
  • 0
    +1 действительно работает, с бонусом за перечисление недостатков
  • 0
    Отличный пост - с решением и объяснением ...
2

Поскольку вы не можете изменить текстовый файл на месте (ну, очевидно, вы можете, но это просто тяжело), ​​такой объект будет в основном сосредоточен вокруг системы read-modify-write.

  • 0
    Согласовано. Я бы никогда не попытался изменить вещи на месте. В этом случае операция гарантированно сделает ваш файл более компактным, что является более или менее обязательным требованием. Не существует надежного способа восстановления после сбоя и т. Д.
0

Для довольно небольших файлов используйте File.ReadAllLines(filename).ForEach(l = > l.Trim())

  • 0
    Почти. Метод ReadAllLines возвращает строковый массив, и вы должны создать List <T>, чтобы использовать метод ForEach.
  • 0
    Поскольку строковый массив реализует IEnumerable <T>, вы можете использовать File.ReadAllLines (имя файла) .Select (l => l.Trim ())
Показать ещё 4 комментария
0

У вас есть метод System.IO.File.ReadAllLines(), который возвращает строку [] (массив строк).

Затем массив можно использовать с циклом foreach, который вы можете преобразовать в список и использовать метод ForEach (Action).

Итак, это должно работать:

string[] logLines = System.IO.File.ReadAllLines(@"c:\temp.log");
logLines.ToList().ForEach(l => l.Trim());
  • 1
    Та же проблема здесь: logLines фактически не изменяется вообще.
  • 0
    Хорошая точка зрения. Я не заметил, что он хотел написать это обратно в файл.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню