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 文件,并用分号“;”分隔单词