【问题标题】:C# CSV replace delimiter - commas with tabs (Data may contain commas)C# CSV 替换分隔符 - 带有制表符的逗号(数据可能包含逗号)
【发布时间】:2020-09-23 14:17:30
【问题描述】:

我想用 CSV 文件中的制表符替换分隔符逗号

输入

输出

请注意,引号不应替换逗号。同样在输出中,我们要省略双引号

我尝试了以下,但代码也替换了引号括起来的单词的逗号

public void Replace_comma_with_tabs(string path)
{
   var file = File
              .ReadLines(path)
              .SkipWhile(line => string.IsNullOrWhiteSpace(line)) // To be on the safe side
              .Select((line, index) => line.Replace(',', '\t')) // replace ',' with '\t'
              .ToList();                  // Materialization, since we write into the same file
    
   File.WriteAllLines(path, file);
}

如何跳过引号括起来的单词的逗号?

【问题讨论】:

标签: c# csv


【解决方案1】:

这是一种方法。它使用标志quotesStarted 来检查是否应将逗号视为分隔符或列中文本的一部分。我还使用了StringBuilder,因为该类在字符串连接方面具有良好的性能。它读取行,然后为每一行遍历其字符并检查具有特殊含义的字符(逗号、单引号、制表符、单引号之间的逗号):

    static void Main(string[] args)
    {
        var path = "data.txt";
        var file = File.ReadLines(path).ToArray();
        StringBuilder sbFile = new StringBuilder();
        foreach (string line in file)
        {
            if (String.IsNullOrWhiteSpace(line) == false)
            {
                bool quotesStarted = false;
                StringBuilder sbLine = new StringBuilder();
                foreach (char currentChar in line)
                {
                    if (currentChar == '"')
                    {
                        quotesStarted = !quotesStarted;
                        sbLine.Append(currentChar);
                    }
                    else if (currentChar == ',')
                    {
                        if (quotesStarted)
                            sbLine.Append(currentChar);
                        else
                            sbLine.Append("\t");
                    }
                    else if (currentChar == '\t')
                        throw new Exception("Tab found");
                    else
                        sbLine.Append(currentChar);
                }

                sbFile.AppendLine(sbLine.ToString());
            }
        }

        File.WriteAllText("Result-" + path, sbFile.ToString());
    }

【讨论】:

    【解决方案2】:

    有很多方法可以做到这一点,但这里有一个。这仅包括用于转换具有逗号分隔文本和引用文本的字符串的代码。您将在 Select 语句中使用“ToTabs”而不是“Replace”。您必须加强它以添加一些错误检查。

    这将处理带引号的字段内的转义引号,并将现有的制表符转换为空格,但它不是一个完整的 CSV 解析器。

    static class CsvHelper
    {
        public static string ToTabs(this string source)
        {
            Func<char,char> getState = NotInQuotes;
            char last = ' ';
    
            char InQuotes(char ch)
            {
                if ('"' == ch && last != '"')
                    getState = NotInQuotes;
                else if ('\t' == ch)
                    ch = ' ';
    
                last = ch;
    
                return ch;
            }
    
            char NotInQuotes(char ch)
            {
                last = ch;
    
                if ('"' == ch)
                    getState = InQuotes;
                else if (',' == ch)
                    return '\t';
                else if ('\t' == ch)
                    ch = ' ';
    
                return ch;
            }
            return string.Create(source.Length, getState, (buffer,_) =>
            {
                for (int i = 0; i < source.Length; ++i)
                {
                    buffer[i] = getState(source[i]);
                }
            });
        }
    }
    
        static void Main(string[] _)
        {
            const string Source = "a,string,with,commas,\"field,with,\"\"commas\", and, another";
    
            var withTabs = Source.ToTabs();
    
            Console.WriteLine(Source);
            Console.WriteLine(withTabs);
        }
    

    【讨论】:

      【解决方案3】:

      要将字符串中的逗号更改为制表符,请使用Replace 方法。

      例子:

      str2.Replace(",", "hit tab key");
      
      string str = "Lucy, John, Mark, Grace";
      string str2 = str.Replace(",", "    ");
      

      【讨论】:

        猜你喜欢
        • 2020-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多