使用C/C++读取csv文件的每一行,以逗号分隔,如果某单元格的数据本身含有逗号,这里如何避免分隔出错?


在使用MFC读取csv文件的每一行并按逗号分隔时遇到这样的问题:

csv文件是用逗号作为列分隔符的,我读到csv文件的一行后,也是按照逗号来进行分割的,以便能够把这一行字符串按照原本csv文件中列的形式分割出来。但是当某个单元格的数据本身就带有逗号时(比如有一个单元格是“中国,朝鲜”),而且该逗号也是英文半角的,这个时候我的分隔便出错了,因为这个逗号的存在,原本csv中占10列的一行现在被分割成了11个,该如何解决?


2015/01/21 10:00更新

问题已经解决,今天有空会贴上解决方法和代码,谢谢各位的热心帮助。
只能采纳一个回答,就选kepler84的吧,也非常感谢Chobits提供的方法!

c csv C++

litp317 10 years, 8 months ago

CSV格式规范

根据csv的格式规范来看,包含逗号的一列数据应该是被双引号包起来的,这样就好办了,只要把被双引号包含的字符串提取出来然后把里面的逗号替换成别的符号,然后再拼接上原字符串中被双引号包起的字符串左边和右边的部分就好了。这里也只保证适用于格式规范的csv文件,不规范的文件不保证成功。

void _analyse_line(CStringW line) {
    // 保存原字符串副本
    CStringW copy_line = line;
    // 获取首个双引号在字符串中的索引
    int fquote_index = line.Find('\"');
    // 如果不存在双引号,可以直接按照逗号分割该字符串
    // 存在双引号的话检查被双引号包起的字符串中是否存在逗号
    if (fquote_index != -1) {
        int lquote_index = 0, _index;
        // 获取最后一个双引号的索引
        while ((_index = line.Find('\"')) != -1) {
            line = CStringW(line.Right(line.GetLength() - _index - 1));
            lquote_index += _index + 1;
        }
        // 双引号包起的字符串的长度
        int len = lquote_index - fquote_index;
        // 首个双引号左边的字符串
        CStringW left = copy_line.Left(fquote_index);
        line = CStringW(copy_line.Right(copy_line.GetLength() - fquote_index));
        // 最后一个双引号右边的字符串
        CStringW right = CStringW(line.Right(line.GetLength() - len));
        // 被双引号包起的字符串
        line = CStringW(line.Left(len));
        // 替换被双引号包起的字符串中的逗号
        line.Replace('\,', '\t');
        // 拼接新的字符串
        line = left + line + right;
    }

    vector arr = split(line, ',');
    // 把用'\t'替换过的逗号还原回来
    for (int i = 0; i

split方法不贴了,实现方法很多。

小小小猫仔 answered 10 years, 8 months ago

mkp0714 answered 10 years, 8 months ago

首先这种情况下每一列(或者只是带有逗号的那一列)必须是要有引号来表示“虽然有逗号但只是一列”这个语意的。否则的话这个CSV格式错误。

在有引号的情况下,这时你就不能用简单的split去处理字符串了。简单的方法是扫描字符串,并且标记当前字符是不是在引号里,如果在引号里,忽略逗号,否则碰到逗号就分割。

当然,更简单的方法是用已有的csv library。github上一大把。

按丑但按善良 answered 10 years, 8 months ago

Your Answer