【问题标题】:How to keep quotes when parsing csv file?解析csv文件时如何保留引号?
【发布时间】:2023-12-03 01:40:02
【问题描述】:

我正在使用Microsoft.VisualBasic.FileIO.TextFieldParser 读取 csv 文件,对其进行编辑,然后对其进行解析。

问题是解析后没有保留引号。

我尝试使用parser.HasFieldsEnclosedInQuotes = true;,但由于某种原因它似乎没有保留引号。

当字段包含引号时,此问题会中断,例如: 之前

 "some, field" 

之后

 some, field 

作为两个单独的字段

这是我的方法

public static void CleanStaffFile()
    {
        String path = @"C:\file.csv";
        String dpath = String.Format(@"C:\file_{0}.csv",DateTime.Now.ToString("MMddyyHHmmss"));
        List<String> lines = new List<String>();

        if (File.Exists(path))
        {
            using (TextFieldParser parser = new TextFieldParser(path))
            {
                parser.HasFieldsEnclosedInQuotes = true;
                parser.Delimiters = new string[] { "," };

                while (!parser.EndOfData)
                {
                    string[] parts = parser.ReadFields();

                    if (parts == null)
                    {
                        break;
                    }

                    if ((parts[12] != "") && (parts[12] != "*,116"))
                    {
                        parts[12] = parts[12].Substring(0, 3);
                    }
                    else
                    {
                        parts[12] = "0";
                    }

                    lines.Add(string.Join(",", parts));
                }
            }

            using (StreamWriter writer = new StreamWriter(dpath, false))
            {
                foreach (String line in lines)
                    writer.WriteLine(line);
            }

        }

        MessageBox.Show("CSV file successfully processed :\n");
    }

【问题讨论】:

  • 如果字段用引号限定,它会将字段视为一个数据项。如果数据的引号部分,您将需要使用不同的文本限定符。
  • 所以你想在string.Join(",", parts)修改它后有引号?然后很容易,因为之前只有包含分隔符的字段用引号括起来。只需在 String.Join 之前再次添加它们。
  • 请显示一些有问题的数据,以使问题更容易。

标签: c# csv double-quotes textfieldparser


【解决方案1】:

所以你想在string.Join(",", parts) 修改后有引号?然后很容易,因为之前只有包含分隔符的字段用引号括起来。只需在 String.Join 之前再次添加它们。

所以之前(和想要的):

"some, field" 

之后(不需要):

some, field 

这应该可行:

string[] fields = parser.ReadFields();
// insert your logic here ....
var newFields = fields 
    .Select(f => f.Contains(",") ? string.Format("\"{0}\"", f) : f);
lines.Add(string.Join(",", newFields));

编辑

我想保留引号,即使不包含逗号

那就更简单了:

var newFields = fields.Select(f => string.Format("\"{0}\"", f));

【讨论】:

  • 我需要在那里插入什么逻辑?即使不包含逗号,我也想保留引号谢谢
  • @meda:这只是我省略的部分。我必须承认,我不确定您实际上想要实现什么。但是,我认为这与如何保留已删除的引号无关。所以// insert your logic here .... 是您的代码中以if (parts == null) 开头的内容。 编辑我的答案根据“保留引号,即使不包含引号”。
  • 我的意思是即使不包含逗号
【解决方案2】:

TextFieldParser.HasFieldsEnclosedInQuotes 属性的用法如下,来自 MSDN 页面:

如果属性为 True,则解析器假定字段用引号 (" ") 括起来,并且可能包含行尾。

如果一个字段用引号括起来,例如abc, "field2a,field2b", field3,并且这个属性是True,那么所有用引号括起来的文本都将按原样返回;此示例将返回 abc|field2a,field2b|field3。将此属性设置为 False 将使此示例返回 abc|"field2a|field2b"|field3

引号将指示字段的开始和结束,然后可能包含用于通常分隔字段的字符。如果你的数据本身有引号,你需要将HasFieldsEnclosedInQuotes设置为false

如果您的数据字段可以同时包含分隔符和引号,则需要在解析之前开始转义引号,这是一个问题。基本上,您已经超越了简单 CSV 文件的功能。

【讨论】: