CSV文件读写操作的C#实现

在处理数据交换时,经常需要一种简单且通用的方法来存储和读取数据。CSV(Comma-Separated Values,逗号分隔值)文件格式因其简单性和兼容性而广受欢迎。本文将介绍如何使用C#编写两个类,CsvFileWriterCsvFileReader,来实现对CSV文件的读写操作。

CSV文件简介

CSV文件是一种纯文本文件,其中的每一行包含一个或多个值,这些值通过逗号分隔。每个值代表一个字段(或电子表格中的一列),每行代表一个记录(或电子表格中的一行)。虽然CSV文件的读写操作相对简单,但在处理包含逗号或双引号的值时需要额外注意。

编写CsvFileWriter类

为了将数据写入CSV文件,需要创建一个CsvFileWriter类。这个类继承自StreamWriter,用于将数据写入文件。在写入每一行数据时,需要考虑以下特殊情况:

  • 如果值中包含逗号,需要用双引号将该值包围,以避免将逗号解释为值分隔符。
  • 如果值中包含双引号,同样需要用双引号包围,并在值中将双引号转义为两个双引号。

以下是CsvFileWriter类的基本实现:

using System; using System.Collections.Generic; using System.IO; using System.Text; namespace ReadWriteCsv { public class CsvRow : List<string> { public string LineText { get; set; } } public class CsvFileWriter : StreamWriter { public CsvFileWriter(Stream stream) : base(stream) { } public CsvFileWriter(string filename) : base(filename) { } public void WriteRow(CsvRow row) { StringBuilder builder = new StringBuilder(); bool firstColumn = true; foreach (string value in row) { if (!firstColumn) builder.Append(','); if (value.IndexOfAny(new char[] { ',', '\"' }) != -1) builder.AppendFormat("\"{0}\"", value.Replace("\"", "\"\"")); else builder.Append(value); firstColumn = false; } row.LineText = builder.ToString(); WriteLine(row.LineText); } } }

在上述代码中,CsvRow类用于存储一行CSV数据,而CsvFileWriter类则负责将CsvRow对象中的数据写入CSV文件。

编写CsvFileReader类

为了从CSV文件中读取数据,需要创建一个CsvFileReader类。这个类继承自StreamReader,用于从文件中读取数据。在读取每一行数据时,需要考虑以下特殊情况:

  • 如果字段被双引号包围,需要正确处理字段内的逗号和双引号。
  • 如果字段未被双引号包围,需要正确分割字段。

以下是CsvFileReader类的基本实现:

using System; using System.Collections.Generic; using System.IO; using System.Text; namespace ReadWriteCsv { public class CsvFileReader : StreamReader { public CsvFileReader(Stream stream) : base(stream) { } public CsvFileReader(string filename) : base(filename) { } public bool ReadRow(CsvRow row) { row.LineText = ReadLine(); if (String.IsNullOrEmpty(row.LineText)) return false; int pos = 0; int rows = 0; while (pos < row.LineText.Length) { string value; if (row.LineText[pos] == '"') { pos++; int start = pos; while (pos < row.LineText.Length) { if (row.LineText[pos] == '"') { pos++; if (pos >= row.LineText.Length || row.LineText[pos] != '"') { pos--; break; } pos++; } } value = row.LineText.Substring(start, pos - start).Replace("\"\"", "\""); } else { int start = pos; while (pos < row.LineText.Length && row.LineText[pos] != ',') pos++; value = row.LineText.Substring(start, pos - start); } if (rows < row.Count) row[rows] = value; else row.Add(value); rows++; while (pos < row.LineText.Length && row.LineText[pos] != ',') pos++; if (pos < row.LineText.Length) pos++; } while (row.Count > rows) row.RemoveAt(rows); return (row.Count > 0); } } }

在上述代码中,CsvFileReader类负责从CSV文件中读取数据,并将其存储到CsvRow对象中。

使用CsvFileWriter和CsvFileReader类

现在已经创建了CsvFileWriterCsvFileReader类,接下来将展示如何使用这些类来写入和读取CSV文件。

void WriteTest() { using (CsvFileWriter writer = new CsvFileWriter("WriteTest.csv")) { for (int i = 0; i < 100; i++) { CsvRow row = new CsvRow(); for (int j = 0; j < 5; j++) row.Add(String.Format("Column{0}", j)); writer.WriteRow(row); } } } void ReadTest() { 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(); } } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485