Introduction

A common requirement is to have applications share data with other programs. Although there are interfaces available to work with, for example, Microsoft Excel data files, this approach is generally complex, involves a fair amount of overhead, and requires that support libraries accompany your application.

Comma-Separated Values (CSV) Files

A much simpler way to have your application share data is by reading and writing Comma-Separated Values (CSV) files. CSV files can easily be read and written by many programs, including Microsoft Excel.

For the most part, reading and writing CSV files is trivial. As the name suggestions, a CSV file is simply a plain text file that contains one or more values per line, separated by commas. Each value is a field (or column in a spreadsheet), and each line is a record (or row in a spreadsheet).

However, there is slightly more work involved. Double quotes are used to wrap values that contain commas so that the commas are not interpreted as a value separator. The same is also done for values that contain double quotes. In addition, two double quotes together signify a double quote in the value and not a value separator.

So this seems like a perfect task for a handy little C# class. Listing 1 shows my CsvFileWriter and CsvFileReaderclasses.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text; namespace ReadWriteCsv
{
/// <summary>
/// Class to store one CSV row
/// </summary>
public class CsvRow : List<string>
{
public string LineText { get; set; }
} /// <summary>
/// Class to write data to a CSV file
/// </summary>
public class CsvFileWriter : StreamWriter
{
public CsvFileWriter(Stream stream)
: base(stream)
{
} public CsvFileWriter(string filename)
: base(filename)
{
} /// <summary>
/// Writes a single row to a CSV file.
/// </summary>
/// <param name="row">The row to be written</param>
public void WriteRow(CsvRow row)
{
StringBuilder builder = new StringBuilder();
bool firstColumn = true;
foreach (string value in row)
{
// Add separator if this isn't the first value
if (!firstColumn)
builder.Append(',');
// Implement special handling for values that contain comma or quote
// Enclose in quotes and double up any double quotes
if (value.IndexOfAny(new char[] { '"', ',' }) != -)
builder.AppendFormat("\"{0}\"", value.Replace("\"", "\"\""));
else
builder.Append(value);
firstColumn = false;
}
row.LineText = builder.ToString();
WriteLine(row.LineText);
}
} /// <summary>
/// Class to read data from a CSV file
/// </summary>
public class CsvFileReader : StreamReader
{
public CsvFileReader(Stream stream)
: base(stream)
{
} public CsvFileReader(string filename)
: base(filename)
{
} /// <summary>
/// Reads a row of data from a CSV file
/// </summary>
/// <param name="row"></param>
/// <returns></returns>
public bool ReadRow(CsvRow row)
{
row.LineText = ReadLine();
if (String.IsNullOrEmpty(row.LineText))
return false; int pos = ;
int rows = ; while (pos < row.LineText.Length)
{
string value; // Special handling for quoted field
if (row.LineText[pos] == '"')
{
// Skip initial quote
pos++; // Parse quoted value
int start = pos;
while (pos < row.LineText.Length)
{
// Test for quote character
if (row.LineText[pos] == '"')
{
// Found one
pos++; // If two quotes together, keep one
// Otherwise, indicates end of value
if (pos >= row.LineText.Length || row.LineText[pos] != '"')
{
pos--;
break;
}
}
pos++;
}
value = row.LineText.Substring(start, pos - start);
value = value.Replace("\"\"", "\"");
}
else
{
// Parse unquoted value
int start = pos;
while (pos < row.LineText.Length && row.LineText[pos] != ',')
pos++;
value = row.LineText.Substring(start, pos - start);
} // Add field to list
if (rows < row.Count)
row[rows] = value;
else
row.Add(value);
rows++; // Eat up to and including next comma
while (pos < row.LineText.Length && row.LineText[pos] != ',')
pos++;
if (pos < row.LineText.Length)
pos++;
}
// Delete any unused items
while (row.Count > rows)
row.RemoveAt(rows); // Return true if any columns read
return (row.Count > );
}
}
}
Listing 1: CsvFileWriter and CsvFileReader Classes

Because the .NET stream classes generally seem to be split into reading and writing, I decided to follow that pattern with my CSV class and split it into CsvFileWriter and CsvFileReader. This also simplifies the code because neither class needs to worry about which mode the file is in or protect against the user switching modes.

The writer class performs any encoding necessary, as I described above, and the reader class performs any necessary decoding.

Using the code

Both classes take a CsvRow argument. The CsvRow class derives from List<string>, so it's basically just a list of strings.

When you call CsvFileWriter.WriteRow(), the row argument specifies the string values to write out. And when you call CsvFileReader.ReadRow(), the row argument returns the values that were read in.

CsvFileReader.ReadRow() also places the entire line into the CsvRow.LineText member, just in case the caller wants to inspect that. Finally, CsvFileReader.ReadRow() returns a Boolean value that is false when no values could be read at the current line. Under normal circumstances, this would indicate the end of the file.

Listing 2 demonstrates using the classes.

void WriteTest()
{
// Write sample data to CSV file
using (CsvFileWriter writer = new CsvFileWriter("WriteTest.csv"))
{
for (int i = ; i < ; i++)
{
CsvRow row = new CsvRow();
for (int j = ; j < ; j++)
row.Add(String.Format("Column{0}", j));
writer.WriteRow(row);
}
}
} 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();
}
}
}
Listing 2: Sample Code to Write and Read CSV files

Conclusion

That's about all there is to it. The classes are fairly simple so I didn't include a sample project. All the code for the classes is shown in Listing 1. Note that this code, as presented, does not handle quoted values that span multiple lines.

This code should be helpful for anyone wanting an easy way to share data with Microsoft Excel or any other program that can read or write CSV files.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Also this article comes from : http://www.codeproject.com/Articles/415732/Reading-and-Writing-CSV-Files-in-Csharp

Reading and Writing CSV Files in C#的更多相关文章

  1. Reading and writing RData files

    前面添加个lapply()或者dplyr::llply()就能读取,储存多个文件了.http://bluemountaincapital.github.io/FSharpRProvider/readi ...

  2. Reading Csv Files with Text_io in Oracle D2k Forms

    Below is the example to read and import comma delimited csv file in oracle forms with D2k_Delimited_ ...

  3. Writing Text Files On The Client in Oracle Forms 10g

    Below is the example to write file on client in Oracle Forms 10g with webutil library package.Note:  ...

  4. PostgreSQL Reading Ad Writing Files、Execution System Instructions Vul

    catalog . postgresql简介 . 文件读取/写入 . 命令执行 . 影响范围 . 恶意代码分析 . 缓解方案 1. postgresql简介 PostgreSQL 是一个自由的对象-关 ...

  5. Reading or Writing to Another Processes Memory in C# z

    http://www.jarloo.com/reading-and-writing-to-memory/ Declarations [Flags] public enum ProcessAccessF ...

  6. Apache POI – Reading and Writing Excel file in Java

    来源于:https://www.mkyong.com/java/apache-poi-reading-and-writing-excel-file-in-java/ In this article, ...

  7. Reading and writing

    A text file is a sequence of characters stored on a permanent medium like a hard drive, flash memory ...

  8. Analysis about different methods for reading and writing file in Java language

    referee:Java Programming Tutorial Advanced Input & Output (I/O) JDK 1.4+ introduced the so-calle ...

  9. C++读写CSV文件

    前两天看了<Reading and Writing CSV Files in MFC>(http://www.codeproject.com/Articles/53759/Reading- ...

随机推荐

  1. 用C语言把双向链表中的两个结点交换位置,考虑各种边界问题。

    用C语言把双向链表中的两个结点交换位置,考虑各种边界问题. [参考] http://blog.csdn.net/silangquan/article/details/18051675

  2. 日历插件My97DatePicker的使用

    在开发过程中,我们会经常遇到让用户输入日期的表单,这类表单处理起来也不是太繁琐,就是简单的字符串和日期之间的转换.但是,如果用户不按照已设定的日期格式进行输入,必定会造成不必要的麻烦.为了更好的处理这 ...

  3. yii框架详解 之 国际化 (I18N)

    我们要开启组件中们关于语言的配置,默认的就是CPhpMessageSource,也可以改为其他的方式. #组件配置中  'messages' => array(     'class'=> ...

  4. sqlserverJDBC驱动链接

    final String DRIVER="com.microsoft.jdbc.sqlserver.SQLServerDriver"; final String URL=" ...

  5. MAC系统下,删除.svn文件

    MAC系统下,.svn文件是隐藏的. 如果项目是非export导出的,那么项目中会有很多的.svn文件. 如果项目的体积非常庞大,我们如何快速的批量删除.svn文件呢?下面是操作方法: 打开终端,cd ...

  6. 模板类重载<<运算符

    写了一个Matrix模板类,需要重载<<, 1.需要友元函数 2.需要此函数的实现在.h中(本人试验出来的,放在.cpp中编译不通过) template <typename T> ...

  7. 字符匹配算法之Boyer-Moore算法

    Boyer-Moore算法的精华是从后向前,取好后缀与坏后缀中的最大移动位移动搜索词,以达到最快速检索的效果. 详情参考:http://www.ruanyifeng.com/blog/2013/05/ ...

  8. kmp

    #include <bits/stdc++.h> #define MAXN 100000 using namespace std; string a, b; int next[MAXN]; ...

  9. 设计模式之构建者模式(Builder):初步理解

    构建者(Builder)设计模式(又叫生成器设计模式): 当一个类的内部数据过于复杂的时候(通常是负责持有数据的类,比如Config.VO.PO.Entity...),要创建的话可能就需要了解这个类的 ...

  10. FragmentPagerAdapter实现刷新

    在fragmentpageadapter的instantiateItem方法里,他会先去FragmentManager里面去查找有没有相关的fragment如果有就直接使用如果没有才会触发fragme ...