Я пытаюсь обновить файл CSV данными из текстового поля и сталкиваюсь с проблемами.
Пример CSV-файла:
тест1,данные1,дополнительныеданные1
тест2,данные2,ещёданные2
тест3,данные3,большеданные3
тест4,данные4,большеданные4
тест5,данные5,ещёданные5
тест6,данные6,ещёданные6
тест7,данные7,ещёданные7
тест8,данные8,ещёданные8
тест9,данные9,ещёданные9
тест10,данные10,дополнительныеданные10
Ожидаемый CSV-файл:
test1,Change1,moredata1
тест2,данные2,ещёданные2
тест3,данные3,большеданные3
test4,Change2,moredata4
тест5,данные5,ещёданные5
тест6,данные6,ещёданные6
тест7,данные7,ещёданные7
тест8,данные8,ещёданные8
тест9,данные9,ещёданные9
test10,Change3,moredata10
Фактический файл CSV
test1,Change1
,moredata1
test2,data2,moredata2
test3,data3,moredata3
test4,data4,moredata4
test5,data5,moredata5
test6,data6,moredata6
test7,data7,moredata7
test8,data8,moredata8
test9,data9,moredata9
test10,data10,moredata10
test1,Change1
,moredata1
test2,data2,moredata2
test3,data3,moredata3
test4,Change2
,moredata4
test5,data5,moredata5
test6,data6,moredata6
test7,data7,moredata7
test8,data8,moredata8
test9,data9,moredata9
test10,data10,moredata10
test1,Change1
,moredata1
test2,data2,moredata2
test3,data3,moredata3
test4,data4,moredata4
test5,data5,moredata5
test6,data6,moredata6
test7,data7,moredata7
test8,data8,moredata8
test9,data9,moredata9
test10,Change3,moredata10
test1,Change1
,moredata1
test2,data2,moredata2
test3,data3,moredata3
test4,Change2
,moredata4
test5,data5,moredata5
test6,data6,moredata6
test7,data7,moredata7
test8,data8,moredata8
test9,data9,moredata9
test10,Change3,moredata10
Код:
var importboxData = massimportBox.Text.Split('\n');
foreach (var iLine in importboxData)
{
using (StreamReader reader = new StreamReader(path))
{
String line;
while ((line = reader.ReadLine()) != null)
{
if (line.Split(',')[0].Equals(iLine.Split(',')[0]))
{
String[] split = line.Split(',');
int indexNum = Int32.Parse(indexBox.Text);
split[indexNum] = iLine.Split(',')[1];
line = String.Join(",", split);
}
lines.Add(line);
}
}
using (StreamWriter writer = new StreamWriter(path, false))
{
foreach (String line in lines)
writer.WriteLine(line);
}
}
Вы без необходимости читаете и записываете весь файл для каждого желаемого изменения.
Попробуйте что-то более похожее на:
Dictionary<String, String> changes = new Dictionary<string, string>();
foreach (String iLine in massimportBox.Lines)
{
String[] values = iLine.Split(',');
if (values.Length==2 && values[0].Trim().Length>0)
{
changes[values[0]] = values[1];
}
}
int indexNum = Int32.Parse(indexBox.Text);
String[] lines = System.IO.File.ReadAllLines(path);
for (int i=0; i<lines.Length; i++)
{
String[] values = lines[i].Split(',');
String key = values[0];
if (changes.ContainsKey(key) && indexNum>=0 && indexNum<values.Length)
{
values[indexNum] = changes[key];
lines[i] = String.Join(",", values);
}
}
System.IO.File.WriteAllLines(path, lines);
values.Length==2
следит за тем, чтобы на линии было ровно две детали; «ключ» перед запятой и «значение» после запятой. Если двух частей не будет, то мы не будем знать, чем заменить старое значение.
Понял, хорошо! Еще одна проблема. Так вроде сработало. Однако это, кажется, испортило интервал. Я выложил скрин в верхнем посте.
Вы пишете ТЕКСТОВЫЙ ФАЙЛ, который не имеет абсолютно никакого понятия о интервалах при открытии в Excel. Сделайте эти столбцы БОЛЬШЕ с помощью мыши! При таком подходе вы не можете контролировать размер «столбцов». Если вы хотите контролировать, как данные будут выглядеть в Excel, вам нужно создать файл .xlsx
, а не файл .txt
CSV. Создать настоящую электронную таблицу Excel было бы намного сложнее...
Это не проблема интервала, это была плохая формулировка с моей стороны. Они находятся в совершенно новых клетках. Например, перед запуском кода test2 находился в A1. После запуска кода он теперь находится в A3, а A2 пуст. Просмотр файла .csv через notepad.exe показывает, что все нормально, но попытка запустить приложение для анализа .csv теперь не удалась. -- Обновлено: это должно быть что-то с разделением текстового поля с помощью '\n'. Потому что, когда просто делаешь одну строку, все в порядке.
Если вы думаете, что это анализ TextBox, измените foreach (String iLine in massimportBox.Text.Split('\n'))
на foreach (String iLine in massimportBox.Lines)
и посмотрите, будет ли это лучше.
Это помогло, еще раз спасибо за помощь.
Ваша проблема связана с вложенными циклами. Ваш код будет повторять чтение файла один раз для каждого запрошенного изменения. Попробуйте следующее решение, в котором создается словарь значений <key, cahnge> и файл читается один раз.
var importboxData = massimportBox.Text.Split('\n');
Dictionary<string,string> iSplitDict = new Dictionary<string,string> ()
foreach (var iLine in importboxData)
{
string[] iSplit = iLine.Split(',');
iSplitDict.Add(iSplit[0], iSplit[1])
}
using (StreamReader reader = new StreamReader(path))
{
string line;
while ((line = reader.ReadLine()) != null)
{
string[] split = line.Split(',');
if (iSplitDict.ContainsKey(split[0]))
{
int indexNum = Int32.Parse(indexBox.Text);
split[indexNum] = iSplitDict[split[0]];
line = String.Join(",", split);
}
lines.Add(line);
}
using (StreamWriter writer = new StreamWriter(path, false))
{
foreach (String line in lines)
{
writer.WriteLine(line);
}
}
}
Спасибо за ответ, это сработало именно так, как ожидалось! Быстрый вопрос, что делает строка values.Lenth==2~?