用C#写的读写CSV文件

用C#写的读取CSV文件的源代码

CSV文件的格子中包含逗号,引号,换行等,都能轻松读取,而且可以把数据转化成DATATABLE格式

using System;
using System.Text;
using System.Collections;
using System.IO;
using System.Data;
using System.Text.RegularExpressions;
using System.Diagnostics;

namespace CsvLib
{
 #region 类说明信息

 /// <summary>
 ///  <DL>
 ///  <DT><b>读CSV文件类,读取指定的CSV文件,可以导出DataTable</b></DT>
 ///   <DD>
 ///    <UL>
 ///    </UL>
 ///   </DD>
 ///  </DL>
 ///  <Author>yangzhihong</Author>
 ///  <CreateDate>2006/01/16</CreateDate>
 ///  <Company></Company>
 ///  <Version>1.0</Version>
 /// </summary>
 #endregion
 public class CsvStreamReader
 {
  private  ArrayList  rowAL;        //行链表,CSV文件的每一行就是一个链
  private  string  fileName;       //文件名

  private  Encoding encoding;       //编码

  public CsvStreamReader()
  {
   this.rowAL = new ArrayList();
   this.fileName = "";
   this.encoding = Encoding.Default;
  }

  /// <summary>
  ///
  /// </summary>
  /// <param name="fileName">文件名,包括文件路径</param>
  public CsvStreamReader(string fileName)
  {
   this.rowAL = new ArrayList();
   this.fileName = fileName;
   this.encoding = Encoding.Default;
   LoadCsvFile();
  }

  /// <summary>
  ///
  /// </summary>
  /// <param name="fileName">文件名,包括文件路径</param>
  /// <param name="encoding">文件编码</param>
  public CsvStreamReader(string fileName,Encoding encoding)
  {
   this.rowAL = new ArrayList();
   this.fileName = fileName;
   this.encoding = encoding;
   LoadCsvFile();
  }

  /// <summary>
  /// 文件名,包括文件路径
  /// </summary>
  public string FileName
  {
   set
   {
    this.fileName = value;
    LoadCsvFile();
   }
  }

  /// <summary>
  /// 文件编码
  /// </summary>

  public Encoding FileEncoding
  {
   set
   {
    this.encoding = value;
   }
  }

  /// <summary>
  /// 获取行数
  /// </summary>
  public int RowCount
  {
   get
   {
    return this.rowAL.Count;
   }
  }

  /// <summary>
  /// 获取列数
  /// </summary>
  public int ColCount
  {
   get
   {
    int maxCol;

    maxCol = 0;
    for (int i = 0;i<this.rowAL.Count;i++)
    {
     ArrayList colAL = (ArrayList) this.rowAL[i];

     maxCol = (maxCol > colAL.Count)?maxCol:colAL.Count;
    }

    return maxCol;
   }
  }

  /// <summary>
  /// 获取某行某列的数据

  /// row:行,row = 1代表第一行

  /// col:列,col = 1代表第一列
  /// </summary>
  public string this[int row,int col]
  {
   get
   {
    //数据有效性验证

    CheckRowValid(row);
    CheckColValid(col);
    ArrayList colAL = (ArrayList) this.rowAL[row-1];

    //如果请求列数据大于当前行的列时,返回空值

    if (colAL.Count < col)
    {
     return "";
    }

                return colAL[col-1].ToString();
   }
  }

  /// <summary>
  /// 根据最小行,最大行,最小列,最大列,来生成一个DataTable类型的数据

  /// 行等于1代表第一行

  /// 列等于1代表第一列

  /// maxrow: -1代表最大行
  /// maxcol: -1代表最大列
  /// </summary>
  public DataTable this[int minRow,int maxRow,int minCol,int maxCol]
  {
   get
   {
    //数据有效性验证

    CheckRowValid(minRow);
    CheckMaxRowValid(maxRow);
    CheckColValid(minCol);
    CheckMaxColValid(maxCol);
    if (maxRow == -1)
    {
     maxRow = RowCount;
    }
    if (maxCol == -1)
    {
     maxCol = ColCount;
    }
    if (maxRow < minRow)
    {
     throw new Exception("最大行数不能小于最小行数");
    }
    if (maxCol < minCol)
    {
     throw new Exception("最大列数不能小于最小列数");
    }
    DataTable csvDT = new DataTable();
    int   i;
    int   col;
    int   row;

    //增加列

    for (i = minCol;i <= maxCol;i++)
    {
     csvDT.Columns.Add(i.ToString());
    }
    for (row = minRow;row <= maxRow;row++)
    {
     DataRow csvDR = csvDT.NewRow();

     i = 0;
     for (col = minCol;col <=maxCol;col++)
     {
      csvDR[i] = this[row,col];
      i++;
     }
     csvDT.Rows.Add(csvDR);
    }

    return csvDT;
   }
  }

  /// <summary>
  /// 检查行数是否是有效的

  /// </summary>
  /// <param name="col"></param>
  private void CheckRowValid(int row)
  {
   if (row <= 0)
   {
    throw new Exception("行数不能小于0");
   }
   if (row > RowCount)
   {
    throw new Exception("没有当前行的数据");
   }
  }

  /// <summary>
  /// 检查最大行数是否是有效的

  /// </summary>
  /// <param name="col"></param>
  private void CheckMaxRowValid(int maxRow)
  {
   if (maxRow <= 0 && maxRow != -1)
   {
    throw new Exception("行数不能等于0或小于-1");
   }
   if (maxRow > RowCount)
   {
    throw new Exception("没有当前行的数据");
   }
  }

  /// <summary>
  /// 检查列数是否是有效的

  /// </summary>
  /// <param name="col"></param>
  private void CheckColValid(int col)
  {
   if (col <= 0)
   {
    throw new Exception("列数不能小于0");
   }
   if (col > ColCount)
   {
    throw new Exception("没有当前列的数据");
   }
  }

  /// <summary>
  /// 检查检查最大列数是否是有效的

  /// </summary>
  /// <param name="col"></param>
  private void CheckMaxColValid(int maxCol)
  {
   if (maxCol <= 0 && maxCol != -1)
   {
    throw new Exception("列数不能等于0或小于-1");
   }
   if (maxCol > ColCount)
   {
    throw new Exception("没有当前列的数据");
   }
  }

  /// <summary>
  /// 载入CSV文件
  /// </summary>
  private void LoadCsvFile()
  {
   //对数据的有效性进行验证

   if (this.fileName == null)
   {
    throw new Exception("请指定要载入的CSV文件名");
   }
   else if (!File.Exists(this.fileName))
   {
    throw new Exception("指定的CSV文件不存在");
   }
   else
   {
   }
   if (this.encoding == null)
   {
    this.encoding = Encoding.Default;
   }

   StreamReader sr = new StreamReader(this.fileName,this.encoding);
   string   csvDataLine;

   csvDataLine = "";
   while (true)
   {
    string fileDataLine;

    fileDataLine = sr.ReadLine();
    if (fileDataLine == null)
    {
     break;
    }
    if (csvDataLine == "")
    {
     csvDataLine = fileDataLine;//GetDeleteQuotaDataLine(fileDataLine);
    }
    else
    {
     csvDataLine += "/r/n" + fileDataLine;//GetDeleteQuotaDataLine(fileDataLine);
    }
    //如果包含偶数个引号,说明该行数据中出现回车符或包含逗号
    if (!IfOddQuota(csvDataLine))
    {
     AddNewDataLine(csvDataLine);
     csvDataLine = "";
    }
   }
   sr.Close();
   //数据行出现奇数个引号
   if (csvDataLine.Length > 0)
   {
    throw new Exception("CSV文件的格式有错误");
   }
  }

  /// <summary>
  /// 获取两个连续引号变成单个引号的数据行
  /// </summary>
  /// <param name="fileDataLine">文件数据行</param>
  /// <returns></returns>
  private string GetDeleteQuotaDataLine(string fileDataLine)
  {
   return fileDataLine.Replace("/"/"","/"");
  }

  /// <summary>
  /// 判断字符串是否包含奇数个引号
  /// </summary>
  /// <param name="dataLine">数据行</param>
  /// <returns>为奇数时,返回为真;否则返回为假</returns>
  private bool IfOddQuota(string dataLine)
  {
   int  quotaCount;
   bool oddQuota;

   quotaCount = 0;
   for (int i = 0;i < dataLine.Length;i++)
   {
    if (dataLine[i] == ‘/"‘)
    {
     quotaCount++;
    }
   }

   oddQuota = false;
   if (quotaCount % 2 == 1)
   {
    oddQuota = true;
   }   

   return oddQuota;
  }

  /// <summary>
  /// 判断是否以奇数个引号开始

  /// </summary>
  /// <param name="dataCell"></param>
  /// <returns></returns>
  private bool IfOddStartQuota(string dataCell)
  {
   int  quotaCount;
   bool oddQuota;

   quotaCount = 0;
   for (int i = 0;i < dataCell.Length;i++)
   {
    if (dataCell[i] == ‘/"‘)
    {
     quotaCount++;
    }
    else
    {
     break;
    }
   }

   oddQuota = false;
   if (quotaCount % 2 == 1)
   {
    oddQuota = true;
   }   

   return oddQuota;
  }

  /// <summary>
  /// 判断是否以奇数个引号结尾
  /// </summary>
  /// <param name="dataCell"></param>
  /// <returns></returns>
  private bool IfOddEndQuota(string dataCell)
  {
   int  quotaCount;
   bool oddQuota;

   quotaCount = 0;
   for (int i = dataCell.Length -1;i >= 0;i--)
   {
    if (dataCell[i] == ‘/"‘)
    {
     quotaCount++;
    }
    else
    {
     break;
    }
   }

   oddQuota = false;
   if (quotaCount % 2 == 1)
   {
    oddQuota = true;
   }   

   return oddQuota;
  }

  /// <summary>
  /// 加入新的数据行

  /// </summary>
  /// <param name="newDataLine">新的数据行</param>
  private void AddNewDataLine(string newDataLine)
  {
   Debug.WriteLine("NewLine:" + newDataLine);

   //return;

   ArrayList colAL = new ArrayList();
   string[] dataArray = newDataLine.Split(‘,‘);
   bool  oddStartQuota;       //是否以奇数个引号开始

   string      cellData;

   oddStartQuota = false;
   cellData = "";
   for (int i = 0 ;i < dataArray.Length;i++)
   {
    if (oddStartQuota)
    {
     //因为前面用逗号分割,所以要加上逗号
     cellData += "," + dataArray[i];
     //是否以奇数个引号结尾
     if (IfOddEndQuota(dataArray[i]))
     {
      colAL.Add(GetHandleData(cellData));
      oddStartQuota = false;
      continue;
     }
    }
    else
    {
     //是否以奇数个引号开始

     if (IfOddStartQuota(dataArray[i]))
     {
      //是否以奇数个引号结尾,不能是一个双引号,并且不是奇数个引号

      if (IfOddEndQuota(dataArray[i]) && dataArray[i].Length > 2 && !IfOddQuota(dataArray[i]))
      {
       colAL.Add(GetHandleData(dataArray[i]));
       oddStartQuota = false;
       continue;
      }
      else
      {

       oddStartQuota = true;
       cellData = dataArray[i];
       continue;
      }
     }
     else
     {
      colAL.Add(GetHandleData(dataArray[i]));
     }
    }
   }
   if (oddStartQuota)
   {
    throw new Exception("数据格式有问题");
   }
   this.rowAL.Add(colAL);
  }

  /// <summary>
  /// 去掉格子的首尾引号,把双引号变成单引号

  /// </summary>
  /// <param name="fileCellData"></param>
  /// <returns></returns>
  private string GetHandleData(string fileCellData)
  {
   if (fileCellData == "")
   {
    return "";
   }
   if (IfOddStartQuota(fileCellData))
   {
    if (IfOddEndQuota(fileCellData))
    {
     return fileCellData.Substring(1,fileCellData.Length-2).Replace("/"/"","/""); //去掉首尾引号,然后把双引号变成单引号
    }
    else
    {
     throw new Exception("数据引号无法匹配" + fileCellData);
    }
   }
   else
   {
    //考虑形如""    """"      """"""
    if (fileCellData.Length >2 && fileCellData[0] == ‘/"‘)
    {
     fileCellData = fileCellData.Substring(1,fileCellData.Length-2).Replace("/"/"","/""); //去掉首尾引号,然后把双引号变成单引号
    }
   }

   return fileCellData;
  }
 }
}

using System;
using System.Text;
using System.Collections;
using System.IO;
using System.Data;

namespace CsvLib
{
 #region 类说明信息
 /// <summary>
 ///  <DL>
 ///  <DT><b>写CSV文件类,首先给CSV文件赋值,最后通过Save方法进行保存操作</b></DT>
 ///   <DD>
 ///    <UL>
 ///    </UL>
 ///   </DD>
 ///  </DL>
 ///  <Author>yangzhihong</Author>
 ///  <CreateDate>2006/01/16</CreateDate>
 ///  <Company></Company>
 ///  <Version>1.0</Version>
 /// </summary>
 #endregion
 public class CsvStreamWriter
 {
  private  ArrayList  rowAL;        //行链表,CSV文件的每一行就是一个链
  private  string  fileName;       //文件名
  private  Encoding encoding;       //编码

  public CsvStreamWriter()
  {
   this.rowAL = new ArrayList();
   this.fileName = "";
   this.encoding = Encoding.Default;
  }

  /// <summary>
  ///
  /// </summary>
  /// <param name="fileName">文件名,包括文件路径</param>
  public CsvStreamWriter(string fileName)
  {
   this.rowAL = new ArrayList();
   this.fileName = fileName;
   this.encoding = Encoding.Default;
  }

  /// <summary>
  ///
  /// </summary>
  /// <param name="fileName">文件名,包括文件路径</param>
  /// <param name="encoding">文件编码</param>
  public CsvStreamWriter(string fileName,Encoding encoding)
  {
   this.rowAL = new ArrayList();
   this.fileName = fileName;
   this.encoding = encoding;
  }

  /// <summary>
  /// row:行,row = 1代表第一行
  /// col:列,col = 1代表第一列
  /// </summary>
  public string this[int row,int col]
  {
   set
   {
    //对行进行判断
    if (row <= 0)
    {
     throw new Exception("行数不能小于0");
    }
    else if (row > this.rowAL.Count) //如果当前列链的行数不够,要补齐
    {
     for (int i = this.rowAL.Count + 1;i <= row;i++)
     {
      this.rowAL.Add(new ArrayList());
     }
    }
    else
    {
    }
    //对列进行判断
    if (col <= 0)
    {
     throw new Exception("列数不能小于0");
    }
    else
    {
     ArrayList colTempAL = (ArrayList) this.rowAL[row-1];

     //扩大长度
     if (col > colTempAL.Count)
     {
      for (int i = colTempAL.Count;i <= col;i++)
      {
       colTempAL.Add("");
      }
     }
     this.rowAL[row-1] = colTempAL;
    }
    //赋值
    ArrayList colAL = (ArrayList) this.rowAL[row-1];

    colAL[col-1] = value;
    this.rowAL[row-1] = colAL;
   }
  }

  /// <summary>
  /// 文件名,包括文件路径
  /// </summary>
  public string FileName
  {
   set
   {
    this.fileName = value;
   }
  }

  /// <summary>
  /// 文件编码
  /// </summary>

  public Encoding FileEncoding
  {
   set
   {
    this.encoding = value;
   }
  }

  /// <summary>
  /// 获取当前最大行
  /// </summary>
  public int CurMaxRow
  {
   get
   {
    return this.rowAL.Count;
   }
  }

  /// <summary>
  /// 获取最大列
  /// </summary>
  public int CurMaxCol
  {
   get
   {
    int maxCol;

    maxCol = 0;
    for (int i = 0;i<this.rowAL.Count;i++)
    {
     ArrayList colAL = (ArrayList) this.rowAL[i];

     maxCol = (maxCol > colAL.Count)?maxCol:colAL.Count;
    }

    return maxCol;
   }
  }

  /// <summary>
  /// 添加表数据到CSV文件中
  /// </summary>
  /// <param name="dataDT">表数据</param>
  /// <param name="beginCol">从第几列开始,beginCol = 1代表第一列</param>
  public void AddData(DataTable dataDT,int beginCol)
  {
   if (dataDT == null)
   {
    throw new Exception("需要添加的表数据为空");
   }
   int curMaxRow;

   curMaxRow = this.rowAL.Count;
   for (int i = 0;i < dataDT.Rows.Count;i++)
   {
    for (int j = 0;j <dataDT.Columns.Count;j++)
    {
     this[curMaxRow + i + 1,beginCol + j] = dataDT.Rows[i][j].ToString();
    }
   }
  }

  /// <summary>
  /// 保存数据,如果当前硬盘中已经存在文件名一样的文件,将会覆盖
  /// </summary>
  public void Save()
  {
   //对数据的有效性进行判断
   if (this.fileName == null)
   {
    throw new Exception("缺少文件名");
   }
   else if (File.Exists(this.fileName))
   {
    File.Delete(this.fileName);
   }
   if (this.encoding == null)
   {
    this.encoding = Encoding.Default;
   }
   System.IO.StreamWriter sw = new StreamWriter(this.fileName,false,this.encoding);

   for (int i = 0 ;i < this.rowAL.Count;i++)
   {
    sw.WriteLine(ConvertToSaveLine((ArrayList) this.rowAL[i]));
   }

   sw.Close();
  }

  /// <summary>
  /// 保存数据,如果当前硬盘中已经存在文件名一样的文件,将会覆盖
  /// </summary>
  /// <param name="fileName">文件名,包括文件路径</param>
  public void Save(string fileName)
  {
   this.fileName = fileName;
   Save();
  }

  /// <summary>
  /// 保存数据,如果当前硬盘中已经存在文件名一样的文件,将会覆盖
  /// </summary>
  /// <param name="fileName">文件名,包括文件路径</param>
  /// <param name="encoding">文件编码</param>
  public void Save(string fileName,Encoding encoding)
  {
   this.fileName = fileName;
   this.encoding = encoding;
   Save();
  }

  /// <summary>
  /// 转换成保存行
  /// </summary>
  /// <param name="colAL">一行</param>
  /// <returns></returns>
  private string ConvertToSaveLine(ArrayList colAL)
  {
   string saveLine;

   saveLine = "";
   for (int i = 0;i< colAL.Count;i++)
   {
    saveLine += ConvertToSaveCell(colAL[i].ToString());
    //格子间以逗号分割
    if (i < colAL.Count - 1)
    {
     saveLine += ",";
    }
   }

   return saveLine;
  }

  /// <summary>
  /// 字符串转换成CSV中的格子
  /// 双引号转换成两个双引号,然后首尾各加一个双引号
  /// 这样就不需要考虑逗号及换行的问题
  /// </summary>
  /// <param name="cell">格子内容</param>
  /// <returns></returns>
  private string ConvertToSaveCell(string cell)
  {
   cell = cell.Replace("/"","/"/"");

   return "/"" + cell + "/"";
  }
 }
}
时间: 2024-11-09 09:47:26

用C#写的读写CSV文件的相关文章

用opencsv文件读写CSV文件

首先明白csv文件长啥样儿: 用excel打开就变成表格了,看不到细节 推荐用其它简单粗暴一点儿的编辑器,比如Notepad++, csv文件内容如下: csv文件默认用逗号分隔各列. 有了基础的了解就进入主题,用Opencsv读写csv文件 读:CSVReader 写:CSVWriter 下面分别来看一下opencsv为我们提供的方法(这里只介绍最常用的几个): 读:CSVReader 构造器中涉及三个参数: reader:就是读取文件的流对象,常用的有BufferedReader,Input

利用JavaCSV API来读写csv文件

http://blog.csdn.net/loongshawn/article/details/53423121 http://javacsv.sourceforge.net/ 转载请注明来源-作者@loongshawn:http://blog.csdn.net/loongshawn/article/details/53423121 1 背景 CSV文件的读写其实是有很多方法的,在这里介绍一种利用第三方jar包来读写CSV文件的方法. 日常工作中,如果有现成的第三方工具包,咱最好还是用现成的,有

C/C++读写csv文件

博客转载自:http://blog.csdn.net/u012234115/article/details/64465398 C++ 读写CSV文件,注意一下格式即可 #include <iostream> #include <string> #include <vector> #include <fstream> #include <sstream> using namespace std; int main() { // 写文件 ofstre

如何通过 JavaCSV 类库来优雅地(偷懒)读写 CSV 文件?

欢迎关注笔者的公众号: 小哈学Java, 专注于推送 Java 领域优质干货文章!! 个人博客: https://www.exception.site/essay/how-to-create-read-csv-by-javacsv 一.背景 小哈公司最近准备开发一套新的平台,具体什么平台,因为涉密,这里就不透露了.平台在最终的的技术选型中,其中主要依赖的技术栈是 Apache Flink, 一款 Apache 基金会开源的流处理框架,平台的核心业务都会交给 Flink 去处理,其中包括离线批量任

python3使用csv模块读写csv文件

python3使用csv模块读写csv文件 读取csv文件: import csv #打开文件,用with打开可以不用去特意关闭file了,python3不支持file()打开文件,只能用open() with open("XXX.csv","r",encoding="utf-8") as csvfile: #读取csv文件,返回的是迭代类型 read = csv.reader(csvfile) for i in read: print(i) 存

Pandas 基础(4) - 读/写 Excel 和 CSV 文件

这一节将分别介绍读/写 Excel 和 CSV 文件的各种方式: - 读入 CSV 文件 首先是准备一个 csv 文件, 这里我用的是 stock_data.csv, 文件我已上传, 大家可以直接下载下来使用. 正如前面讲过的, csv 文件可以放在 jupyter notebook 同目录下, 这样直接写文件名就可以了, 但是如果没有放在同目录下, 就需要写绝对路径, 否则读取不到. import pandas as pd df = pd.read_csv('/Users/rachel/Sit

java读写CSV文件

java读写CSV文件 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 读取csv文件中数据 将数据保存为csv文件格式 读取CSV文件中的数据 import java.io.*; import java.util.ArrayList; import java.util.StringTokenizer; public class readCSV { void readCSV(String readpath, ArrayList Nolist, ArrayList Dnalist

python读写csv文件

python自带有csv模块,如果想了解更详细的内容,可以参考官方文档 一.读操作 不知道为什么,要是打开文件时不使用'b'模式,就会有隔行出现,所以,在windows中想要正常操作csv文件,就加上b模式.delimiter来指定reader各个域之间的分隔符. def readData(): with open('csvFile.csv','rb') as fobj: csvFileReader = csv.reader(fobj,delimiter='-'); header = next(

Python-csv模块读写csv文件

import csv # 采用DictReader进行读写: # 读csv文件def get_data(self, from_file): test_data = [] with open(from_file, 'rb') as csv_file: csv.register_dialect('read', delimiter='\t', quoting=csv.QUOTE_NONE) reader = csv.DictReader(csv_file, dialect='read') for ro