C#读取和写入CSV格式文件总结

作者:袖梨 2022-06-25

最近需求要将数据保存到.csv文件(逗号分隔值 )中然后上传到ftp服务器上,供系统调用。CSV数据格式并没有非常统一的标准 但是为了避免出错 我们在开发的时候统一格式是这样的

"name","pwd","date"

"张三","123","2015-09-30"

接下来代码处理中默认格式都是这样的 其实就是纯文本的形式


为什么要用csv文件

这就涉及到数据互通的问题,有些程序支持的表格数据另一些程序并不见得支持,而csv格式的却被大多数的应用程序支持,所以在交换保存数据的时候是个不错的选择。
 

而在项目开发中 有需要做的处理也不是很简单的

比如有csv文件的读取 数据的转换(如转成datatable),csv文件的重命名 ,csv文件的写入,文件上传到ftp服务器上等等

这里将开发的方法进行了简单的整理,以备不时之需,时间仓促,有不足之处大家多多指点。

注意的点

①文件处理完的时候一定记得关闭释放数据流 否则文件会被占用

②csv并没有严格的标准,多人开发的时候必须规定好格式,统一开发

一、将CSV文件的数据读取到DataTable中

首先,我们为了方便管理,在web网站中常常需要读取csv文件中的数据并且显示在网站上方便查询。所以比较方便的办法是见csv文件中的数据转换成datatable形式,代码如下。

/// 
/// 将CSV文件的数据读取到DataTable中
/// 
/// CSV文件路径
/// 返回读取了CSV数据的DataTable
public static DataTable OpenCSV(string filePath)
{
    DataTable dt = new DataTable();
    FileStream fs = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
    StreamReader sr = new StreamReader(fs, Encoding.UTF8);
    //StreamReader sr = new StreamReader(fs, encoding);
    //string fileContent = sr.ReadToEnd();
    //记录每次读取的一行记录
    string strLine = "";
    //记录每行记录中的各字段内容
    string[] aryLine = null;
    string[] tableHead = null;
    //标示列数
    int columnCount = 0;
    //标示是否是读取的第一行
    bool IsFirst = true;
    //逐行读取CSV中的数据
    while ((strLine = sr.ReadLine()) != null)
    {
        if (IsFirst == true)
        {
            tableHead = strLine.Split(',');
            IsFirst = false;
            columnCount = tableHead.Length;
            //创建列
            for (int i = 0; i < columnCount; i++)
            {
                tableHead[i] = tableHead[i].Replace(""", "");
                DataColumn dc = new DataColumn(tableHead[i]);
                dt.Columns.Add(dc);
            }
        }
        else
        {
            aryLine = strLine.Split(',');
            DataRow dr = dt.NewRow();
            for (int j = 0; j < columnCount; j++)
            {
                dr[j] = aryLine[j].Replace(""","");
            }
            dt.Rows.Add(dr);
        }
    }
    if (aryLine != null && aryLine.Length > 0)
    {
        dt.DefaultView.Sort = tableHead[2] + " " + "DESC";
    }
    sr.Close();
    fs.Close();
    return dt;
}


 
二、将DataTable中数据写入到CSV文件中

当然我们一个文件中的数据迁移到另一个文件中或者 直接从数据库中查询的数据 插入到csv文件中 ,有一种方法是通过datatable的形式中转,所以 需要把datatable 转成 csv 代码如下:

/// 
/// 将DataTable中数据写入到CSV文件中
/// 
/// 提供保存数据的DataTable
/// CSV的文件路径
public static bool SaveCSV(DataTable dt, string fullPath)
{
    try
    {
        FileInfo fi = new FileInfo(fullPath);
        if (!fi.Directory.Exists)
        {
            fi.Directory.Create();
        }
        FileStream fs = new FileStream(fullPath, System.IO.FileMode.Create, System.IO.FileAccess.Write);
        //StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.Default);
        StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8);
        string data = "";
        //写出列名称
        for (int i = 0; i < dt.Columns.Count; i++)
        {
            data += """ + dt.Columns[i].ColumnName.ToString() + """;
            if (i < dt.Columns.Count - 1)
            {
                data += ",";
            }
        }
        sw.WriteLine(data);
        //写出各行数据
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            data = "";
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                string str = dt.Rows[i][j].ToString();
                str = string.Format(""{0}"", str);
                data += str;
                if (j < dt.Columns.Count - 1)
                {
                    data += ",";
                }
            }
            sw.WriteLine(data);
        }
        sw.Close();
        fs.Close();
        return true;
    }
    catch {
        return false;
    }
}


 
三、修改文件名称

修改文件名称 我们需要保存历史数据 或者实时的知道那个文件被修改 可以通过改变文件的名称 如加上当天的日期等等 方便管理

/// 
/// 修改文件名称 
/// 
/// 旧的路径 完整的物理路径
/// 新的路径
/// 
public static bool ChangeFileName(string OldPath, string NewPath) {
    bool re = false;
    //OldPath = HttpContext.Current.Server.MapPath(OldPath);虚拟的
    //NewPath = HttpContext.Current.Server.MapPath(NewPath);
    try {
        if (File.Exists(OldPath)) {
            File.Move(OldPath, NewPath);
            re = true;
        }
    }
    catch {
        re = false;
    }
    return re;
}


 
四、scv文件的数据写入

直接在网页表单提交数据保存在csv文件中 直接写入文件

/// 
/// 写入文件
/// 
/// 
/// 
/// 
public static bool SaveCSV(string fullPath,string Data)
{
    bool re = true;
    try
    {
        FileStream FileStream = new FileStream(fullPath, FileMode.Append);
        StreamWriter sw = new StreamWriter(FileStream, System.Text.Encoding.UTF8);
        sw.WriteLine(Data);
        //清空缓冲区
        sw.Flush();
        //关闭流
        sw.Close();
        FileStream.Close();
    }
    catch {
        re = false;
    }
    return re;
}




C#如何读取csv格式文件


一、CSV文件规则

1 开头是不留空,以行为单位。
2 可含或不含列名,含列名则居文件第一行。
3 一行数据不跨行,无空行。
4 以半角逗号(即,)作分隔符,列为空也要表达其存在。
5 列内容如存在半角逗号(即,)则用半角引号(即',')将该字段值包含起来。
6 列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。
7 文件读写时引号,逗号操作规则互逆。
8 内码格式不限,可为 ASCII、Unicode 或者其他。
9 不支持特殊字符

二、C#读取csv文件的方法

//读CSV文件类,读取指定的CSV文件,可以导出DataTable
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;
    }
    /// 
    ///
    /// 
    /// 文件名,包括文件路径
    public CsvStreamReader(string fileName)
    {
        this.rowAL = new ArrayList();
        this.fileName = fileName;
        this.encoding = Encoding.Default;
        LoadCsvFile();
    }
    /// 
    ///
    /// 
    /// 文件名,包括文件路径
    /// 文件编码
    public CsvStreamReader(string fileName, Encoding encoding)
    {
        this.rowAL = new ArrayList();
        this.fileName = fileName;
        this.encoding = encoding;
        LoadCsvFile();
    }
    /// 
    /// 文件名,包括文件路径
    /// 
    public string FileName
    {
        set
        {
            this.fileName = value;
            LoadCsvFile();
        }
    }
    /// 
    /// 文件编码
    /// 
    public Encoding FileEncoding
    {
        set
        {
            this.encoding = value;
        }
    }
    /// 
    /// 获取行数
    /// 
    public int RowCount
    {
        get
        {
            return this.rowAL.Count;
        }
    }
    /// 
    /// 获取列数
    /// 
    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;
        }
    }
    /// 
    /// 获取某行某列的数据
    /// row:行,row = 1代表第一行
    /// col:列,col = 1代表第一列  
    /// 
    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();
        }
    }
    /// 
    /// 根据最小行,最大行,最小列,最大列,来生成一个DataTable类型的数据
    /// 行等于1代表第一行
    /// 列等于1代表第一列
    /// maxrow: -1代表最大行
    /// maxcol: -1代表最大列
    /// 
    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;
        }
    }
    /// 
    /// 检查行数是否是有效的
    /// 
    ///   
    private void CheckRowValid(int row)
    {
        if (row <= 0)
        {
            throw new Exception("行数不能小于0");
        }
        if (row > RowCount)
        {
            throw new Exception("没有当前行的数据");
        }
    }
    /// 
    /// 检查最大行数是否是有效的
    /// 
    ///   
    private void CheckMaxRowValid(int maxRow)
    {
        if (maxRow <= 0 && maxRow != -1)
        {
            throw new Exception("行数不能等于0或小于-1");
        }
        if (maxRow > RowCount)
        {
            throw new Exception("没有当前行的数据");
        }
    }
    /// 
    /// 检查列数是否是有效的
    /// 
    ///   
    private void CheckColValid(int col)
    {
        if (col <= 0)
        {
            throw new Exception("列数不能小于0");
        }
        if (col > ColCount)
        {
            throw new Exception("没有当前列的数据");
        }
    }
    /// 
    /// 检查检查最大列数是否是有效的
    /// 
    ///   
    private void CheckMaxColValid(int maxCol)
    {
        if (maxCol <= 0 && maxCol != -1)
        {
            throw new Exception("列数不能等于0或小于-1");
        }
        if (maxCol > ColCount)
        {
            throw new Exception("没有当前列的数据");
        }
    }
    /// 
    /// 载入CSV文件
    /// 
    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文件的格式有错误");
        }
    }
    /// 
    /// 获取两个连续引号变成单个引号的数据行
    /// 
    /// 文件数据行
    /// 
    private string GetDeleteQuotaDataLine(string fileDataLine)
    {
        return fileDataLine.Replace("\"\"", "\"");
    }
    /// 
    /// 判断字符串是否包含奇数个引号
    /// 
    /// 数据行
    /// 为奇数时,返回为真;否则返回为假
    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;
    }
    /// 
    /// 判断是否以奇数个引号开始
    /// 
    /// 
    /// 
    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;
    }
    /// 
    /// 判断是否以奇数个引号结尾
    /// 
    /// 
    /// 
    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;
    }
    /// 
    /// 加入新的数据行
    /// 
    /// 新的数据行
    private void AddNewDataLine(string newDataLine)
    {
        //System.Diagnostics.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);
    }
    /// 
    /// 去掉格子的首尾引号,把双引号变成单引号
    /// 
    /// 
    /// 
    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;
    }
}





C#:将DataTable内容写入到CSV文件 与 将CSV文件内容读取到DataTab

一、将DataTable内容写入到CSV文件


///
/// 将DataTable中的数据保存成CSV文件
///
private void btnSaveCSV_Click(object sender, EventArgs e)
{
    saveFileDialog1.Filter = "CSV文件|*.CSV";
    saveFileDialog1.InitialDirectory = "C:\";
    if (saveFileDialog1.ShowDialog() == DialogResult.Cancel)
    {
        return;
    }
    else
    {
        string fileName = saveFileDialog1.FileName;
        SaveCSV(ds.Tables[0], fileName);
    }
}
///
/// 将DataTable中数据写入到CSV文件中
///
/// 提供保存数据的DataTable
/// CSV的文件路径
public void SaveCSV(DataTable dt, string fileName)
{
    FileStream fs = new FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write);
    StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.Default);
    string data = "";
    //写出列名称
    for (int i = 0; i < dt.Columns.Count; i++)
    {
        data += dt.Columns[i].ColumnName.ToString();
        if (i < dt.Columns.Count - 1)
        {
            data += ",";
        }
    }
    sw.WriteLine(data);
    //写出各行数据
    for (int i = 0; i < dt.Rows.Count; i++)
    {
        data = "";
        for (int j = 0; j < dt.Columns.Count; j++)
        {
            data += dt.Rows[i][j].ToString();
            if (j < dt.Columns.Count - 1)
            {
                data += ",";
            }
        }
        sw.WriteLine(data);
    }
    sw.Close();
    fs.Close();
    MessageBox.Show("CSV文件保存成功!");
}


相关文章

精彩推荐