我需要能够同时解析CSV和TSV文件。我不能依靠用户来知道差异,所以我想避免让用户选择类型。是否有一种简单的方法来检测使用的是哪个分隔符?
一种方法是在每一行中阅读,同时计数制表符和逗号,找出每行中最一致的用法。当然,数据可以包括逗号或制表符,所以说起来容易做起来难。
编辑:这个项目的另一个有趣的方面是,我在读取文件时也需要检测它的模式,因为它可能是许多文件中的一个。这意味着在我能够解析它之前,我将不知道我有多少字段。
发布于 2009-04-17 19:56:36
您可以在预览窗口中显示结果-类似于Excel所做的方式。很明显,在这种情况下使用的分隔符是错误的。然后,您可以允许它们选择一个分隔符范围,并实时进行预览更新。
然后,您只需简单地猜测开始使用的分隔符(例如,逗号或制表符是否放在第一位)。
发布于 2009-04-17 21:40:48
在Python中,csv模块中有一个嗅探器类,可以用来猜测给定文件的分隔符和引号。它的策略(引用于csv.py的docstring):
首先,查找两个相同的引号(可能的商标符)之间的文本,该引号前面和后面跟着相同的字符(可能的分隔符)。例如:
,'some text',引号以最多者获胜,与分隔符相同。如果没有商标符,则不能以这种方式确定分隔符。
在这种情况下,请尝试以下方法:
分隔符应该在每一行上出现相同的次数。然而,由于格式错误的数据,它可能不会。我们不想要一个全部或不需要的方法,所以我们允许这个数字的小变化。
H 110),最符合的字符是分隔符<>h 211>G 212。
由于性能原因,数据是以块计算的,因此它可以尝试评估数据中的最小部分,并在必要时评估附加块。
我不会在这里引用源代码-它在每个Python安装的Lib目录中。
请记住,CSV也可以使用分号代替逗号作为分隔符(例如,在德语版本的Excel中,CSV是分号分隔符,因为逗号在德国用作十进制分隔符.)
发布于 2015-02-03 23:55:05
我遇到了一个类似的需要,我想我会分享我的想法。我还没有通过它运行大量的数据,所以有可能的边缘情况。此外,请记住,此函数的目标不是100%确定分隔符,而是向用户提供最佳猜测。
/// <summary>
/// Analyze the given lines of text and try to determine the correct delimiter used. If multiple
/// candidate delimiters are found, the highest frequency delimiter will be returned.
/// </summary>
/// <example>
/// string discoveredDelimiter = DetectDelimiter(dataLines, new char[] { '\t', '|', ',', ':', ';' });
/// </example>
/// <param name="lines">Lines to inspect</param>
/// <param name="delimiters">Delimiters to search for</param>
/// <returns>The most probable delimiter by usage, or null if none found.</returns>
public string DetectDelimiter(IEnumerable<string> lines, IEnumerable<char> delimiters) {
Dictionary<char, int> delimFrequency = new Dictionary<char, int>();
// Setup our frequency tracker for given delimiters
delimiters.ToList().ForEach(curDelim =>
delimFrequency.Add(curDelim, 0)
);
// Get a total sum of all occurrences of each delimiter in the given lines
delimFrequency.ToList().ForEach(curDelim =>
delimFrequency[curDelim.Key] = lines.Sum(line => line.Count(p => p == curDelim.Key))
);
// Find delimiters that have a frequency evenly divisible by the number of lines
// (correct & consistent usage) and order them by largest frequency
var possibleDelimiters = delimFrequency
.Where(f => f.Value > 0 && f.Value % lines.Count() == 0)
.OrderByDescending(f => f.Value)
.ToList();
// If more than one possible delimiter found, return the most used one
if (possibleDelimiters.Any()) {
return possibleDelimiters.First().Key.ToString();
}
else {
return null;
}
}https://stackoverflow.com/questions/761932
复制相似问题