【问题标题】:Replacing specific commas in a comma-delimited file替换逗号分隔文件中的特定逗号
【发布时间】:2016-05-31 16:54:32
【问题描述】:

我有一个文件,我将其流式传输到列表对象中以保存到数据库中的临时文件中,因为我必须使用临时表中的数据连接到其他表以获得最终结果,然后将此最终结果导出到.csv 文件。

一切正常,除了原始文件的流读取。

文件以逗号分隔,结构非常明确,结构永远不会改变。

我的问题是这样的:

“AccountHolder”字段在组成字符串的字符之间有一个逗号,因此我的 FileStream 将其视为分隔符。如何在不破坏 FileStream 必须遵守的逗号分隔符的情况下替换 AccountHolder 字符串中的逗号?

List<object[]> fileContent = new List<object[]>();

            using (FileStream reader = File.OpenRead(ofd.FileName))
            using (TextFieldParser parser = new TextFieldParser(reader))
            {
                parser.TrimWhiteSpace = true;
                parser.Delimiters = new[] { "," };
                parser.HasFieldsEnclosedInQuotes = true;
                while (!parser.EndOfData)
                {
                    object[] line = parser.ReadFields();
                    fileContent.Add(line);
                    lstRegNo.Add(line[0].ToString().Trim());
                    lstAccHolder.Add(line[1].ToString().Trim().Replace(',', ' '));
                    lstAmount.Add(line[2].ToString().Trim().Replace(',', ' '));
                    lstAccNo.Add(line[3].ToString().Trim());
                    lstBranch.Add(line[4].ToString().Trim());
                    lstDate.Add(line[5].ToString().Trim());
                    lstCode.Add(line[6].ToString().Trim());
                    lstOrphenColumn.Add(line[7].ToString().Trim());
                }

这是我正在流式传输的文件的示例:

000001,A WHATEVER,00000000001,0000000000001,000001,160510,17,0
000002,B WHATEVER,00000000002,0000000000002,000002,160510,17,0
000003,C, WHATEVER,00000000003,0000000000003,000003,160510,17,0
000004,D WHATEVER,00000000004,0000000000004,000004,160510,17,0
000005,E WHATEVER,00000000005,0000000000005,000005,160510,17,0

如您所见,在第 3 行,AccountHolder 的名称中有一个逗号。我需要它的值是“C WHATEVER”,而不是“C, WHATEVER” 我想消除那个逗号,但仍然能够将文件流式传输到我的列表中对象用逗号分隔文件中的字段。

请注意,每次我收到文件的数据都会有所不同,因此仅寻找静态值不会削减它。

我该怎么做?

【问题讨论】:

  • 要解决此问题,您可以使用唯一分隔符(例如 ;)或将文本放入 ""quote 它们 - 必须嵌入逗号或双引号字符的字段被引用”)。
  • 提供 CSV 文件的人违反了 CSV 文件的规则,您应该要求他们按照@Sinatr 的说明进行操作。可以围绕此类事故进行编码,但请考虑您可能遇到的所有可能问题。你加入了哪些专栏?如果多余的逗号出现在第 7 列而不是第 2 列会怎样?目前很难解决
  • @Sinatr:不确定他是否可以更改输入文件(将字段用双引号括起来)
  • 那么 CSV 提供者有责任修复 @Veverke,很难确定逗号应该在 CSV 文件中的哪个位置,并且在编程上非常困难
  • 这看起来像是人类输入的。人类可能会犯许多不同类型的打字错误,并且很难编写一个通用程序来查找并修复所有可能的人为错误。

标签: c# csv


【解决方案1】:

嗯...如果字段是固定的,那么您没有正确设置解析器。它知道如何处理与规范 CSV 文件有些不同的固定宽度字段。

顺便说一句,我倾向于制作一些反映“列”名称的常量:

//--> indexes into parsed line...
const int RegNo = 0;
const int AcctHolder = 2;
const int Amount = 4;
const int AcctNo = 6;
//--> ...etc.

using Microsoft.VisualBasic.FileIO;
//...
List<object[]> fileContent = new List<object[]>();
using (FileStream reader = File.OpenRead(ofd.FileName))
using (TextFieldParser parser = new TextFieldParser(reader))
{
  parser.TextFieldType = FieldType.FixedWidth;
  parser.SetFieldWidths
  (
     6  1, //--> width of RegNo, width of ignored comma
    10, 1, //--> width of AcctHolder, width of ignored comma
    10, 1, //--> width of Amount, width of ignored comma
    13, 1, //--> etc...
     6, 1, 
     6, 1, 
     2, 1,
     1
  );
  while (!parser.EndOfData)
  {
    object[] line = parser.ReadFields();
    fileContent.Add(line);
    lstRegNo.Add( line[ RegNo ].ToString( ));
    lstAccHolder.Add(line[ AcctHolder ].ToString().Replace(',', ' '));
    lstAmount.Add(line[ Amount ].ToString().Trim().Replace(',', ' '));
    lstAccNo.Add(line[ AcctNo ].ToString().Trim());
    //--> etc...
  }
}

欲了解更多信息,请查看this

【讨论】:

  • 好吧,该文件是固定宽度的,但以逗号分隔的方式......如果这有意义吗?我们正在切换到一个新的导入系统,因此过程如下: 1 - 接收系统生成的文件 2 - 修改此文件 3 - 使用原始文件中的数据 + 我们的附加数据创建一个新文件 (csv)数据库 原始文件用逗号分隔,但很明显这些字段是固定宽度的,因为旧系统需要这种格式
  • @GrammatonCleric,固定宽度更容易与之交互......我在代码中假设您只需将逗号读入您会忽略的字段。遗留系统总是很难处理 - 你无法控制即将发生的事情,甚至可能不再有源代码。去过那里,祝你好运!
【解决方案2】:

一个想法是,每当您阅读一行时,您都会计算逗号的数量。因此,假设您的列数始终为 7。下面的代码将捕获第二列中所有多余的逗号。

    string filename="sample.csv";
    var stream=new StreamReader(filename);
    string l=null;

    while((l = stream.ReadLine())!=null)
    {
        var ss=l.Split(',');
        int count = ss.Length - 1;//number of commas found
        int extraCommas = count - 7;

        var regNo = ss[0];
        StringBuilder accHolder = new StringBuilder();

        //loops from 1 and captures x number of extra commas
        for (int x = 1; x <= extraCommas+1; x++)
        {
            accHolder.Append(ss[x]);
        }

        var amount = ss[2 + extraCommas];
        var accNo = ss[3 + extraCommas];
        var branch = ss[4 + extraCommas];
        var date = ss[5 + extraCommas];   
        //etc....             
    }

【讨论】:

    【解决方案3】:

    最终我做了以下事情:

    List<string[]> fileContents = new List<string[]>();
    
                var lines = File.ReadAllLines(ofd.FileName).ToList();
                foreach (var item in lines)
                {
                    string RegNo = string.Format("{0}", item.ToString().Substring(0, 19));
                    string accHolder = string.Format("{0}", item.ToString().Substring(21, 30));
                    string amount = string.Format("{0}", item.ToString().Substring(52, 11));
                    string accNo = string.Format("{0}", item.ToString().Substring(64, 13));
                    string branch = string.Format("{0}", item.ToString().Substring(78, 6));
                    string date = string.Format("{0}-{1}-{2}", "20" + item.ToString().Substring(85, 2), item.ToString().Substring(87, 2), item.ToString().Substring(89, 2));
                    string code = string.Format("{0}", item.ToString().Substring(92, 2));
                    string orphenColumn = string.Format("{0}", item.ToString().Substring(95, 1));
    
                    lstRegNo.Add(RegNo.Trim());
                    lstAccHolder.Add(ExtensionMethods.RemoveSpecialCharacters(accHolder.Trim()));
                    lstAmount.Add(amount.Trim());
                    lstAccNo.Add(accNo.Trim());
                    lstBranch.Add(branch.Trim());
                    lstDate.Add(date);
                    lstCode.Add(code.Trim());
                    lstOrphenColumn.Add(orphenColumn);
                }
    

    这似乎适用于我迄今为止导入的每个文件。

    感谢您的所有建议!

    【讨论】:

    • 所以你解析为固定宽度?
    • @montewhizdoh,是的,我做到了。对我来说幸运的是,该文件的生成方式允许我这样做
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-21
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 2013-12-10
    • 2012-04-09
    • 1970-01-01
    相关资源
    最近更新 更多