c++ 从 .csv 文件中读取

Posted

技术标签:

【中文标题】c++ 从 .csv 文件中读取【英文标题】:c++ Read from .csv file 【发布时间】:2013-05-03 00:53:19 【问题描述】:

我有这段代码应该在控制台中计算出 .csv 文件中的信息;

while(file.good())


    getline(file, ID, ',');
    cout << "ID: " << ID << " " ; 

    getline(file, nome, ',') ;
    cout << "User: " << nome << " " ;

    getline(file, idade, ',') ;
    cout << "Idade: " << idade << " "  ; 

    getline(file, genero, ' ') ; 
    cout << "Sexo: " <<  genero<< " "  ;


还有一个包含这个的 csv 文件(当我用记事本打开时):

0,Filipe,19,M

1,Maria,20,F

2,Walter,60,M

每当我运行程序时,控制台都会显示:

我的问题是为什么程序不是在每一行而不是只在第一行重复这些 cout 消息

顺便说一句,nome 是名字,idade 是年龄,genero/sexo 是性别,发帖前忘记翻译了

【问题讨论】:

我一直在寻找一种简单的方法来做到这一点,如果可能的话。关于我目前的知识,您发布的链接对我来说就像中文 @FreemanZhang:那是 C#,这是 C++。 @FilipeGama:您有两个问题,(A)答案中提到的分隔符,以及(B),您正在检查输入是否在错误的地方有效。如果只修复 A,这将导致最后一行出现重复。 @Mooing Duck 是的,它会,但只是有时无法弄清楚为什么,你能解释一下我应该在哪里检查输入是否有效? @FilipeGama:如果你做输入操作,测试是否成功。流会传播失败,因此您只需要测试最后一个是否成功,这太棒了。 【参考方案1】:

您可以关注this answer,了解在 C++ 中处理 CSV 的许多不同方法。

在您的情况下,对getline 的最后一次调用实际上是将第一行的最后一个字段,然后将所有剩余的行放入变量genero。这是因为直到文件末尾都没有找到空格分隔符。尝试将空格字符改为换行符:

    getline(file, genero, file.widen('\n'));

或更简洁地说:

    getline(file, genero);

此外,您对file.good() 的检查还为时过早。文件中的最后一个换行符仍在输入流中,直到它被下一个getline() 调用ID 丢弃。正是在这一点上检测到文件结尾,所以检查应该基于此。您可以通过将 while 测试更改为基于对 ID 本身的 getline() 调用来解决此问题(假设每行格式正确)。

while (getline(file, ID, ',')) 
    cout << "ID: " << ID << " " ; 

    getline(file, nome, ',') ;
    cout << "User: " << nome << " " ;

    getline(file, idade, ',') ;
    cout << "Idade: " << idade << " "  ; 

    getline(file, genero);
    cout << "Sexo: " <<  genero<< " "  ;

为了更好地检查错误,您应该检查每次调用 getline() 的结果。

【讨论】:

@FilipeGama:你试过我建议的修复方法了吗? 是的,第二个有效 :) 谢谢,正如我在其他答案中所说,我会投票但不能因为没有足够的积分 @user315052:有两个问题:(A)答案中提到的分隔符,以及(B),您正在检查输入是否在错误的地方有效。如果只修复 A,这将导致最后一行出现重复。 @MooingDuck:很好,修正了我的答案。 @user315052 谢谢,我刚刚接受了您最完整的回答,也感谢 MooingDuck。 Gratz,仍然无法投票【参考方案2】:

csv 文件就像任何其他文件一样是一个字符流。 getline 从文件中读取到分隔符,但是在您的情况下,最后一项的分隔符不是您假设的 ' '

getline(file, genero, ' ') ; 

换行符\n

所以把那行改成

getline(file, genero); // \n is default delimiter

【讨论】:

正是我想写的,所以+1。此代码不查找换行符,这导致其余部分未正确解析。 谢谢你终于解决了这个问题 :) 我会投票给你,但没有足够的分数,所以这是我的评论,gratz @FilipeGama “点赞”并不是说“谢谢”的唯一方式。接受他们的回答是欣赏他们努力的另一种完全有效的方式。 np Filipe,很乐意提供帮助 @Refugnic Eternium @claptrap 不知道,已经“接受”【参考方案3】:

您的 csv 格式错误。输出不是三个循环,而是一个输出。 为确保这是一个循环,请添加一个计数器并在每个循环中递增它。它应该只数到一。

这就是您的代码所看到的

0,Filipe,19,M\n1,Maria,20,F\n2,Walter,60,M

试试这个

0,Filipe,19,M
1,Maria,20,F
2,Walter,60,M


while(file.good())


    getline(file, ID, ',');
    cout << "ID: " << ID << " " ; 

    getline(file, nome, ',') ;
    cout << "User: " << nome << " " ;

    getline(file, idade, ',') ;
    cout << "Idade: " << idade << " "  ; 

    getline(file, genero) ; \\ diff
    cout << "Sexo: " <<  genero;\\diff



【讨论】:

如果不是 3 个循环,它如何显示第 2 行和第 3 行(即使没有 couts?对不起,我很难理解这些 .csv 概念,提前感谢编辑:如果你可以编辑我的代码并在这里发布,我将非常感谢:) 它有点工作,但现在我明白了:dl.dropboxusercontent.com/u/4613740/console2.png 它出于某种原因重复了最后一行...... 再一次,这只适用于第一行,其他的它只会搞砸......这样:dl.dropboxusercontent.com/u/4613740/console3.png 没有注意到逗号,仍然:dl.dropboxusercontent.com/u/4613740/console4.png 重复最后一行并在 ID 之前插入新行 :( 这让我发疯... 我已经更正了代码和 csv,(我之前没有编译器)。重复的行是由于 .csv 末尾的空白行【参考方案4】:

那是因为您的 csv 文件格式无效, 也许您的文本文件中的换行符不是 \n 或 \r

并且, 使用 c/c++ 解析文本不是一个好主意。 试试 awk:

 $awk -F"," 'print "ID="$1"\tName="$2"\tAge="$3"\tGender="$4' 1.csv
 ID=0   Name=Filipe Age=19  Gender=M
 ID=1   Name=Maria  Age=20  Gender=F
 ID=2   Name=Walter Age=60  Gender=M

【讨论】:

感谢您的回答,虽然我不知道 awk 是如何工作的,但您知道任何有用的链接吗? 谢谢先生,我去看看 看来您使用的是 Windows。这是GAWK for Windows 再次感谢所有帮助,但无论如何已经开始工作了 :)

以上是关于c++ 从 .csv 文件中读取的主要内容,如果未能解决你的问题,请参考以下文章

C++:使用 fgetc 读取 csv 文件,并用分号“;”分隔单词

C++ 中的 CSV 解析器不读取第一个元素

Linux 与 Windows,C++ 运行时性能差异超过读取 CSV 文件

在 C++ 中,如何使用多个线程读取一个文件?

Qt中如何读取csv文件到二维数组

DEV C++读取TAB