sam*_*miz 20 c# csv asp.net text-parsing
我需要能够解析CSV和TSV文件.我不能依赖用户知道差异,所以我想避免要求用户选择类型.有没有一种简单的方法来检测正在使用哪个分隔符?
一种方法是读取每一行并计算制表符和逗号,并找出哪一行最常用.当然,数据可能包括逗号或制表符,因此说起来容易做起来难.
编辑:这个项目的另一个有趣的方面是,当我阅读它时,我还需要检测文件的模式,因为它可能是众多文件中的一个.这意味着在解析它之前我不会知道有多少个字段.
Tim*_*ker 15
在Python中,csv模块中有一个Sniffer类,可用于猜测给定文件的分隔符和引号字符.它的策略是(引自csv.py的文档字符串):
[首先,查看]包含在两个相同引号(可能的quotechar)之间的文本,这些引号之前和之后是相同的字符(可能的分隔符).例如:
,'some text',
Run Code Online (Sandbox Code Playgroud)
获胜最多的引用,与分隔符相同.如果没有quotechar,则无法以这种方式确定分隔符.
在这种情况下,请尝试以下方法:
分隔符应在每行上出现相同的次数.但是,由于数据格式错误,可能不会.我们不想要全有或全无的方法,所以我们允许这个数字的微小变化.
出于性能原因,数据以块的形式进行评估,因此它可以尝试并评估可能的最小部分数据,并根据需要评估其他块.
我不打算在这里引用源代码 - 它位于每个Python安装的Lib目录中.
请记住,CSV也可以使用分号而不是逗号作为分隔符(例如,在德语版本的Excel中,CSV以分号分隔,因为逗号在德国用作小数分隔符...)
dom*_*mer 14
您可以在预览窗口中显示结果 - 类似于Excel的工作方式.在这种情况下使用错误的分隔符时非常清楚.然后,您可以允许他们选择一系列分隔符并实时预览更新.
然后你可以简单地猜测开始时的分隔符(例如,首先是逗号或制表符).
我遇到了类似的需求,并认为我会分享我的想法。我还没有通过它运行大量数据,因此可能存在边缘情况。此外,请记住,此函数的目标不是 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;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24056 次 |
| 最近记录: |