在c#中读写CSV/制表符分隔文件

13

我需要从 .net 中的 CSV/Tab 分隔文件读取并写入这样的文件。

困难在于我不知道每个文件的结构,需要将 cvs/tab 文件写入 DataTable,但 FileHelpers 库似乎不支持此功能。

我已经使用 OLEDB 为 Excel 编写了代码,但是对于编写 tab 文件,我真的看不出有什么方法,所以将回到库中寻找解决方案。

有人能提供建议吗?

8个回答

15

7
你得喜欢实用性强的通用类都在 Microsoft.VisualBasic.dll 中。 - MgSam
不幸的是,它似乎不支持指定您自己的文本换行字符,它假定这是双引号并允许您打开/关闭。 - ChrisProsser
1
你能提供一个快速的例子吗?链接并不是充分的答案。如果它失效了,这个回复对任何谷歌用户都没有用处。 - Mr. C

9
我使用了这个CsvReader,它非常好用且可配置性强。它能很好地处理各种字符串和分隔符的转义。其他快速简单实现中的转义处理较差,但这个库在读取方面真的很棒。如果需要,只需添加几行代码即可添加缓存。

不支持写入,但你可以自己很容易地实现。或者从这段代码中获取灵感。


抱歉..这对我来说有点陌生,但我想在编写csv文件时我的主要考虑因素是字符串的分隔符(我已经有一段时间没有处理csv文件了)。 - Tim Almond
我添加了一个CSV写入链接,您可以将某些常量字符串替换为您喜欢的分隔符,然后就可以了。阅读比写入复杂得多... - jdehaan
1
但是编写包含任意字符串的CSV文件并不容易。记得转义序列! - Ben Voigt
你为什么会推荐这个而不是.NET自带的那一个? - Jonathan Allen

2

CsvHelper的简单示例

using (TextWriter writer = new StreamWriter(filePath)
{
    var csvWriter = new CsvWriter(writer);
    csvWriter.Configuration.Delimiter = "\t";
    csvWriter.Configuration.Encoding = Encoding.UTF8;
    csvWriter.WriteRecords(exportRecords); 
}

属性或索引器 'property' 无法赋值 -- 它是只读的。 - rjose

1

您可以在代码中创建数据表,并且(假设有标题行)可以根据文件中的第一行创建列。之后,只需要读取文件并基于其中的数据创建新行即可。

您可以使用类似以下的代码:

DataTable Tbl = new DataTable();
using(StreamReader sr = new StreamReader(path))
{
  int count = 0;
  string headerRow = sr.Read();
  string[] headers = headerRow.split("\t") //Or ","
  foreach(string h in headers)
  {
    DataColumn dc = new DataColumn(h);
    Tbl.Columns.Add(dc);
    count++;
  }
  while(sr.Peek())
  {
    string data = sr.Read();
    string[] cells = data.Split("\t") 
    DataRow row = new DataRow();
    foreach(string c in cells)
    {
      row.Columns.Add(c);
    }
    Tbl.Rows.Add(row);
  }
}

以上的代码还没有被编译,所以可能会有一些错误,但它应该能让你走上正确的轨道。

你的分割代码有误,可能是因为定界符被引号包围。 - Jonathan Allen
@Jonathan Allen:是的,确实可以。它并不是为了成为完整的解决方案...只是指向可能正确的轨迹的一个指针。 - AllenG
当我使用你的代码时,出现错误。这一行 'while(sr.Peek())' 抛出错误 "无法将类型 'int' 隐式转换为 'bool'"我感到困惑。我认为在布尔值计算中,整数值0会被视为false,所有其他整数值都会视为true?自此写作之后,C#语法有所改变吗? - Flopdong

1

0

我已经找到了最佳解决方案

http://www.codeproject.com/Articles/415732/Reading-and-Writing-CSV-Files-in-Csharp

我只是不得不重新编写

void ReadTest()
{
    // Read sample data from CSV file
    using (CsvFileReader reader = new CsvFileReader("ReadTest.csv"))
    {
        CsvRow row = new CsvRow();
        while (reader.ReadRow(row))
        {
            foreach (string s in row)
            {
                Console.Write(s);
                Console.Write(" ");
            }
            Console.WriteLine();

            row = new CsvRow(); //this line added
        }
    }
}

0

您可以读写csv文件,这对您可能会有所帮助。

将分隔符传递给参数“separationChar”

示例:-

    private DataTable dataTable = null;
    private bool IsHeader = true;
    private string headerLine = string.Empty;
    private List<string> AllLines = new List<string>();
    private StringBuilder sb = new StringBuilder();
    private char seprateChar = ',';


    public DataTable ReadCSV(string path, bool IsReadHeader, char serparationChar)
    {
        seprateChar = serparationChar;
        IsHeader = IsReadHeader;
        using (StreamReader sr = new StreamReader(path,Encoding.Default))
        {
            while (!sr.EndOfStream)
            {
              AllLines.Add( sr.ReadLine());
            }
            createTemplate(AllLines);
        }

        return dataTable;
    }
    public void WriteCSV(string path,DataTable dtable,char serparationChar)
    {
        AllLines = new List<string>();
        seprateChar = serparationChar;
        List<string> StableHeadrs = new List<string>();
        int colCount = 0;
        using (StreamWriter sw = new StreamWriter(path))
        {
            foreach (DataColumn col in dtable.Columns)
            {
                sb.Append(col.ColumnName);
                if(dataTable.Columns.Count-1 > colCount)
                sb.Append(seprateChar);
                colCount++;
            }
            AllLines.Add(sb.ToString());

            for (int i = 0; i < dtable.Rows.Count; i++)
            {
                sb.Clear();
                for (int j = 0; j < dtable.Columns.Count; j++)
                {
                    sb.Append(Convert.ToString(dtable.Rows[i][j]));
                    if (dataTable.Columns.Count - 1 > j)
                    sb.Append(seprateChar);
                }
                AllLines.Add(sb.ToString());
            }

            foreach (string dataline in AllLines)
            {
                sw.WriteLine(dataline);
            }
        }


    }

    private DataTable createTemplate(List<string> lines)
    {

        List<string> headers = new List<string>();
        dataTable = new DataTable();
        if (lines.Count > 0)
        {
            string[] argHeaders = null;
            for (int i = 0; i < lines.Count; i++)
            {
                if (i > 0)
                {
                    DataRow newRow = dataTable.NewRow();
                    // others add to rows
                    string[] argLines = lines[i].Split(seprateChar);
                    for (int b = 0; b < argLines.Length; b++)
                    {
                        newRow[b] = argLines[b];
                    }
                    dataTable.Rows.Add(newRow);

                }
                else
                {
                    // header add to columns
                    argHeaders = lines[0].Split(seprateChar);
                    foreach (string c in argHeaders)
                    {
                        DataColumn column = new DataColumn(c, typeof(string));
                        dataTable.Columns.Add(column);
                    }
                }

            }

        }
        return dataTable;
    }

0

嗯,还有另一个库Cinchoo ETL - 一个开源的CSV文件读写库。

你可以用几种方式来读取CSV文件。

Id, Name
1, Tom
2, Mark

这是如何使用该库来读取它的方法

using (var reader = new ChoCSVReader("emp.csv").WithFirstLineHeader())
{
   foreach (dynamic item in reader)
   {
      Console.WriteLine(item.Id);
      Console.WriteLine(item.Name);
   }
}

如果您已经定义了与以下CSV文件相匹配的POCO对象
public class Employee
{
   public int Id { get; set; }
   public string Name { get; set; }
}

您可以使用以下 POCO 类解析相同的文件。
using (var reader = new ChoCSVReader<Employee>("emp.csv").WithFirstLineHeader())
{
   foreach (var item in reader)
   {
      Console.WriteLine(item.Id);
      Console.WriteLine(item.Name);
   }
}

请查看CodeProject上的文章,了解如何使用它。
免责声明:我是这个库的作者。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接