【问题标题】:How to preserve CSV field whitespace for quoted field using Microsoft.VisualBasic.FileIO.TextFieldParser?如何使用 Microsoft.VisualBasic.FileIO.TextFieldParser 为引用字段保留 CSV 字段空白?
【发布时间】:2015-12-15 01:59:55
【问题描述】:

我正在使用 Microsoft.VisualBasic.FileIO.TextFieldParser 解析 CSV 数据。与我发现的用于解析 CSV 的免费软件库相比,它非常好。它做了我认为它应该 WRT CSV 的所有事情,除了它不保留用引号括起来的字段的前导/尾随空格。好吧,如果我将 TrimWhiteSpace 设置为 false,它会这样做,但是它不会修剪字段中的空格 not 括在引号中。对于 CSV,我希望它修剪未引用的字段而不修剪引用的字段。

这就是我使用课程的方式:

  var parser = new TextFieldParser(textReader) {Delimiters = new[] {","}};
  //TrimWhiteSpace is true by default
  var row1 = _textFieldParser.ReadFields();
  var row2 = _textFieldParser.ReadFields();

考虑这些数据:

 1 , 2 
" 1 ", " 2 "

对于 TrimWhiteSpace==true,row1 和 row2 都是 ["1", "2"]。 对于 TrimWhiteSpace==false,row1 和 row2 都是 [" 1 ", " 2 "]。

我想要的是 row1==["1", "2"] 和 row2==[" 1 ", " 2 "]。

【问题讨论】:

  • 我阅读了文档并搜索了网络(我认为这个网站不用多说)。正如我所描述的,我使用库尝试了各种代码组合。你在说什么?你认为这不是一个好问题吗?
  • 在寻找相同答案时偶然发现了这一点。已将 @EngineerDollery 的最后一条评论标记为删除,因为它违反了 SO 的行为准则,我希望他们能够基于他们向史蒂夫提供“建议”而意识到这一点......

标签: csv textfieldparser


【解决方案1】:

虽然回答得晚了,但发现这个问题很有趣并且投票率很高,因为 IMO 令人惊讶的是,在所述条件下没有内置方法来保持空白。

因此假设输入与问题相同,并添加一行以同时保留双引号转义字符 (an immediately following double quote):

1 , 2 
" 1 ", " 2 "
" a ""quoted"" word ", " hello world "

HasFieldsEnclosedInQuotes 设置为false,并使用简单的Regex 处理任何用引号括起来的字段:

var separator = new string('=', 40);
Console.WriteLine(separator);
// demo only - show the input lines read from a text file 
var text = File.ReadAllText(inputPath);
var lines = text.Split(
    new string[] { Environment.NewLine }, 
    StringSplitOptions.None
);

using (var textReader = new StringReader(text))
{
    using (var parser = new TextFieldParser(textReader))
    {
        parser.TextFieldType = FieldType.Delimited;
        parser.SetDelimiters(",");
        parser.TrimWhiteSpace = true;
        parser.HasFieldsEnclosedInQuotes = false;
        // remove double quotes, since HasFieldsEnclosedInQuotes is false
        var regex = new Regex(@"
        # match double quote 
        \""    
        # if not immediately followed by a double quote
        (?!\"")
        ",
            RegexOptions.IgnorePatternWhitespace
        );

        var rowStart = 0;
        while (parser.PeekChars(1) != null)
        {
            Console.WriteLine(
                "row {0}: {1}", parser.LineNumber, lines[rowStart]
            );
            var fields = parser.ReadFields();
            for (int i = 0; i < fields.Length; ++i)
            {
                Console.WriteLine(
                    "parsed field[{0}] = [{1}]", i,
                    regex.Replace(fields[i], "")
                );
            }
            ++rowStart;
            Console.WriteLine(separator);
        }
    }
}

输出:

========================================
row 1: 1 , 2
parsed field[0] = [1]
parsed field[1] = [2]
========================================
row 2: " 1 ", " 2 "
parsed field[0] = [ 1 ]
parsed field[1] = [ 2 ]
========================================
row 3: " a ""quoted"" word ", " hello world "
parsed field[0] = [ a "quoted" word ]
parsed field[1] = [ hello world ]
========================================

【讨论】:

  • 感谢您的努力。但是,使用 HasFieldsEnclosedInQuotes=false 解析器不会忽略字段中的逗号。例如,"a,b",c 的结果是 [a] [b] [c] 但应该是 [a,b] [c]。
  • 我很确定没有办法用解析器做我想做的事......解析器有一个致命的缺陷(错误)。但是,我想我还是会问问周围的。感谢您的尝试。
猜你喜欢
  • 1970-01-01
  • 2018-11-17
  • 1970-01-01
  • 2018-06-03
  • 1970-01-01
  • 1970-01-01
  • 2021-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多