Proces byłoby coś takiego:
- Otwórz
StreamWriter
do pliku tymczasowego.
- Otwórz plik
StreamReader
w pliku docelowym.
- Dla każdej linii:
- Podziel tekst na kolumny na podstawie ogranicznika.
- Sprawdź kolumny wartości, które chcesz zastąpić i zastąp je.
- Połącz wartości kolumn z powrotem za pomocą ogranicznika.
- Napisz wiersz do pliku tymczasowego.
- Po zakończeniu usuń plik docelowy i przenieś plik tymczasowy do ścieżki pliku docelowego.
Uwaga dotycząca kroków 2 i 3.1: Jeśli masz pewność co do struktury pliku i jest to dość proste, możesz to zrobić po wyjęciu z pudełka zgodnie z opisem (za chwilę dołączę próbkę). Istnieją jednak czynniki w pliku CSV, które mogą wymagać uwagi (na przykład rozpoznanie, kiedy ogranicznik jest używany dosłownie w wartości kolumny). Możesz sam tego dokonać lub wypróbować numer existing solution.
Podstawowe przykład tylko przy użyciu StreamReader
i StreamWriter
:
var sourcePath = @"C:\data.csv";
var delimiter = ",";
var firstLineContainsHeaders = true;
var tempPath = Path.GetTempFileName();
var lineNumber = 0;
var splitExpression = new Regex(@"(" + delimiter + @")(?=(?:[^""]|""[^""]*"")*$)");
using (var writer = new StreamWriter(tempPath))
using (var reader = new StreamReader(sourcePath))
{
string line = null;
string[] headers = null;
if (firstLineContainsHeaders)
{
line = reader.ReadLine();
lineNumber++;
if (string.IsNullOrEmpty(line)) return; // file is empty;
headers = splitExpression.Split(line).Where(s => s != delimiter).ToArray();
writer.WriteLine(line); // write the original header to the temp file.
}
while ((line = reader.ReadLine()) != null)
{
lineNumber++;
var columns = splitExpression.Split(line).Where(s => s != delimiter).ToArray();
// if there are no headers, do a simple sanity check to make sure you always have the same number of columns in a line
if (headers == null) headers = new string[columns.Length];
if (columns.Length != headers.Length) throw new InvalidOperationException(string.Format("Line {0} is missing one or more columns.", lineNumber));
// TODO: search and replace in columns
// example: replace 'v' in the first column with '\/': if (columns[0].Contains("v")) columns[0] = columns[0].Replace("v", @"\/");
writer.WriteLine(string.Join(delimiter, columns));
}
}
File.Delete(sourcePath);
File.Move(tempPath, sourcePath);
w takim razie dlaczego nie spróbować zmniejszyć stosując Hadoop Mapa .... –
Będziesz w stanie zrobić zmiany tylko w przypadku zmian linia będzie mieć długość, która nie przekracza pierwotną długość linii –
Dlaczego nie wystarczy napisać do nowy plik? A więc: 1. Przeczytaj 2. Modyfikuj 3.Write, aby skopiować. Czy to coś, czego nie chcesz robić, czy po prostu szukasz "eleganckiego" sposobu na zrobienie tego? – StampedeXV