13

在大多数情况下,CSV 文件是带有逗号分隔记录的文本文件。但是,有时这些文件会以分号分隔。(如果区域设置将小数分隔符设置为逗号,Excel 将在保存 CSV 时使用分号分隔符——这在欧洲很常见。参考: http ://en.wikipedia.org/wiki/Comma-separated_values#Application_support )

我的问题是,让程序猜测是逗号还是分号分隔的最佳方法是什么?

例如,像 1,1;1,1 这样的行可能不明确。它可以解释为逗号分隔为:1 1;1(字符串)1

或分号分隔为 1,1 1,1

到目前为止,我最好的猜测是尝试使用 , 和 ; 来解析文件。定界符,然后选择与第一行(通常是标题行)具有相同长度的行数最多的解析。如果两者的行数相同,请选择具有更多列的行。这样做的主要缺点是额外的开销。

想法?

4

5 回答 5

1

如果每一行都应该有相同的列数,我相信 Excel 就是这种情况,那么,使用逗号和分号,计算出第 N 行和第 N+1 行的列数。无论哪种方法(逗号或分号)产生不同的答案都是错误的(不是文件的格式)。您可以从头开始,直到其中一个被证明是不正确的。你不需要标题行或任何东西。您不必阅读比必要更多的文件,而且它永远不会为您提供文件格式的错误答案,它可能会到最后但尚未得出结论。您所需要的只是每一行都有相同数量的列属性来保存。

于 2010-08-03T19:54:57.520 回答
1

根据您正在使用的内容,如果您保证有一个标题行,那么您尝试两者的方法可能是最佳的整体实践。然后,一旦您确定发生了什么,如果您到达更下方没有所需列数的行,那么您就知道格式不正确。

通常,我会将其视为用户在上传时指定的选项,而不是程序测试。

于 2010-05-07T15:33:02.150 回答
1

您可以阅读第一行

FileReader fileReader = new FileReader(filePath);
    BufferedReader bufferedReader = new BufferedReader(fileReader);
    String s = bufferedReader.readLine();
    String substring = s.substring(s.indexOf(firstColumnName) + 3, s.indexOf(firstColumnName) + 4);
    bufferedReader.close();
    fileReader.close();
    substring.charAt(0);

然后你捕获这个值

substring.charAt(0)

取决于 CSV 是逗号还是分号可以使用最后一个值

于 2011-12-14T23:01:19.543 回答
0

这是我的代码(没有对文本进行验证)......也许它可以帮助或建立一个基础:-)!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using MoreLinq; // http://stackoverflow.com/questions/15265588/how-to-find-item-with-max-value-using-linq

namespace HQ.Util.General.CSV
{
    public class CsvHelper
    {
        public static Dictionary<LineSeparator, Func<string, string[]>>  DictionaryOfLineSeparatorAndItsFunc = new Dictionary<LineSeparator, Func<string, string[]>>();

        static CsvHelper()
        {
            DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Unknown] = ParseLineNotSeparated;
            DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Tab] = ParseLineTabSeparated;
            DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Semicolon] = ParseLineSemicolonSeparated;
            DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Comma] = ParseLineCommaSeparated;
        }

        // ******************************************************************
        public enum LineSeparator
        {
            Unknown = 0,
            Tab,
            Semicolon,
            Comma
        }

        // ******************************************************************
        public static LineSeparator GuessCsvSeparator(string oneLine)
        {
            List<Tuple<LineSeparator, int>> listOfLineSeparatorAndThereFirstLineSeparatedValueCount = new List<Tuple<LineSeparator, int>>();

            listOfLineSeparatorAndThereFirstLineSeparatedValueCount.Add(new Tuple<LineSeparator, int>(LineSeparator.Tab, CsvHelper.ParseLineTabSeparated(oneLine).Count()));
            listOfLineSeparatorAndThereFirstLineSeparatedValueCount.Add(new Tuple<LineSeparator, int>(LineSeparator.Semicolon, CsvHelper.ParseLineSemicolonSeparated(oneLine).Count()));
            listOfLineSeparatorAndThereFirstLineSeparatedValueCount.Add(new Tuple<LineSeparator, int>(LineSeparator.Comma, CsvHelper.ParseLineCommaSeparated(oneLine).Count()));

            Tuple<LineSeparator, int> bestBet = listOfLineSeparatorAndThereFirstLineSeparatedValueCount.MaxBy((n)=>n.Item2);

            if (bestBet != null && bestBet.Item2 > 1)
            {
                return bestBet.Item1;
            }

            return LineSeparator.Unknown;
        }

        // ******************************************************************
        public static string[] ParseLineCommaSeparated(string line)
        {
            // CSV line parsing : From "jgr4" in http://www.kimgentes.com/worshiptech-web-tools-page/2008/10/14/regex-pattern-for-parsing-csv-files-with-embedded-commas-dou.html
            var matches = Regex.Matches(line, @"\s?((?<x>(?=[,]+))|""(?<x>([^""]|"""")+)""|""(?<x>)""|(?<x>[^,]+)),?",
                                        RegexOptions.ExplicitCapture);

            string[] values = (from Match m in matches
                               select m.Groups["x"].Value.Trim().Replace("\"\"", "\"")).ToArray();

            return values;
        }

        // ******************************************************************
        public static string[] ParseLineTabSeparated(string line)
        {
            var matchesTab = Regex.Matches(line, @"\s?((?<x>(?=[\t]+))|""(?<x>([^""]|"""")+)""|""(?<x>)""|(?<x>[^\t]+))\t?",
                            RegexOptions.ExplicitCapture);

            string[] values = (from Match m in matchesTab
                                select m.Groups["x"].Value.Trim().Replace("\"\"", "\"")).ToArray();

            return values;
        }

        // ******************************************************************
        public static string[] ParseLineSemicolonSeparated(string line)
        {
            // CSV line parsing : From "jgr4" in http://www.kimgentes.com/worshiptech-web-tools-page/2008/10/14/regex-pattern-for-parsing-csv-files-with-embedded-commas-dou.html
            var matches = Regex.Matches(line, @"\s?((?<x>(?=[;]+))|""(?<x>([^""]|"""")+)""|""(?<x>)""|(?<x>[^;]+));?",
                                        RegexOptions.ExplicitCapture);

            string[] values = (from Match m in matches
                               select m.Groups["x"].Value.Trim().Replace("\"\"", "\"")).ToArray();

            return values;
        }

        // ******************************************************************
        public static string[] ParseLineNotSeparated(string line)
        {
            string [] lineValues = new string[1];
            lineValues[0] = line;
            return lineValues;
        }

        // ******************************************************************
        public static List<string[]> ParseText(string text)
        {
            string[] lines = text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
            return ParseString(lines);
        }

        // ******************************************************************
        public static List<string[]> ParseString(string[] lines)
        {
            List<string[]> result = new List<string[]>();

            LineSeparator lineSeparator = LineSeparator.Unknown;
            if (lines.Any())
            {
                lineSeparator = GuessCsvSeparator(lines[0]);
            }

            Func<string, string[]> funcParse = DictionaryOfLineSeparatorAndItsFunc[lineSeparator];

            foreach (string line in lines)
            {
                if (string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }

                result.Add(funcParse(line));
            }

            return result;
        }

        // ******************************************************************
    }
}
于 2014-01-13T21:35:08.263 回答
0

假设您的 csv 中有以下内容:

title,url,date,copyright,hdurl,explanation,media_type,service_version

那么你可以使用 python 的内置 CSV 模块,如下所示:

import csv
data = "title,url,date,copyright,hdurl,explanation,media_type,service_version"
sn = csv.Sniffer()
delimiter = sn.sniff(data).delimiter

打印名为的变量delimiter将返回',',这是这里的分隔符。您可以使用一些不同的分隔符进行测试。

于 2020-12-30T19:22:02.970 回答