zoukankan      html  css  js  c++  java
  • C#获取csv文件内容对逗号和引号分隔的处理

    2016.10.31

       分隔线以下是多年以前的一篇随笔,很抱歉这么久才看到回复并指出文中的不足,我是希望能够解决问题,纠正网上搜索来的不好用的方案,没想到我自己也犯了同样的错误,特此更正,以期帮到更多的朋友。

    有关正则表达式我进行了修改,完整示例如下: 

      string s = string.Empty;
      string src = string.Empty;
      StreamReader fs = new StreamReader(new FileStream("d:\\demo.csv", FileMode.Open, FileAccess.Read), Encoding.GetEncoding("gb2312"));
      while (!string.IsNullOrEmpty(s = fs.ReadLine()))
      {
          if (!string.IsNullOrEmpty(s))
          {
              Console.WriteLine(s);
              MatchCollection col = Regex.Matches(src, "(?<=^|,)[^\"]*?(?=,|$)|(?<=^|,\")(?:(\"\")?[^\"]*?)*(?=\",?|$)", RegexOptions.ExplicitCapture);
              IEnumerator ie = col.GetEnumerator();
              while (ie.MoveNext())
              {
                  Console.WriteLine(ie.Current);
              }
          }
          Console.Read();
       }
       fs.Close();

    正则表达式的效果如下:

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------

        在小批量数据导入的时候,最常用的就是使用excel工具,将数据保存为xls或csv文件,然后上传到服务器,然后读取出来通过数据库访问类的相关方法更新到数据库中。对于如何读取xls文件的方法,网上太多了,使用excel对象或ole db/odbc连接都行。对于csv文件,其中有一种方式就是通过文件流,将它作为文本读取出来,这其中会遇到一点小意外。

        我们知道,使用excel工具保存成csv文件时有几个规则:

    1、每一行的单元格内容之间用逗号分隔。

    2、如果单元格的内容本身有逗号,这个单元格的内容将会用引号包含。

    3、如果单元格的内容本身有引号,

        引号不在首或尾,这个单元格内容不会被引号包含。

        引号在首或尾,这个单元格内容会被引号包含且原来首尾的引号会被转义。

        所以对于这样的内容,直接按逗号或引号使用split方法明显不合适,需要预先处理一下。办法很多,最容易想到的就是用正则过滤掉本身带逗号或引号的内容,剩下的再按逗号split就方便了,我将csv文件中的每一行获取出来存放到一个键值对的集合中,为了保证前后顺序一致,使用SortedList,这里用控制台程序示例一下:

     1 string s = string.Empty;
     2 string src = string.Empty;
     3 SortedList sl = new SortedList();
     4 StreamReader fs = new StreamReader(new FileStream("demo.csv", FileMode.Open, FileAccess.Read), Encoding.GetEncoding("gb2312"));
     5 while (!string.IsNullOrEmpty(s = fs.ReadLine()))
     6 {
     7     if (!string.IsNullOrEmpty(s))
     8     {
     9         Console.WriteLine(s);
    10         src = s.Replace("\"\"""'");
    11         MatchCollection col = Regex.Matches(src, ",\"([^\"]+)\",", RegexOptions.ExplicitCapture);
    12         IEnumerator ie = col.GetEnumerator();
    13         while (ie.MoveNext())
    14         {
    15             string patn = ie.Current.ToString();
    16             int key = src.Substring(0, src.IndexOf(patn)).Split(',').Length;
    17             if (!sl.ContainsKey(key))
    18             {
    19                 sl.Add(key, patn.Trim(new char[] { ',''"' }).Replace("'""\""));
    20                 src = src.Replace(patn, ",,");
    21             }
    22         }
    23 
    24         string[] arr = src.Split(',');
    25         for (int i = 0; i < arr.Length; i++)
    26         {
    27             if (!sl.ContainsKey(i))
    28                 sl.Add(i, arr[i]);
    29         }
    30 
    31         IDictionaryEnumerator ienum = sl.GetEnumerator();
    32         while (ienum.MoveNext())
    33         {
    34             Console.WriteLine(string.Format("{0}:{1}", ienum.Key, ienum.Value.ToString().Replace("'""\"")));
    35         }
    36         sl.Clear();
    37         src = string.Empty;
    38     }
    39     Console.Read();
    40 }
    41 fs.Close();
  • 相关阅读:
    HDU 1754线段树基本操作,建树,更新,查询
    用第三方下载工具下载官方XCode独立安装包的方法
    解决Windows平台通过cURL上传APP到蒲公英pgyer平台时无法使用中文升级描述的问题
    Cygwin 版本的 Curl 安装,提取,使用笔记
    Android Gradle 引用本地 AAR 的几种方式
    VM虚拟机快照还原效果实现方式
    插入中文错误ERROR 1406 (22001): Data too long for column 'name' at row 1
    mysql初始化默认为空的密码修改
    性能测试学习计划(转)
    context-param和init-param区别
  • 原文地址:https://www.cnblogs.com/BeanHsiang/p/1597804.html
Copyright © 2011-2022 走看看