C#实现读写CSV文件的方法详解

目录
  • CSV文件标准
    • 文件示例
    • RFC 4180
    • 简化标准
  • 读写CSV文件
    • 使用CsvHelper
    • 使用自定义方法
  • 总结

项目中经常遇到CSV文件的读写需求,其中的难点主要是CSV文件的解析。本文会介绍CsvHelperTextFieldParser正则表达式三种解析CSV文件的方法,顺带也会介绍一下CSV文件的写方法。

CSV文件标准

在介绍CSV文件的读写方法前,我们需要了解一下CSV文件的格式。

文件示例

一个简单的CSV文件:

Test1,Test2,Test3,Test4,Test5,Test6
str1,str2,str3,str4,str5,str6
str1,str2,str3,str4,str5,str6

一个不简单的CSV文件:

"Test1
"",""","Test2
"",""","Test3
"",""","Test4
"",""","Test5
"",""","Test6
"","""
" 中文,D23 ","3DFD4234""""""1232""1S2","ASD1"",""23,,,,213
23F32","
",,asd
" 中文,D23 ","3DFD4234""""""1232""1S2","ASD1"",""23,,,,213
23F32","
",,asd

你没看错,上面两个都是CSV文件,都只有3行CSV数据。第二个文件多看一眼都是精神污染,但项目中无法避免会出现这种文件。

RFC 4180

CSV文件没有官方的标准,但一般项目都会遵守 RFC 4180 标准。这是一个非官方的标准,内容如下:

Each record is located on a separate line, delimited by a line break (CRLF).

The last record in the file may or may not have an ending line break.

There maybe an optional header line appearing as the first line of the file with the same format as normal record lines. This header will contain names corresponding to the fields in the file and should contain the same number of fields as the records in the rest of the file (the presence or absence of the header line should be indicated via the optional "header" parameter of this MIME type).

Within the header and each record, there may be one or more fields, separated by commas. Each line should contain the same number of fields throughout the file. Spaces are considered part of a field and should not be ignored. The last field in the record must not be followed by a comma.

Each field may or may not be enclosed in double quotes (however some programs, such as Microsoft Excel, do not use double quotes at all). If fields are not enclosed with double quotes, then double quotes may not appear inside the fields.

Fields containing line breaks (CRLF), double quotes, and commas should be enclosed in double-quotes.

If double-quotes are used to enclose fields, then a double-quote appearing inside a field must be escaped by preceding it with another double quote.

翻译一下:

  • 每条记录位于单独的行上,由换行符 (CRLF) 分隔。
  • 文件中的最后一条记录可能有也可能没有结束换行符。
  • 可能有一个可选的标题行出现在文件的第一行,格式与普通记录行相同。此标题将包含与文件中的字段对应的名称,并且应包含与文件其余部分中的记录相同数量的字段(标题行的存在或不存在应通过此 MIME 类型的可选“标头”参数指示)。
  • 在标题和每条记录中,可能有一个或多个字段,以逗号分隔。在整个文件中,每行应包含相同数量的字段。空格被视为字段的一部分,不应忽略。记录中的最后一个字段后面不能有逗号。
  • 每个字段可以用双引号括起来,也可以不用双引号(但是某些程序,例如 Microsoft Excel,根本不使用双引号)。如果字段没有用双引号括起来,那么双引号可能不会出现在字段内。
  • 包含换行符 (CRLF)、双引号和逗号的字段应该用双引号括起来。
  • 如果使用双引号将字段括起来,则出现在字段中的双引号必须在其前面加上另一个双引号。

简化标准

上面的标准可能比较拗口,我们对它进行一些简化。要注意一下,简化不是简单的删减规则,而是将类似的类似进行合并便于理解。
后面的代码也会使用简化标准,简化标准如下:

  • 每条记录位于单独的行上,由换行符 (CRLF) 分隔。
  • 注:此处的行不是普通文本意义上的行,是指符合CSV文件格式的一条记录(后面简称为CSV行),在文本上可能占据多行。
  • 文件中的最后一条记录需有结束换行符,文件的第一行为标题行(标题行包含字段对应的名称,标题数与记录的字段数相同)。
  • 注:原标准中可有可无的选项统一规定为必须有,方便后期的解析,而且没有标题行让别人怎么看数据。
  • 在标题和每条记录中,可能有一个或多个字段,以逗号分隔。在整个文件中,每行应包含相同数量的字段空格被视为字段的一部分,不应忽略。记录中的最后一个字段后面不能有逗号
  • 注:此标准未做简化,虽然也有其它标准使用空格、制表符等做分割的,但不使用逗号分割的文件还叫逗号分隔值文件吗。
  • 每个字段都用双引号括起来,出现在字段中的双引号必须在其前面加上另一个双引号
  • 注:原标准有必须使用双引号和可选双引号的情况,那全部使用双引号肯定不会出错。*

读写CSV文件

在正式读写CSV文件前,我们需要先定义一个用于测试的Test类。代码如下:

class Test
{
    public string Test1{get;set;}
    public string Test2 { get; set; }
    public string Test3 { get; set; }
    public string Test4 { get; set; }
    public string Test5 { get; set; }
    public string Test6 { get; set; }

    //Parse方法会在自定义读写CSV文件时用到
    public static Test Parse (string[]fields )
    {
        try
        {
            Test ret = new Test();
            ret.Test1 = fields[0];
            ret.Test2 = fields[1];
            ret.Test3 = fields[2];
            ret.Test4 = fields[3];
            ret.Test5 = fields[4];
            ret.Test6 = fields[5];
            return ret;
        }
        catch (Exception)
        {
            //做一些异常处理,写日志之类的
            return null;
        }
    }
}

生成一些测试数据,代码如下:

static void Main(string[] args)
{
    //文件保存路径
    string path = "tset.csv";
    //清理之前的测试文件
    File.Delete("tset.csv");

    Test test = new Test();
    test.Test1 = " 中文,D23 ";
    test.Test2 = "3DFD4234\"\"\"1232\"1S2";
    test.Test3 = "ASD1\",\"23,,,,213\r23F32";
    test.Test4 = "\r";
    test.Test5 = string.Empty;
    test.Test6 = "asd";

    //测试数据
    var records = new List<Test> { test, test };

    //写CSV文件
    /*
    *直接把后面的写CSV文件代码复制到此处
    */

    //读CSV文件
     /*
    *直接把后面的读CSV文件代码复制到此处
    */

    Console.ReadLine();
}

使用CsvHelper

CsvHelper 是用于读取和写入 CSV 文件的库,支持自定义类对象的读写。

github上标星最高的CSV文件读写C#库,使用MS-PLApache 2.0开源协议。

使用NuGet下载CsvHelper,读写CSV文件的代码如下:

 //写CSV文件
using (var writer = new StreamWriter(path))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
    csv.WriteRecords(records);
}

using (var writer = new StreamWriter(path,true))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
    //追加
    foreach (var record in records)
    {
        csv.WriteRecord(record);
    }
}

//读CSV文件
using (var reader = new StreamReader(path))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
    records = csv.GetRecords<Test>().ToList();
    //逐行读取
    //records.Add(csv.GetRecord<Test>());
}

如果你只想要拿来就能用的库,那文章基本上到这里就结束了。

使用自定义方法

为了与CsvHelper区分,新建一个CsvFile类存放自定义读写CSV文件的代码,最后会提供类的完整源码。CsvFile类定义如下:

/// <summary>
/// CSV文件读写工具类
/// </summary>
public class CsvFile
{
    #region 写CSV文件
    //具体代码...
    #endregion

    #region 读CSV文件(使用TextFieldParser)
    //具体代码...
    #endregion

    #region 读CSV文件(使用正则表达式)
    //具体代码...
    #endregion

}

基于简化标准的写CSV文件

根据简化标准(具体标准内容见前文),写CSV文件代码如下:

#region 写CSV文件
//字段数组转为CSV记录行
private static string FieldsToLine(IEnumerable<string> fields)
{
    if (fields == null) return string.Empty;
    fields = fields.Select(field =>
    {
        if (field == null) field = string.Empty;
        //简化标准,所有字段都加双引号
        field = string.Format("\"{0}\"", field.Replace("\"", "\"\""));

        //不简化标准
        //field = field.Replace("\"", "\"\"");
        //if (field.IndexOfAny(new char[] { ',', '"', ' ', '\r' }) != -1)
        //{
        //    field = string.Format("\"{0}\"", field);
        //}
        return field;
    });
    string line = string.Format("{0}{1}", string.Join(",", fields), Environment.NewLine);
    return line;
}

//默认的字段转换方法
private static IEnumerable<string> GetObjFields<T>(T obj, bool isTitle) where T : class
{
    IEnumerable<string> fields;
    if (isTitle)
    {
        fields = obj.GetType().GetProperties().Select(pro => pro.Name);
    }
    else
    {
        fields = obj.GetType().GetProperties().Select(pro => pro.GetValue(obj)?.ToString());
    }
    return fields;
}

/// <summary>
/// 写CSV文件,默认第一行为标题
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list">数据列表</param>
/// <param name="path">文件路径</param>
/// <param name="append">追加记录</param>
/// <param name="func">字段转换方法</param>
/// <param name="defaultEncoding"></param>
public static void Write<T>(List<T> list, string path,bool append=true, Func<T, bool, IEnumerable<string>> func = null, Encoding defaultEncoding = null) where T : class
{
    if (list == null || list.Count == 0) return;
    if (defaultEncoding == null)
    {
        defaultEncoding = Encoding.UTF8;
    }
    if (func == null)
    {
        func = GetObjFields;
    }
    if (!File.Exists(path)|| !append)
    {
        var fields = func(list[0], true);
        string title = FieldsToLine(fields);
        File.WriteAllText(path, title, defaultEncoding);
    }
    using (StreamWriter sw = new StreamWriter(path, true, defaultEncoding))
    {
        list.ForEach(obj =>
        {
            var fields = func(obj, false);
            string line = FieldsToLine(fields);
            sw.Write(line);
        });
    }
}
#endregion

使用时,代码如下:

//写CSV文件
//使用自定义的字段转换方法,也是文章开头复杂CSV文件使用字段转换方法
CsvFile.Write(records, path, true, new Func<Test, bool, IEnumerable<string>>((obj, isTitle) =>
{
    IEnumerable<string> fields;
    if (isTitle)
    {
        fields = obj.GetType().GetProperties().Select(pro => pro.Name + Environment.NewLine + "\",\"");
    }
    else
    {
        fields = obj.GetType().GetProperties().Select(pro => pro.GetValue(obj)?.ToString());
    }
    return fields;
}));

//使用默认的字段转换方法
//CsvFile.Write(records, path);

你也可以使用默认的字段转换方法,代码如下:

CsvFile.Save(records, path);

使用TextFieldParser解析CSV文件

TextFieldParser是VB中解析CSV文件的类,C#虽然没有类似功能的类,不过可以调用VB的TextFieldParser来实现功能。

TextFieldParser解析CSV文件的代码如下:

#region 读CSV文件(使用TextFieldParser)
/// <summary>
/// 读CSV文件,默认第一行为标题
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="path">文件路径</param>
/// <param name="func">字段解析规则</param>
/// <param name="defaultEncoding">文件编码</param>
/// <returns></returns>
public static List<T> Read<T>(string path, Func<string[], T> func, Encoding defaultEncoding = null) where T : class
{
    if (defaultEncoding == null)
    {
        defaultEncoding = Encoding.UTF8;
    }
    List<T> list = new List<T>();
    using (TextFieldParser parser = new TextFieldParser(path, defaultEncoding))
    {
        parser.TextFieldType = FieldType.Delimited;
        //设定逗号分隔符
        parser.SetDelimiters(",");
        //设定不忽略字段前后的空格
        parser.TrimWhiteSpace = false;
        bool isLine = false;
        while (!parser.EndOfData)
        {
            string[] fields = parser.ReadFields();
            if (isLine)
            {
                var obj = func(fields);
                if (obj != null) list.Add(obj);
            }
            else
            {
                //忽略标题行业
                isLine = true;
            }
        }
    }
    return list;
}
#endregion

使用时,代码如下:

//读CSV文件
records = CsvFile.Read(path, Test.Parse);

使用正则表达式解析CSV文件

如果你有一个问题,想用正则表达式来解决,那么你就有两个问题了。

正则表达式有一定的学习门槛,而且学习后不经常使用就会忘记。正则表达式解决的大多数是一些不易变更需求的问题,这就导致一个稳定可用的正则表达式可以传好几代。

本节的正则表达式来自 《精通正则表达式(第3版)》 第6章 打造高效正则表达式——简单的消除循环的例子,有兴趣的可以去了解一下,表达式说明如下:

注:这本书最终版的解析CSV文件的正则表达式是Jave版的使用占有优先量词取代固化分组的版本,也是百度上经常见到的版本。不过占有优先量词在C#中有点问题,本人能力有限解决不了,所以使用了上图的版本。不过,这两版正则表达式性能上没有差异。

正则表达式解析CSV文件代码如下:

#region 读CSV文件(使用正则表达式)
/// <summary>
/// 读CSV文件,默认第一行为标题
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="path">文件路径</param>
/// <param name="func">字段解析规则</param>
/// <param name="defaultEncoding">文件编码</param>
/// <returns></returns>
public static List<T> Read_Regex<T>(string path, Func<string[], T> func, Encoding defaultEncoding = null) where T : class
{
    List<T> list = new List<T>();
    StringBuilder sbr = new StringBuilder(100);
    Regex lineReg = new Regex("\"");
    Regex fieldReg = new Regex("\\G(?:^|,)(?:\"((?>[^\"]*)(?>\"\"[^\"]*)*)\"|([^\",]*))");
    Regex quotesReg = new Regex("\"\"");

    bool isLine = false;
    string line = string.Empty;
    using (StreamReader sr = new StreamReader(path))
    {
        while (null != (line = ReadLine(sr)))
        {
            sbr.Append(line);
            string str = sbr.ToString();
            //一个完整的CSV记录行,它的双引号一定是偶数
            if (lineReg.Matches(sbr.ToString()).Count % 2 == 0)
            {
                if (isLine)
                {
                    var fields = ParseCsvLine(sbr.ToString(), fieldReg, quotesReg).ToArray();
                    var obj = func(fields.ToArray());
                    if (obj != null) list.Add(obj);
                }
                else
                {
                    //忽略标题行业
                    isLine = true;
                }
                sbr.Clear();
            }
            else
            {
                sbr.Append(Environment.NewLine);
            }
        }
    }
    if (sbr.Length > 0)
    {
        //有解析失败的字符串,报错或忽略
    }
    return list;
}

//重写ReadLine方法,只有\r\n才是正确的一行
private static string ReadLine(StreamReader sr)
{
    StringBuilder sbr = new StringBuilder();
    char c;
    int cInt;
    while (-1 != (cInt =sr.Read()))
    {
        c = (char)cInt;
        if (c == '\n' && sbr.Length > 0 && sbr[sbr.Length - 1] == '\r')
        {
            sbr.Remove(sbr.Length - 1, 1);
            return sbr.ToString();
        }
        else
        {
            sbr.Append(c);
        }
    }
    return sbr.Length>0?sbr.ToString():null;
}

private static List<string> ParseCsvLine(string line, Regex fieldReg, Regex quotesReg)
{
    var fieldMath = fieldReg.Match(line);
    List<string> fields = new List<string>();
    while (fieldMath.Success)
    {
        string field;
        if (fieldMath.Groups[1].Success)
        {
            field = quotesReg.Replace(fieldMath.Groups[1].Value, "\"");
        }
        else
        {
            field = fieldMath.Groups[2].Value;
        }
        fields.Add(field);
        fieldMath = fieldMath.NextMatch();
    }
    return fields;
}
#endregion

使用时代码如下:

//读CSV文件
records = CsvFile.Read_Regex(path, Test.Parse);

目前还未发现正则表达式解析有什么bug,不过还是不建议使用。

完整的CsvFile工具类

完整的CsvFile类代码如下:

using Microsoft.VisualBasic.FileIO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace ConsoleApp4
{
    /// <summary>
    /// CSV文件读写工具类
    /// </summary>
    public class CsvFile
    {
        #region 写CSV文件
        //字段数组转为CSV记录行
        private static string FieldsToLine(IEnumerable<string> fields)
        {
            if (fields == null) return string.Empty;
            fields = fields.Select(field =>
            {
                if (field == null) field = string.Empty;
                //所有字段都加双引号
                field = string.Format("\"{0}\"", field.Replace("\"", "\"\""));

                //不简化
                //field = field.Replace("\"", "\"\"");
                //if (field.IndexOfAny(new char[] { ',', '"', ' ', '\r' }) != -1)
                //{
                //    field = string.Format("\"{0}\"", field);
                //}
                return field;
            });
            string line = string.Format("{0}{1}", string.Join(",", fields), Environment.NewLine);
            return line;
        }

        //默认的字段转换方法
        private static IEnumerable<string> GetObjFields<T>(T obj, bool isTitle) where T : class
        {
            IEnumerable<string> fields;
            if (isTitle)
            {
                fields = obj.GetType().GetProperties().Select(pro => pro.Name);
            }
            else
            {
                fields = obj.GetType().GetProperties().Select(pro => pro.GetValue(obj)?.ToString());
            }
            return fields;
        }

        /// <summary>
        /// 写CSV文件,默认第一行为标题
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">数据列表</param>
        /// <param name="path">文件路径</param>
        /// <param name="append">追加记录</param>
        /// <param name="func">字段转换方法</param>
        /// <param name="defaultEncoding"></param>
        public static void Write<T>(List<T> list, string path,bool append=true, Func<T, bool, IEnumerable<string>> func = null, Encoding defaultEncoding = null) where T : class
        {
            if (list == null || list.Count == 0) return;
            if (defaultEncoding == null)
            {
                defaultEncoding = Encoding.UTF8;
            }
            if (func == null)
            {
                func = GetObjFields;
            }
            if (!File.Exists(path)|| !append)
            {
                var fields = func(list[0], true);
                string title = FieldsToLine(fields);
                File.WriteAllText(path, title, defaultEncoding);
            }
            using (StreamWriter sw = new StreamWriter(path, true, defaultEncoding))
            {
                list.ForEach(obj =>
                {
                    var fields = func(obj, false);
                    string line = FieldsToLine(fields);
                    sw.Write(line);
                });
            }
        }
        #endregion

        #region 读CSV文件(使用TextFieldParser)
        /// <summary>
        /// 读CSV文件,默认第一行为标题
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path">文件路径</param>
        /// <param name="func">字段解析规则</param>
        /// <param name="defaultEncoding">文件编码</param>
        /// <returns></returns>
        public static List<T> Read<T>(string path, Func<string[], T> func, Encoding defaultEncoding = null) where T : class
        {
            if (defaultEncoding == null)
            {
                defaultEncoding = Encoding.UTF8;
            }
            List<T> list = new List<T>();
            using (TextFieldParser parser = new TextFieldParser(path, defaultEncoding))
            {
                parser.TextFieldType = FieldType.Delimited;
                //设定逗号分隔符
                parser.SetDelimiters(",");
                //设定不忽略字段前后的空格
                parser.TrimWhiteSpace = false;
                bool isLine = false;
                while (!parser.EndOfData)
                {
                    string[] fields = parser.ReadFields();
                    if (isLine)
                    {
                        var obj = func(fields);
                        if (obj != null) list.Add(obj);
                    }
                    else
                    {
                        //忽略标题行业
                        isLine = true;
                    }
                }
            }
            return list;
        }
        #endregion

        #region 读CSV文件(使用正则表达式)
        /// <summary>
        /// 读CSV文件,默认第一行为标题
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path">文件路径</param>
        /// <param name="func">字段解析规则</param>
        /// <param name="defaultEncoding">文件编码</param>
        /// <returns></returns>
        public static List<T> Read_Regex<T>(string path, Func<string[], T> func, Encoding defaultEncoding = null) where T : class
        {
            List<T> list = new List<T>();
            StringBuilder sbr = new StringBuilder(100);
            Regex lineReg = new Regex("\"");
            Regex fieldReg = new Regex("\\G(?:^|,)(?:\"((?>[^\"]*)(?>\"\"[^\"]*)*)\"|([^\",]*))");
            Regex quotesReg = new Regex("\"\"");

            bool isLine = false;
            string line = string.Empty;
            using (StreamReader sr = new StreamReader(path))
            {
                while (null != (line = ReadLine(sr)))
                {
                    sbr.Append(line);
                    string str = sbr.ToString();
                    //一个完整的CSV记录行,它的双引号一定是偶数
                    if (lineReg.Matches(sbr.ToString()).Count % 2 == 0)
                    {
                        if (isLine)
                        {
                            var fields = ParseCsvLine(sbr.ToString(), fieldReg, quotesReg).ToArray();
                            var obj = func(fields.ToArray());
                            if (obj != null) list.Add(obj);
                        }
                        else
                        {
                            //忽略标题行业
                            isLine = true;
                        }
                        sbr.Clear();
                    }
                    else
                    {
                        sbr.Append(Environment.NewLine);
                    }
                }
            }
            if (sbr.Length > 0)
            {
                //有解析失败的字符串,报错或忽略
            }
            return list;
        }

        //重写ReadLine方法,只有\r\n才是正确的一行
        private static string ReadLine(StreamReader sr)
        {
            StringBuilder sbr = new StringBuilder();
            char c;
            int cInt;
            while (-1 != (cInt =sr.Read()))
            {
                c = (char)cInt;
                if (c == '\n' && sbr.Length > 0 && sbr[sbr.Length - 1] == '\r')
                {
                    sbr.Remove(sbr.Length - 1, 1);
                    return sbr.ToString();
                }
                else
                {
                    sbr.Append(c);
                }
            }
            return sbr.Length>0?sbr.ToString():null;
        }

        private static List<string> ParseCsvLine(string line, Regex fieldReg, Regex quotesReg)
        {
            var fieldMath = fieldReg.Match(line);
            List<string> fields = new List<string>();
            while (fieldMath.Success)
            {
                string field;
                if (fieldMath.Groups[1].Success)
                {
                    field = quotesReg.Replace(fieldMath.Groups[1].Value, "\"");
                }
                else
                {
                    field = fieldMath.Groups[2].Value;
                }
                fields.Add(field);
                fieldMath = fieldMath.NextMatch();
            }
            return fields;
        }
        #endregion

    }
}

使用方法如下:

//写CSV文件
CsvFile.Write(records, path, true, new Func<Test, bool, IEnumerable<string>>((obj, isTitle) =>
{
    IEnumerable<string> fields;
    if (isTitle)
    {
        fields = obj.GetType().GetProperties().Select(pro => pro.Name + Environment.NewLine + "\",\"");
    }
    else
    {
        fields = obj.GetType().GetProperties().Select(pro => pro.GetValue(obj)?.ToString());
    }
    return fields;
}));

//读CSV文件
records = CsvFile.Read(path, Test.Parse);

//读CSV文件
records = CsvFile.Read_Regex(path, Test.Parse);

总结

  • 介绍了CSV文件的 RFC 4180 标准及其简化理解版本
  • 介绍了CsvHelper、TextFieldParser、正则表达式三种解析CSV文件的方法
  • 项目中推荐使用CsvHelper,如果不想引入太多开源组件可以使用TextFieldParser,不建议使用正则表达式

以上就是C#实现读写CSV文件的方法详解的详细内容,更多关于C#读写CSV文件的资料请关注我们其它相关文章!

(0)

相关推荐

  • C#导出数据到CSV文件的通用类实例

    本文实例讲述了C#导出数据到csv文件的通用类.分享给大家供大家参考.具体如下: 通过这个类可以很简单的定义数据格式,并导出到csv文件 //这里写了一个通用的类 using System; using System.Data; using System.Configuration; using System.Collections.Generic; using System.Web; using System.Web.Security; using System.Web.UI; using S

  • C#实现导入CSV文件到Excel工作簿的方法

    本文实例讲述了C#实现导入CSV文件到Excel工作簿的方法.分享给大家供大家参考.具体如下: 你必须在项目中添加对 Microsoft.Office.Core 的引用:from the .NET tab of the Visual Studio Add Reference dialog box, and the Microsoft Excel 12.0 Object Library (you can use 14.0 if you want, too, but nothing lower).

  • C#读取csv格式文件的方法

    本文实例讲述了C#读取csv格式文件的方法.分享给大家供大家参考.具体实现方法如下: 一.CSV文件规则   1 开头是不留空,以行为单位. 2 可含或不含列名,含列名则居文件第一行. 3 一行数据不跨行,无空行. 4 以半角逗号(即,)作分隔符,列为空也要表达其存在. 5 列内容如存在半角逗号(即,)则用半角引号(即',')将该字段值包含起来. 6 列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来.

  • 一个读写csv文件的C#类

    本文实例为大家分享了一个读写csv文件的C#类,供大家参考,具体内容如下 using System; using System.Collections.Generic; using System.IO; using System.Text; namespace CSVDemo { /// <summary> /// CSVUtil is a helper class handling csv files. /// </summary> public class CSVUtil {

  • c# 对CSV文件操作(写入、读取、修改)

    一.DataTable数据写入CSV文件 public static void SaveCSV(DataTable dt, string fullPath)//table数据写入csv { System.IO.FileInfo fi = new System.IO.FileInfo(fullPath); if (!fi.Directory.Exists) { fi.Directory.Create(); } System.IO.FileStream fs = new System.IO.File

  • C#导入和导出CSV文件

    一.手工导出导出 1.winform void DataGridViewToExcel(DataGridView dataGridView1) { SaveFileDialog saveFileDialog = new SaveFileDialog(); saveFileDialog.Filter = "Execl files (*.xls)|*.xls"; saveFileDialog.FilterIndex = 0; saveFileDialog.RestoreDirectory

  • C#中将DataTable转换成CSV文件的方法

    DataTable用于在.net项目中,用于缓存数据,DataTable表示内存中数据的一个表.CSV文件最早用在简单的数据库里,由于其格式简单,并具备很强的开放性,所以起初被扫图家用作自己图集的标记.CSV文件是个纯文本文件,每一行表示一张图片的许多属性. 在.net项目中运用C#将DataTable转化为CSV文件,现在提供一个较为通用的方法,具体代码如下: /// <summary> /// 将DataTable转换成CSV文件 /// </summary> /// <

  • C#实现读写CSV文件的方法详解

    目录 CSV文件标准 文件示例 RFC 4180 简化标准 读写CSV文件 使用CsvHelper 使用自定义方法 总结 项目中经常遇到CSV文件的读写需求,其中的难点主要是CSV文件的解析.本文会介绍CsvHelper.TextFieldParser.正则表达式三种解析CSV文件的方法,顺带也会介绍一下CSV文件的写方法. CSV文件标准 在介绍CSV文件的读写方法前,我们需要了解一下CSV文件的格式. 文件示例 一个简单的CSV文件: Test1,Test2,Test3,Test4,Test

  • Python Pandas读写txt和csv文件的方法详解

    目录 一.文本文件 1. read_csv() 2. to_csv() 一.文本文件 文本文件,主要包括csv和txt两种等,相应接口为read_csv()和to_csv(),分别用于读写数据 1. read_csv() 格式代码: pandas.read_csv(filepath_or_buffer, sep=', ', delimiter=None, header='infer', names=None, index_col=None, usecols=None, squeeze=False

  • Java实现将类数据逐行写入CSV文件的方法详解

    目录 1. 需求和思路 2. 现有方法 3. 代码 4. 参考 1. 需求和思路 最近要用java制作一个数据集,每一行是一个样本,格式是csv.用了一下java类的相关概念,把csv文件里的每一行,即每一个样本视为一个类. 2. 现有方法 目前已有的csv包如opencsv,可以支持字符串,也可以支持javabean(即java类).相关教程如下 Java OpenCSV|极客教程 由于墙的原因,我maven老是下载不到opencsv的jar包,没办法我只能手写个平民版的 3. 代码 自定义的

  • Qt读写ini文件的方法详解(含源码+注释)

    目录 一.示例Ini文件内容 二.Ini文件的写入 三.Ini文件的读取 3.1 第一种读取方式 3.2 第二种读取方式 3.3 读取结果示例 补充:获取所有节点和key以及节点的遍历 相关文章 总结 一.示例Ini文件内容 下方为本文所使用的ini文件的内容 [group1] key1=val1 key2=val2 sameKay=sameVal [group2] jian1=zhi1 jian2=zhi2 sameKay=sameZhi 二.Ini文件的写入 ini文件不需要像xml和jso

  • 使用C/C++读写.mat文件的方法详解

    目录 一.创建工程并添加测试代码 二.修改CmakeLists文件 三.添加环境变量 四.令人头秃的错误 五.运行结果 总结 最近需要使用C++来处理matlab生成的数据, 参考了网上一些博客,不过他们都是使用的VS,我比较喜欢使用Clion, 在配置的过程中也遇到了一些坑,记录一下. 一.创建工程并添加测试代码 创建工程就不说了,注意一下我使用的编译工具链是MinGW.测试代码参考的matlab官方的程序:读取用 C/C++ 编写的 MAT 文件 - MATLAB & Simulink -

  • python读写csv文件的方法

    1.爬取豆瓣top250书籍 import requests import json import csv from bs4 import BeautifulSoup books = [] def book_name(url): res = requests.get(url) html = res.text soup = BeautifulSoup(html, 'html.parser') items = soup.find(class_="grid-16-8 clearfix").f

  • C++ OpenCV读写XML或YAML文件的方法详解

    目录 前言 1.如何使用 1.1第一步:XML.YAML文件的打开 1.2 第二步:进行文件读写操作 1.3 第三步:vector(array)和map的输入和输出 1.4 第四步:文件关闭 2.代码展示 2.1 写文件 2.2 读文件 2.3 完整的示例代码 前言 本节我们将认识XML和YAML这两种文件类型. 所谓XML,即eXtensible Markup Language,翻译成中文为“可扩展标识语言”.首先,XML是一种元标记语言.所谓元标记,就是开发者可以根据自身需要定义自己的标记,

  • Python高效处理大文件的方法详解

    目录 开始 处理文本 串行处理 多进程处理 并行处理 并行批量处理 将文件分割成批 运行并行批处理 tqdm 并发 结论 为了进行并行处理,我们将任务划分为子单元.它增加了程序处理的作业数量,减少了整体处理时间. 例如,如果你正在处理一个大的CSV文件,你想修改一个单列.我们将把数据以数组的形式输入函数,它将根据可用的进程数量,一次并行处理多个值.这些进程是基于你的处理器内核的数量. 在这篇文章中,我们将学习如何使用multiprocessing.joblib和tqdm Python包减少大文件

  • 对pandas写入读取h5文件的方法详解

    1.引言 通过参考相关博客对hdf5格式简要介绍. hdf5在存储的是支持压缩,使用的方式是blosc,这个是速度最快的也是pandas默认支持的. 使用压缩可以提磁盘利用率,节省空间. 开启压缩也没有什么劣势,只会慢一点点. 压缩在小数据量的时候优势不明显,数据量大了才有优势. 同时发现hdf读取文件的时候只能是一次写,写的时候可以append,可以put,但是写完成了之后关闭文件,就不能再写了, 会覆盖. 另外,为什么单独说pandas,主要因为本人目前对于h5py这个包的理解不是很深入,不

  • Python读写JSON文件的操作详解

    目录 JSON JSON 起源 JSON 样例 Python 原生支持 JSON 序列化 JSON 简单的序列化示例 JSON 反序列化 简单的反序列化示例 应用案例 编码和解码 JSON JSON 起源 JSON 全称 JavaScript Object Notation .是处理对象文字语法的 JavaScript 编程语言的一个子集.JSON 早已成为与语言无关的语言,并作为自己的标准存在. JSON 样例 { "data":[ { "id": "1

随机推荐