【问题标题】:Add new column in existing csv file in c#在c#中的现有csv文件中添加新列
【发布时间】:2020-07-22 13:29:26
【问题描述】:

我需要将新列插入到每天更新的现有 CSV 文件中,并以管道分隔

||||||||||||||||||||||||||||||||||||||||||||||||||
|Table1|||||||||||||||||||||||||||||||||||||||||||||||||            
||||||||||||||||||||||||||||||||||||||||||||||||||          
N|IDI  |TEST|START DATE HOUR    |CAUSE|KIND|NUMB|NAMES|         
1|10704|    |21/07/2020 15:05:54|L    |MT  |2786|NAV  |         
2|10660|    |21/07/2020 09:27:31|L    |MT  |4088|PIS  |     
||||||||||||||||||||||||||||||||||||||||||||||||||          
|Table2|||||||||||||||||||||||||||||||||||||||||||||||||            
||||||||||||||||||||||||||||||||||||||||||||||||||          
N|IDI  |TEST|START DATE HOUR    |END DATE HOUR      |LENGHT  |RETURNS         |CAUSE|KIND|NUMB|NAMES|           
1|10710|    |21/07/2020 19:34:00|21/07/2020 20:19:09|00:45:09| -              |L    |MT  |7806|ACC  |
2|10708|    |21/07/2020 18:28:12|21/07/2020 18:28:13|00:00:01| -              |T    |MT  |2600|LIT  |       
3|10700|    |21/07/2020 14:16:37|21/07/2020 15:19:13|01:02:36|21/07/2020 17:00|L    |MT  |4435|UHI  |       
4|10698|    |21/07/2020 14:06:45|21/07/2020 14:07:22|00:00:37|-               |B    |MT  |5789|TYK  |
5|10674|    |21/07/2020 10:21:04|21/07/2020 10:44:41|00:23:37|21/07/2020 12:30|T    |MT  |6699|FGR  |
||||||||||||||||||||||||||||||||||||||||||||||||||

请注意,CSV 文件中表 1 和表 2 之间的列数不同

对于表 1,列数为 8

对于表 2,列数为 10

我需要在表 1 和表 2 中添加缺失的列

  1. 结束日期小时
  2. 长度

我尝试使用 C# 将 csv 文件预处理为适当的 CSV,添加缺失的列,但输出为

代码甚至在表 2 中添加了缺失的列

如何解决这个问题?

This the csv file

下面是我的代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        int posNewColumn = 5;

        string output = @"C:\Downloads\import.csv";

        string[] CSVDump = File.ReadAllLines(output);
        List<List<string>> CSV = CSVDump.Select(x => x.Split('|').ToList()).ToList();
        for (int i = 0; i < CSV.Count; i++)
        {
            if (CSV[i].Count > posNewColumn)
            {
                CSV[i].Insert(posNewColumn, i == 0 ? "Headername" : "END DATE HOUR");
            }
            else
            {
                CSV[i].Add(i == 0 ? "Headername" : "END DATE HOUR");
            }
        }
        File.WriteAllLines(output, CSV.Select(x => string.Join("|", x)));
    }
}

【问题讨论】:

  • 这不是 CSV 文件。 CSV 文件只是具有特定格式的文本文件。它没有多个表。您发布的图像不相关 - 看起来您双击文件并期望 Excel 以某种方式显示它,就好像这是 Excel 工作表一样。 Excel 无法猜测分隔符是什么。它将尝试使用最终用户的区域设置导入该数据,例如,; 作为列表分隔符。我怀疑 any 语言环境使用 |
  • 如果您想要多个工作表和表格,请创建和读取真正的 Excel 文件,例如使用Epplusxlsx 格式是一个包含 XML 文件的 zip 包。像 Epplus 这样的库让创建 xlsx 文件就像调用 sheet.Cells.LoadFromCollection(customers) 一样简单
  • 这是一个由服务器生成的 CSV 文件,可供我处理
  • 不是。你可以这样称呼它,但事实并非如此。您可以查看 csv 是什么,甚至是定义它的 RFC,但简短的版本是,它应该是一个 simple 文本文件,以 commas 作为值分隔符。您所拥有的是需要解析以获取数据的文本 report
  • 我什么都不叫...对不起

标签: c# csv


【解决方案1】:

这是我的尝试,试图让它更灵活、更健壮,还允许您在保持对齐的同时在数据行中插入值。

string inputFile = @"import.csv";
string outputFile = @"output.csv";

bool startInserting = false;
string getLine(string endDateText, string lengthText) => $"{endDateText,-19}|{lengthText,-8}|";

var fileContents = File.ReadAllLines(inputFile);
for (int i = 0; i < fileContents.Length; i++)
{
    var line = fileContents[i];

    if (line.Contains("Table1"))
    {
        startInserting = true;
        continue;
    }

    if (line.Contains("Table2"))
        break;

    if (line.Length == 0 || line[0] == '|')
        continue;

    if (startInserting)
    {
        int columnIndex = 33;
        if (line[0] == 'N')
        {
            string headerLine = getLine("END DATE HOUR", "LENGHT"); // I keep the typo
            fileContents[i] = line.Insert(columnIndex, headerLine);
        }
        else if (char.IsDigit(line[0]))
        {
            string dataLine = getLine("", "");
            fileContents[i] = line.Insert(columnIndex, dataLine);
        }
    }

}

File.WriteAllLines(outputFile, fileContents);

这是输出:

||||||||||||||||||||||||||||||||||||||||||||||||||
|Table1|||||||||||||||||||||||||||||||||||||||||||||||||            
||||||||||||||||||||||||||||||||||||||||||||||||||          
N|IDI  |TEST|START DATE HOUR    |END DATE HOUR      |LENGHT  |CAUSE|KIND|NUMB|NAMES|         
1|10704|    |21/07/2020 15:05:54|                   |        |L    |MT  |2786|NAV  |         
2|10660|    |21/07/2020 09:27:31|                   |        |L    |MT  |4088|PIS  |     
||||||||||||||||||||||||||||||||||||||||||||||||||          
|Table2|||||||||||||||||||||||||||||||||||||||||||||||||            
||||||||||||||||||||||||||||||||||||||||||||||||||          
N|IDI  |TEST|START DATE HOUR    |END DATE HOUR      |LENGHT  |RETURNS         |CAUSE|KIND|NUMB|NAMES|           
1|10710|    |21/07/2020 19:34:00|21/07/2020 20:19:09|00:45:09| -              |L    |MT  |7806|ACC  |
2|10708|    |21/07/2020 18:28:12|21/07/2020 18:28:13|00:00:01| -              |T    |MT  |2600|LIT  |       
3|10700|    |21/07/2020 14:16:37|21/07/2020 15:19:13|01:02:36|21/07/2020 17:00|L    |MT  |4435|UHI  |       
4|10698|    |21/07/2020 14:06:45|21/07/2020 14:07:22|00:00:37|-               |B    |MT  |5789|TYK  |
5|10674|    |21/07/2020 10:21:04|21/07/2020 10:44:41|00:23:37|21/07/2020 12:30|T    |MT  |6699|FGR  |
||||||||||||||||||||||||||||||||||||||||||||||||||

注意:它使用了一些相对较新的 C# 功能,因此如果出现编译错误,则必须进行一些调整。

另外请注意,我没有插入 RETURNS,您说的是缺少列,但由于某种原因跳过了那一列。

【讨论】:

    【解决方案2】:

    这就是我想出的。我将它分成两个文件以便于调试,但如果你愿意,你可以撤消它。这会读入每一行,一旦你遇到“Table2”,你就会跳出循环。如果第一列包含“N”,那么您在表格标题中并添加标题,如果没有,则添加一个空字段。

    这是一个脆弱的解决方案,它依赖于该文件的格式不会改变,但我认为它会做你想做的事情。

    int posNewColumn = 4;
    
    string input = @"C:\Temp\SO\import.csv";
    string output = @"C:\Temp\SO\out.csv";
    
    string[] CSVDump = File.ReadAllLines(input);
    List<List<string>> CSV = CSVDump.Select(x => x.Split('|').ToList()).ToList();
    foreach (List<string> line in CSV)
    {
        if (line[1] == "Table2")
        {
            break;
        }
        line.Insert(posNewColumn, line[0] == "N" ? "LENGHT" : string.Empty);
        line.Insert(posNewColumn, line[0] == "N" ? "END DATE HOUR" : string.Empty);
    }
    
    File.WriteAllLines(output, CSV.Select(x => string.Join("|", x)));
    

    【讨论】:

    • 数据行呢?和填充?此外,我不会为每一行调用Insert,为什么不将它们放在if 块中呢?
    • 这会为每个数据行插入两个空列。当您说“填充”时,我不确定您指的是什么。我对每一行进行插入的原因是尝试在文件中保持一致的列数。
    • @schwechel 感谢您的帮助,非常感谢
    • 关于填充,我的意思是输出文件不再可读,因为所有列都不再对齐。此外,您正在向标题行添加管道。您应该在列标题中包含尾随空格,并在数据行中包含相应的空格(或值,如果有)。
    猜你喜欢
    • 1970-01-01
    • 2018-02-06
    • 2021-09-30
    • 2016-11-24
    • 2021-07-17
    • 2012-06-19
    • 2013-07-25
    • 1970-01-01
    • 2019-08-22
    相关资源
    最近更新 更多