|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
using System.Web;
|
|
|
using System.Data;
|
|
|
using System.IO;
|
|
|
using System.Text;
|
|
|
|
|
|
/// <summary>
|
|
|
///ICSVWriterReader 的摘要说明
|
|
|
/// </summary>
|
|
|
public class ICSVWriterReader
|
|
|
{
|
|
|
// C# 读写CSV文件到DataTable
|
|
|
public interface ICSVWriterReaderDo
|
|
|
{//define a interface
|
|
|
string CSVFile { get; set; } //csv file
|
|
|
DataTable Read();//read csv to DataTable.
|
|
|
DataTable ReadTitle();//read csv to DataTable.
|
|
|
bool Write(DataTable dt); //convert datatable to csv
|
|
|
string WritelineString(DataTable dt);//返回表对应csv的字符串
|
|
|
}
|
|
|
|
|
|
public class CSVHelper : ICSVWriterReader
|
|
|
{
|
|
|
private string _csvFile;
|
|
|
|
|
|
public CSVHelper(string csvFile)
|
|
|
{
|
|
|
this._csvFile = csvFile;
|
|
|
}
|
|
|
|
|
|
#region ICSVWriterReader Members
|
|
|
|
|
|
public string CSVFile
|
|
|
{
|
|
|
get { return _csvFile; }
|
|
|
set { _csvFile = value; }
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取CSV文件返回table,出错则返回对应错误 CSV格式分隔符,
|
|
|
/// </summary>
|
|
|
/// <param name="Result"></param>
|
|
|
/// <param name="Table"></param>
|
|
|
public void Read(out string Result , out DataTable Table)
|
|
|
{
|
|
|
Table = new DataTable();
|
|
|
Result = "True";
|
|
|
FileInfo fi = new FileInfo(this._csvFile);
|
|
|
if (fi == null || !fi.Exists)
|
|
|
Result = "文件不存在!" + this._csvFile;
|
|
|
|
|
|
//StreamReader reader = new StreamReader(this._csvFile, Encoding.GetEncoding("GB2312"));
|
|
|
StreamReader reader = new StreamReader(this._csvFile, Encoding.GetEncoding("UTF-8"));
|
|
|
|
|
|
string line = string.Empty; int lineNumber = 0;
|
|
|
|
|
|
try
|
|
|
{
|
|
|
|
|
|
|
|
|
while ((line = reader.ReadLine()) != null)
|
|
|
{
|
|
|
if (lineNumber == 0)
|
|
|
{//Create Tole
|
|
|
Table = CreateDataTable(line);
|
|
|
if (Table.Columns.Count == 0)
|
|
|
Result = "首行出错!";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
bool isSuccess = CreateDataRow(ref Table, line);
|
|
|
if (!isSuccess)
|
|
|
Result = "第" + lineNumber + "出错!";
|
|
|
}
|
|
|
lineNumber++;
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
throw ex;
|
|
|
}
|
|
|
reader.Close();
|
|
|
}
|
|
|
|
|
|
|
|
|
public void Read(out string Result, out DataTable Table, string tag)
|
|
|
{
|
|
|
Table = new DataTable();
|
|
|
Result = "True";
|
|
|
FileInfo fi = new FileInfo(this._csvFile);
|
|
|
if (fi == null || !fi.Exists)
|
|
|
Result = "文件不存在!" + this._csvFile;
|
|
|
|
|
|
StreamReader reader = new StreamReader(this._csvFile, Encoding.GetEncoding("GB2312"));
|
|
|
//StreamReader reader = new StreamReader(this._csvFile, Encoding.GetEncoding("UTF-8"));
|
|
|
|
|
|
string line = string.Empty; int lineNumber = 0;
|
|
|
|
|
|
try
|
|
|
{
|
|
|
|
|
|
|
|
|
while ((line = reader.ReadLine()) != null)
|
|
|
{
|
|
|
if (lineNumber == 0)
|
|
|
{//Create Tole
|
|
|
Table = CreateDataTable(line);
|
|
|
if (Table.Columns.Count == 0)
|
|
|
Result = "首行出错!";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
bool isSuccess = CreateDataRow(ref Table, line);
|
|
|
if (!isSuccess)
|
|
|
Result = "第" + lineNumber + "出错!";
|
|
|
}
|
|
|
lineNumber++;
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
throw ex;
|
|
|
}
|
|
|
reader.Close();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取CSV文件返回table,出错则返回对应错误 CSV格式分隔符;
|
|
|
/// </summary>
|
|
|
/// <param name="Result"></param>
|
|
|
/// <param name="Table"></param>
|
|
|
public void ReadTitle(out string Result, out DataTable Table)
|
|
|
{
|
|
|
Table = new DataTable();
|
|
|
Result = "True";
|
|
|
FileInfo fi = new FileInfo(this._csvFile);
|
|
|
if (fi == null || !fi.Exists)
|
|
|
Result = "文件不存在!" + this._csvFile;
|
|
|
|
|
|
StreamReader reader = new StreamReader(this._csvFile, Encoding.GetEncoding("GB2312"));
|
|
|
|
|
|
string line = string.Empty; int lineNumber = 0;
|
|
|
|
|
|
try
|
|
|
{
|
|
|
|
|
|
|
|
|
while ((line = reader.ReadLine()) != null)
|
|
|
{
|
|
|
if (lineNumber == 0)
|
|
|
{//Create Tole
|
|
|
Table = CreateDataTableTitle(line);
|
|
|
if (Table.Columns.Count == 0)
|
|
|
Result = "首行出错!";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
bool isSuccess = CreateDataRowTitle(ref Table, line);
|
|
|
if (!isSuccess)
|
|
|
Result = "第" + lineNumber + "出错!";
|
|
|
}
|
|
|
lineNumber++;
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
throw ex;
|
|
|
}
|
|
|
reader.Close();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 传入表datatable返回对应csv格式的字符串
|
|
|
/// </summary>
|
|
|
/// <param name="dt">需要转换的表</param>
|
|
|
/// <returns>生成的对应的csv格式的字符串</returns>
|
|
|
public bool Write(DataTable dt)
|
|
|
{
|
|
|
FileInfo fi = new FileInfo(this._csvFile);
|
|
|
if (fi == null) return false;
|
|
|
|
|
|
if (dt == null || dt.Columns.Count == 0 || dt.Rows.Count == 0) return false;
|
|
|
|
|
|
StreamWriter writer = new StreamWriter(this._csvFile, false, System.Text.Encoding.Default);
|
|
|
|
|
|
string line = string.Empty;
|
|
|
|
|
|
line = CreateTitle(dt);
|
|
|
writer.WriteLine(line);
|
|
|
|
|
|
foreach (DataRow dr in dt.Rows)
|
|
|
{
|
|
|
line = CretreLine(dr);
|
|
|
writer.WriteLine(line);
|
|
|
}
|
|
|
|
|
|
writer.Close();
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
private DataTable CreateDataTable(string line)
|
|
|
{
|
|
|
DataTable dt = new DataTable();
|
|
|
int i =0;
|
|
|
foreach (string field in
|
|
|
read_csv(line)[0])
|
|
|
{
|
|
|
i++;
|
|
|
//如果标题为空则为第几列
|
|
|
if (field == "")
|
|
|
{
|
|
|
dt.Columns.Add("NO"+i.ToString());
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
dt.Columns.Add(field);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return dt;
|
|
|
}
|
|
|
|
|
|
private bool CreateDataRow(ref DataTable dt, string line)
|
|
|
{
|
|
|
DataRow dr = dt.NewRow();
|
|
|
|
|
|
string[] fileds = read_csv(line)[0];
|
|
|
|
|
|
if (fileds.Length == 0 || fileds.Length != dt.Columns.Count) return false;
|
|
|
|
|
|
for (int i = 0; i < fileds.Length; i++)
|
|
|
{
|
|
|
dr[i] = fileds[i];
|
|
|
}
|
|
|
|
|
|
dt.Rows.Add(dr);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 传入封号分割的CSV生成表头如:xxx;xxx
|
|
|
/// </summary>
|
|
|
/// <param name="line">字符串</param>
|
|
|
/// <returns></returns>
|
|
|
private DataTable CreateDataTableTitle(string line)
|
|
|
{
|
|
|
DataTable dt = new DataTable();
|
|
|
int i = 0;
|
|
|
foreach (string field in
|
|
|
read_csvTitle(line)[0])
|
|
|
{
|
|
|
i++;
|
|
|
//如果标题为空则为第几列
|
|
|
if (field == "")
|
|
|
{
|
|
|
dt.Columns.Add("NO" + i.ToString());
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
dt.Columns.Add(field);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return dt;
|
|
|
}
|
|
|
|
|
|
private bool CreateDataRowTitle(ref DataTable dt, string line)
|
|
|
{
|
|
|
DataRow dr = dt.NewRow();
|
|
|
|
|
|
string[] fileds = read_csvTitle(line)[0];
|
|
|
|
|
|
if (fileds.Length == 0 || fileds.Length != dt.Columns.Count) return false;
|
|
|
|
|
|
for (int i = 0; i < fileds.Length; i++)
|
|
|
{
|
|
|
dr[i] = fileds[i];
|
|
|
}
|
|
|
|
|
|
dt.Rows.Add(dr);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
private string CreateTitle(DataTable dt)
|
|
|
{
|
|
|
string line = string.Empty;
|
|
|
|
|
|
for (int i = 0; i < dt.Columns.Count; i++)
|
|
|
{
|
|
|
if (dt.Columns[i].ColumnName.ToString().IndexOf(",") != -1)
|
|
|
{
|
|
|
line = line + "\"" + dt.Columns[i].ColumnName + "\",";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
line = line + dt.Columns[i].ColumnName + ",";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
line = line.Substring(0, line.Length - 1);
|
|
|
|
|
|
return line;
|
|
|
}
|
|
|
|
|
|
private string CretreLine(DataRow dr)
|
|
|
{
|
|
|
string line = "";
|
|
|
|
|
|
for (int i = 0; i < dr.ItemArray.Length; i++)
|
|
|
{
|
|
|
if (dr[i].ToString().IndexOf(",") != -1)
|
|
|
{
|
|
|
line = line + "\"" + dr[i] + "\",";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
line = line + dr[i] + ",";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
line = line.Substring(0, line.Length - 1);
|
|
|
|
|
|
return line;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取CSV文件到数组中,如xxx;xxx;xxx
|
|
|
/// </summary>
|
|
|
/// <param name="text">传入需要读取的CSV文件</param>
|
|
|
/// <returns></returns>
|
|
|
public static string[][] read_csvTitle(string text)
|
|
|
{
|
|
|
if (text == null)
|
|
|
return null;
|
|
|
var text_array = new List<string[]>();
|
|
|
var line = new List<string>();
|
|
|
var field = new StringBuilder();
|
|
|
//是否在双引号内
|
|
|
bool in_quata = false;
|
|
|
//字段是否开始
|
|
|
bool field_start = true;
|
|
|
for (int i = 0; i < text.Length; i++)
|
|
|
{
|
|
|
char ch = text[i];
|
|
|
if (in_quata)
|
|
|
{
|
|
|
//如果已经处于双引号范围内
|
|
|
if (ch == '\"')
|
|
|
{
|
|
|
//如果是两个引号,则当成一个普通的引号处理
|
|
|
if (i < text.Length - 1 && text[i + 1] == '\"')
|
|
|
{
|
|
|
field.Append('\"');
|
|
|
i++;
|
|
|
}
|
|
|
else
|
|
|
//否则退出引号范围
|
|
|
in_quata = false;
|
|
|
}
|
|
|
else //双引号范围内的任何字符(除了双引号)都当成普通字符
|
|
|
{
|
|
|
field.Append(ch);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
switch (ch)
|
|
|
{
|
|
|
case ';': //新的字段开始
|
|
|
line.Add(field.ToString());
|
|
|
field.Remove(0, field.Length);
|
|
|
field_start = true;
|
|
|
break;
|
|
|
case '\"'://引号的处理
|
|
|
if (field_start)
|
|
|
in_quata = true;
|
|
|
else
|
|
|
field.Append(ch);
|
|
|
break;
|
|
|
case '\r': //新的记录行开始
|
|
|
if (field.Length > 0 || field_start)
|
|
|
{
|
|
|
line.Add(field.ToString());
|
|
|
field.Remove(0, field.Length);
|
|
|
}
|
|
|
text_array.Add(line.ToArray());
|
|
|
line.Clear();
|
|
|
field_start = true;
|
|
|
//在 window 环境下,\r\n通常是成对出现,所以要跳过
|
|
|
if (i < text.Length - 1 && text[i + 1] == '\n')
|
|
|
i++;
|
|
|
break;
|
|
|
default:
|
|
|
field_start = false;
|
|
|
field.Append(ch);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
//文件结束
|
|
|
if (field.Length > 0 || field_start)
|
|
|
line.Add(field.ToString());
|
|
|
if (line.Count > 0)
|
|
|
text_array.Add(line.ToArray());
|
|
|
return text_array.ToArray();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取CSV文件到数组中,如xxx,xxx,xxx
|
|
|
/// </summary>
|
|
|
/// <param name="text">传入需要读取的CSV文件</param>
|
|
|
/// <returns></returns>
|
|
|
public static string[][] read_csv(string text)
|
|
|
{
|
|
|
if (text == null)
|
|
|
return null;
|
|
|
var text_array = new List<string[]>();
|
|
|
var line = new List<string>();
|
|
|
var field = new StringBuilder();
|
|
|
//是否在双引号内
|
|
|
bool in_quata = false;
|
|
|
//字段是否开始
|
|
|
bool field_start = true;
|
|
|
for (int i = 0; i < text.Length; i++)
|
|
|
{
|
|
|
char ch = text[i];
|
|
|
if (in_quata)
|
|
|
{
|
|
|
//如果已经处于双引号范围内
|
|
|
if (ch == '\"')
|
|
|
{
|
|
|
//如果是两个引号,则当成一个普通的引号处理
|
|
|
if (i < text.Length - 1 && text[i + 1] == '\"')
|
|
|
{
|
|
|
field.Append('\"');
|
|
|
i++;
|
|
|
}
|
|
|
else
|
|
|
//否则退出引号范围
|
|
|
in_quata = false;
|
|
|
}
|
|
|
else //双引号范围内的任何字符(除了双引号)都当成普通字符
|
|
|
{
|
|
|
field.Append(ch);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
switch (ch)
|
|
|
{
|
|
|
case ',': //新的字段开始
|
|
|
line.Add(field.ToString());
|
|
|
field.Remove(0, field.Length);
|
|
|
field_start = true;
|
|
|
break;
|
|
|
case '\"'://引号的处理
|
|
|
if (field_start)
|
|
|
in_quata = true;
|
|
|
else
|
|
|
field.Append(ch);
|
|
|
break;
|
|
|
case '\r': //新的记录行开始
|
|
|
if (field.Length > 0 || field_start)
|
|
|
{
|
|
|
line.Add(field.ToString());
|
|
|
field.Remove(0, field.Length);
|
|
|
}
|
|
|
text_array.Add(line.ToArray());
|
|
|
line.Clear();
|
|
|
field_start = true;
|
|
|
//在 window 环境下,\r\n通常是成对出现,所以要跳过
|
|
|
if (i < text.Length - 1 && text[i + 1] == '\n')
|
|
|
i++;
|
|
|
break;
|
|
|
default:
|
|
|
field_start = false;
|
|
|
field.Append(ch);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
//文件结束
|
|
|
if (field.Length > 0 || field_start)
|
|
|
line.Add(field.ToString());
|
|
|
if (line.Count > 0)
|
|
|
text_array.Add(line.ToArray());
|
|
|
return text_array.ToArray();
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
}
|
|
|
} |