C# 在c中查找csv或文本文件的分隔符#
我想找到一个分隔符,用于分隔csv或文本文件中的列 我正在使用TextFieldParser类来读取这些文件 下面是我的代码C# 在c中查找csv或文本文件的分隔符#,c#,csv,C#,Csv,我想找到一个分隔符,用于分隔csv或文本文件中的列 我正在使用TextFieldParser类来读取这些文件 下面是我的代码 String path = @"c:\abc.csv"; DataTable dt = new DataTable(); if (File.Exists(path)) { using (Microsoft.VisualBasic.FileIO.TextFieldParser parser = new Microsoft.VisualBasic.FileIO.Tex
String path = @"c:\abc.csv";
DataTable dt = new DataTable();
if (File.Exists(path))
{
using (Microsoft.VisualBasic.FileIO.TextFieldParser parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(path))
{
parser.TextFieldType = FieldType.Delimited;
if (path.Contains(".txt"))
{
parser.SetDelimiters("|");
}
else
{
parser.SetDelimiters(",");
}
parser.HasFieldsEnclosedInQuotes = true;
bool firstLine = true;
while (!parser.EndOfData)
{
string[] fields = parser.ReadFields();
if (firstLine)
{
foreach (var val in fields)
{
dt.Columns.Add(val);
}
firstLine = false;
continue;
}
dt.Rows.Add(fields);
}
}
lblCount.Text = "Count of total rows in the file: " + dt.Rows.Count.ToString();
dgvTextFieldParser1.DataSource = dt;
我希望从文件中读取分隔符,然后传递它,而不是根据文件类型手动传递分隔符
我该怎么做呢?数学上是正确的,但毫无用处。答案:这是不可能的 实用的回答:这是可能的,但取决于你对文件结构的了解程度。它归结为一系列假设,根据我们所做的假设,答案会有所不同。如果你不能做出任何假设,那么。。。请看数学上正确的答案 例如,我们可以假设分隔符是下面集合中的一个或任意一个元素吗
List<char> delimiters = new List<char>{' ', ';', '|'};
List delimiters=新列表{“”,“;”,“|”};
或者我们可以假设分隔符产生的元素长度相等吗
我们应该试着找到一个单一字符的分隔符,还是一个单词可以是一个
等等
基于这个问题,我将假设这是第一个选项,并且我们有一组有限的可能字符,其中恰好有一个是给定文件的分隔符
你数一数每一个这样的角色出现的次数,并假设出现频率最高的就是那个?这是否足够严格,或者你需要更确定吗
List<char> delimiters = new List<char>{' ', ';', '-'};
Dictionary<char, int> counts = delimiters.ToDictionary(key => key, value => 0);
foreach(char c in delimiters)
counts[c] = textArray.Count(t => t == c);
List delimiters=新列表{',';','-'};
字典计数=分隔符。ToDictionary(key=>key,value=>0);
foreach(分隔符中的字符c)
counts[c]=textArray.Count(t=>t==c);
我不在计算机前,因此无法验证,但最后一步是从字典返回键,该键的值为最大值
您需要考虑一种特殊情况,即没有检测到分隔符,两种类型的分隔符数量相等等等。您可能需要从文件中提取n个字节,使用哈希映射/字典计算可能的分隔符字符(或找到的所有字符),然后重复最多的字符可能就是您要查找的分隔符。对我来说,用作分隔符的字符将是使用最多的字符,这是有道理的。当您重置流时,由于您使用的是文本读取器,您可能需要初始化另一个文本读取器或其他东西。如果CSV使用了多个分隔符,那么这将变得更加复杂。您可能必须忽略一些字符,如字母和数字 使用LINQ的非常简单的猜测方法:
static class CsvSeperatorDetector
{
private static readonly char[] SeparatorChars = {';', '|', '\t', ','};
public static char DetectSeparator(string csvFilePath)
{
string[] lines = File.ReadAllLines(csvFilePath);
return DetectSeparator(lines);
}
public static char DetectSeparator(string[] lines)
{
var q = SeparatorChars.Select(sep => new
{Separator = sep, Found = lines.GroupBy(line => line.Count(ch => ch == sep))})
.OrderByDescending(res => res.Found.Count(grp => grp.Key > 0))
.ThenBy(res => res.Found.Count())
.First();
return q.Separator;
}
}
这样做的目的是逐行读取文件(请注意,CSV文件可能包含换行符),然后检查每个潜在分隔符在每行中出现的频率。
然后,我们检查在大多数行上出现的分隔符,在相同行数上出现的分隔符中,我们选择分布最均匀的分隔符(例如,每行5个分隔符的排名高于在一行中出现一次,在另一行中出现10次的分隔符)。
当然,为了自己的目的,您可能需要对此进行调整,添加错误处理、回退逻辑等等。我确信它并不完美,但对我来说已经足够好了。除了文件扩展名之外,你怎么知道分隔符是什么字符?你能数一数每个字符的实例,并假设最常见的一个是分隔符吗?这只是我用来读取两个文件的一个例子。我想做的是自动检测分隔符(不是基于文件类型,而是通过读取数据)。@Henry如果文件中有带引号(“”)的数据,那么最常见的是引号,而不是分隔符。如果假定的分隔符字符在引号内,您可以使用Henry的方法并进行例外(例如,使用RegEx)。我会找到的常见分隔符是一组列表分隔符=新列表{“”,“;”,“-”,“|',”,“}@AMeh我认为这个想法是,大多数分隔格式对字段内容中出现的其他分隔符没有限制,因此,例如,您可以使用
代码>在字段中用、
或|
分隔的文本,所有文本都将被检测到。你可以尝试根据频率提出一些启发,但如果没有额外的信息,我不确定你是否能确定。你能详细说明一下为什么需要自动检测它吗?数据源不能提供额外的存储信息吗?@ryachza我正在textfieldparser类上运行一个测试,以读取不同类型的文件并在datagrid中显示数据。为了提高性能,我希望尽可能地自动化该过程,因此,如果我想在将来读取多个不同类型的文件,我可以很容易地做到这一点,而无需花费太多精力来计算每个文件的分隔符。@AMeh我不确定我是否理解您所说的“为了性能”的含义-您试图优化什么?关于读取不同的文件类型-您从哪里获取正在读取的数据?我希望您的解析器对(格式、数据)对进行操作,而不是在每次读取数据时都尝试重新检测格式?@ryachza我猜OP希望呈现数据,并且需要一些便利,以便更容易地对读取的文件进行定界。因此,优化不是在算法方面,而是不需要手动调查文件(可能就是这样)。他的意思可能是自动化,而不是优化。