C# 解析制表符分隔的文本文件

C# 解析制表符分隔的文本文件,c#,C#,我有一个以制表符分隔的文件,其中包含一些列和行,例如:某些行可能对某些列没有值。 我们知道的是,顺序不会改变,所以第三个制表符分隔的东西总是用于第3列,以此类推 Column1 Column2 Column3 .... Column12 .... Column34 ... Column50 123 34 ABC 234 DEF as@ddd.com True 45 NYC

我有一个以制表符分隔的文件,其中包含一些列和行,例如:某些行可能对某些列没有值。 我们知道的是,顺序不会改变,所以第三个制表符分隔的东西总是用于第3列,以此类推

Column1  Column2  Column3 .... Column12 .... Column34 ... Column50
123  34 ABC
234     DEF                                   as@ddd.com    True
     45           NYC                         wwe@dsds.com  False      
现在我需要读取这个文件,但不是所有的列对我的程序都很重要。例如,我只需要对第2列、第12列和第45列中的值执行一些操作


您建议采用什么方法?

只需读取文件的所有行,然后按制表符分隔符拆分,即可访问每一列

   var fileArray = File.ReadAllLines(myLocation);
    
        for(int i=0;i<fileArray.Length;i++)
        {
           var line=fileArray[i];

           if (i == 0)
           {  
              //handle column names
           }
           else
           {
             var columns = line.Split('\t');
             string value = columns[3];
           }
        }
若您使用的是.NETFramework 4.0或更高版本,则可以使用该方法,而不会对性能造成任何损失,因为它不会将整个文件内容加载到内存中

试试这个:

using System.IO;

class FileData
{
public string Column2{ get; set; }
public string Column12{ get; set; }
public string Column45{ get; set; }
}


List<FileData> filedata =  new List<FileData>();

 FileData temp = new FileData();
 foreach(var line in File.ReadLines("filepath.txt").Skip(1))
 {     
   var tempLine = line.Split('\t');
   temp.Column2 = tempLine[1];
   temp.Column12 = tempLine[11];
   temp.Column45 = tempLine[44]; 
   filedata.Add(temp);
 }

不要自己滚。有些微妙之处并没有立即显现出来。除其他外:

引用字段? 包含嵌入字段和/或记录分隔符的数据 错误长度记录 等 相反,使用塞巴斯蒂安·洛里昂最优秀的作品

编辑说明:尽管名称不同,但这是用于分隔文本文件的通用读取器。可配置项包括

字段分隔符字符 记录分隔符字符 引用文本的引用字符 嵌入引号的转义字符 允许或不允许评论的地方。如果启用,下面的注释字符将开始注释,并以下一个记录分隔符结束。 默认情况下,注释字符, 第一行是否为包含字段名的标题。 试试下面的方法

static void Main(string[] args)
{
    DataTable datatable = new DataTable();
    StreamReader streamreader = new StreamReader(@"C:\Temp\txt.txt");
    char[] delimiter = new char[] { '\t' };
    string[] columnheaders = streamreader.ReadLine().Split(delimiter);
    foreach (string columnheader in columnheaders)
    {
        datatable.Columns.Add(columnheader); // I've added the column headers here.
    }

    while (streamreader.Peek() > 0)
    {
        DataRow datarow = datatable.NewRow();
        datarow.ItemArray = streamreader.ReadLine().Split(delimiter);
        datatable.Rows.Add(datarow);
    }

    foreach (DataRow row in datatable.Rows)
    {
        Console.WriteLine(""----Row No: " + datatable.Rows.IndexOf(row) + "----"");

        foreach (DataColumn column in datatable.Columns)
        {
            //check what columns you need
            if (column.ColumnName == "Column2" || 
                column.ColumnName == "Column12" ||
                column.ColumnName == "Column45") 
            {
                Console.Write(column.ColumnName);
                Console.Write(" ");
                Console.WriteLine(row[column]);
            }
        }
    }
    Console.ReadLine();
}

正如尼古拉斯所说,不要自作主张,因为其中有微妙之处和特殊情况

一个选项是TextFieldParser



逐行阅读,在选项卡上拆分,抓住你需要的列。你到底在寻找什么?你是在寻找意见,还是在问题的某个特定部分遇到了问题?@Jonesy我不知道这一部分:抓住你需要的列。如果文件很大,什么是读取文件不会崩溃或内存不足的有效方法?文件可能很大,有没有更有效的方法让我们一次只能读一行呢?修改后的答案来处理列名tooin forint i=0;对不起,这是我先前回答中的一个输入错误不完整的示例-您需要定义行是什么。谢谢,但我的是制表符分隔的文本文件。您建议的是CSV?唯一的区别是您选择的字段和记录分隔符。只需将其配置为使用HT“\t”而不是逗号“,”作为字段分隔符。一个已定义对象结构的列表可能比三个独立的值列表要好:如何忽略文件的第一行?表示列名。下一行是数据,但第一行是列名Column1 Column2 Column3。。。。第12栏。。。。第34栏。。。Column50@DevWannaBe:将foreach转换为for并跳过第一行,或引入计数器或标志变量。类似于var skip=true,如果skip{skip=false;continue;},则在循环中。无论哪种方式都会起作用,这只是你认为更可读/支持的问题。为什么不只是文件。RealLeScript FielpAth.TXT.SkIP1?@ Jasyy:好点,编辑我的POWWOW…漂亮:有没有最后的想法,你可能会考虑吗?或者你觉得很好,我去用它?我很好奇你为什么在@Sudhakar上用这个答案?在我看来,这要多得多simple@Jonesy没错,我还在评估它们。现在不知道为什么这个答案没有保持它打印的记录的顺序与输入文件中的顺序相同…@Jonesy也尝试了,它崩溃了。@Devwanabe-我不知道你所说的不保持记录的顺序是什么意思。我更新了代码以显示输入文件中的行索引。我希望这有助于您了解输入文件中每行的顺序。这应该是公认的答案。非常简单,并且在获取数据后易于操作。如果您希望有一个合适的数据模型,我也喜欢@Sudhakar tilapudi answer。逐行阅读似乎让人望而生畏,只要给我所有的数据。这里的问题是,如果您想读取一个文件中包含多个列的每一列,那么
static void Main(string[] args)
{
    DataTable datatable = new DataTable();
    StreamReader streamreader = new StreamReader(@"C:\Temp\txt.txt");
    char[] delimiter = new char[] { '\t' };
    string[] columnheaders = streamreader.ReadLine().Split(delimiter);
    foreach (string columnheader in columnheaders)
    {
        datatable.Columns.Add(columnheader); // I've added the column headers here.
    }

    while (streamreader.Peek() > 0)
    {
        DataRow datarow = datatable.NewRow();
        datarow.ItemArray = streamreader.ReadLine().Split(delimiter);
        datatable.Rows.Add(datarow);
    }

    foreach (DataRow row in datatable.Rows)
    {
        Console.WriteLine(""----Row No: " + datatable.Rows.IndexOf(row) + "----"");

        foreach (DataColumn column in datatable.Columns)
        {
            //check what columns you need
            if (column.ColumnName == "Column2" || 
                column.ColumnName == "Column12" ||
                column.ColumnName == "Column45") 
            {
                Console.Write(column.ColumnName);
                Console.Write(" ");
                Console.WriteLine(row[column]);
            }
        }
    }
    Console.ReadLine();
}
using (var parser = new TextFieldParser(filePath))
{
    parser.TextFieldType = FieldType.Delimited;
    parser.SetDelimiters("\t");

    while (!parser.EndOfData)
    {
        var cols = parser.ReadFields();
        // Can now access columns, eg cols[0]
    }
}