【问题标题】:CsvHelper : How to detect the Delimiter from the given csv fileCsvHelper:如何从给定的 csv 文件中检测分隔符
【发布时间】:2015-10-26 08:22:57
【问题描述】:

我正在使用 CsvHelper 将数据读/写到 Csv 文件中。现在我想解析 csv 文件的分隔符。请问这个怎么弄?

我的代码:

     var parser = new CsvParser(txtReader);
     delimiter = parser.Configuration.Delimiter;

我总是得到分隔符是“,”,但实际上在 csv 文件中,分隔符是“\t”。

【问题讨论】:

    标签: csvhelper


    【解决方案1】:

    由于我必须处理根据用户的本地化设置,CSV 文件(保存在 MS Excel 中)可能包含不同分隔符的可能性,我最终采用了以下方法:

    public static string DetectDelimiter(StreamReader reader)
    {
        // assume one of following delimiters
        var possibleDelimiters =  new List<string> {",",";","\t","|"};
    
        var headerLine = reader.ReadLine();
    
        // reset the reader to initial position for outside reuse
        // Eg. Csv helper won't find header line, because it has been read in the Reader
        reader.BaseStream.Position = 0;
        reader.DiscardBufferedData();
    
        foreach (var possibleDelimiter in possibleDelimiters)
        {
            if (headerLine.Contains(possibleDelimiter))
            {
                return possibleDelimiter;
            }
        }
    
        return possibleDelimiters[0];
    }
    

    我还需要重置阅读器的阅读位置,因为它与我在 CsvReader 构造函数中使用的实例相同。

    当时的用法如下:

    using (var textReader = new StreamReader(memoryStream))
    {
        var delimiter = DetectDelimiter(textReader);
    
        using (var csv = new CsvReader(textReader))
        {
            csv.Configuration.Delimiter = delimiter;
    
            ... rest of the csv reader process
    
        }
    }
    

    【讨论】:

      【解决方案2】:

      我在site找到了这段代码

      public static char Detect(TextReader reader, int rowCount, IList<char> separators)
      {
          IList<int> separatorsCount = new int[separators.Count];
      
          int character;
      
          int row = 0;
      
          bool quoted = false;
          bool firstChar = true;
      
          while (row < rowCount)
          {
              character = reader.Read();
      
              switch (character)
              {
                  case '"':
                      if (quoted)
                      {
                          if (reader.Peek() != '"') // Value is quoted and 
                  // current character is " and next character is not ".
                              quoted = false;
                          else
                              reader.Read(); // Value is quoted and current and 
                      // next characters are "" - read (skip) peeked qoute.
                      }
                      else
                      {
                          if (firstChar)  // Set value as quoted only if this quote is the 
                      // first char in the value.
                              quoted = true;
                      }
                      break;
                  case '\n':
                      if (!quoted)
                      {
                          ++row;
                          firstChar = true;
                          continue;
                      }
                      break;
                  case -1:
                      row = rowCount;
                      break;
                  default:
                      if (!quoted)
                      {
                          int index = separators.IndexOf((char)character);
                          if (index != -1)
                          {
                              ++separatorsCount[index];
                              firstChar = true;
                              continue;
                          }
                      }
                      break;
              }
      
              if (firstChar)
                  firstChar = false;
          }
      
          int maxCount = separatorsCount.Max();
      
          return maxCount == 0 ? '\0' : separators[separatorsCount.IndexOf(maxCount)];
      }
      

      separators 是您可能拥有的分隔符。

      希望有所帮助:)

      【讨论】:

      • 感谢您发布此内容并引用参考资料。是的 CSV 是逗号分隔的,但我们都知道用户不会总是遵守规则并正确验证有时我们需要编写疯狂的东西
      【解决方案3】:

      CSV 是 Comma 分隔值。我认为您无法可靠地检测是否有不同的字符使用了分隔符。如果有标题行,那么您也许可以指望它。

      您应该知道使用的分隔符。打开文件时,您应该能够看到它。如果文件的来源每次都给你不同的分隔符并且不可靠,那么我很抱歉。 ;)

      如果你只是想使用不同的分隔符进行解析,那么你可以设置csv.Configuration.Delimiterhttp://joshclose.github.io/CsvHelper/#configuration-delimiter

      【讨论】:

      • @JoshClose 虽然 CSV 代表逗号分隔值,但不同的语言环境会有不同的分隔符。例如,在荷兰,我们使用分号作为列表分隔符。我想知道;为什么 CsvHelper 不从 CultureInfo 中获取默认分隔符?这样,如果您执行一些忽略区域设置的自定义 CSV,您只需要覆盖默认分隔符。
      • 如果你想为它记录一个问题,我认为这将是一个简单的改变。 github.com/JoshClose/CsvHelper/issues
      • @JoshClose 我在github创建了一个问题
      • 是的,在挪威和荷兰,可能在所有使用逗号作为小数分隔符的国家/地区,csv 文件的默认分隔符是分号。例如,Excel 将在挪威语言环境中执行此操作。因此,不处理这与不处理非 ascii 字符似乎是一种相当典型的文化盲目性。
      • 我不同意这个答案。在未知的用户上传文件中检测分隔符是一个有效问题。
      【解决方案4】:

      (至少现在)有一个 DetectDelimiter 值设置为 false。 然后,您可以添加希望测试的分隔符,尽管默认值是合理的

      【讨论】:

        猜你喜欢
        • 2021-12-17
        • 2014-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-19
        • 2018-08-20
        • 1970-01-01
        • 2018-02-18
        相关资源
        最近更新 更多