【问题标题】:Why isnt the >> working properly C++?为什么 >> 不能正常工作 C++?
【发布时间】:2011-02-10 00:56:29
【问题描述】:
std::wifstream theFileHandle;
std::wstring theData;
theFileHandle.open( theFile.Name() );
theFileHandle >> theData;
theFileHandle.close();

谁能告诉我为什么我的字符串 (theData) 只从文件 (theFile) 中获取第一个单词???我希望字符串包含文件中的所有文本,包括空格和换行符,有人对此有建议吗?谢谢。

PS。我需要完美地保存数据。谢谢。

【问题讨论】:

  • 我可以保证>> 操作符实际上工作正常。
  • 您的 PS“需要完美保存数据”,C++ 范围的流可能不会像您认为的那样。它将文件解释为窄字符(例如,在 Windows 中,为 ANSI)并为您提供相应的宽字符(例如,Unicode)。它可能在 *nix 中使用 UTF-8 编码文件,我不知道,但在 Windows 中,如果文件是 Unicode,你会得到垃圾。是的,这很愚蠢。是的,几乎不可能为这种设计想出任何合理的理由。不,这不是微软的错,而是 C++ iostreams 的设计。一种解决方法是读取二进制数据,然后自己翻译。干杯,
  • @Alf P. Steinbach:只需提供一个 codecvt facet 来进行您想要的转换,iostreams 设计就可以了。 MSVC 自带一个用于 UTF-16LE iirc。

标签: c++


【解决方案1】:

你只得到第一个单词的原因是,这正是 >> 运算符在应用于字符串时的工作方式 - 它只是从你正在读取的任何流中获取第一个空格分隔的标记,在跳过之后任何前导空格。

如果要读取文件的全部内容,可以像这样使用getline函数:

std::wifstream theFileHandle;
theFileHandle.open( theFile.Name() );

std::wstringstream data;
for (std::wstring line; getline(theFileHandle, line); )
    data << line << L"\n";

std::wstring theData = data.str();

这会循环,同时可以通过getline 读取更多数据,从而从文件中提取所有数据。由于getline 会跳过换行符,因此这种方法还会重新添加换行符。

编辑:正如@PigBen 所指出的,使用rdbuf() 有一种更简洁的方法来做到这一点:

std::wifstream theFileHandle;
theFileHandle.open( theFile.Name() );

std::wstringstream data;
data << theFileHandle.rdbuf();

std::wstring theData = data.str();

这使用了流插入运算符被重载以接收流缓冲区的事实。这种情况下的行为是读取流缓冲区的全部内容,直到用尽所有数据,这正是您想要的行为。

【讨论】:

  • 你可以使用:data &lt;&lt; theFileHandle.rdbuf(); 而不是 getline 循环。
  • @PigBen- 你是完全正确的。我会相应地修复这个解决方案。
  • 这很好,但由于某种原因,如果文件中有额外的新行,那么它不会拉出它们,所有文本都被挤在一起。任何线索为什么?
【解决方案2】:

字符串的operator&gt;&gt; 被定义为与scanf%s 转换几乎相同,后者只会在遇到空白之前读取。

有多种方法可以将整个文件读入字符串。最简单的大概是:

std::wstringstream buffer;
buffer << theFileHandle.rdbuf();
theData = buffer.str();

如果您正在处理一个大文件,那么至少有一种方法显然更快。请参阅我之前发布的答案中的 Test Four(但该代码是 Martin York 的,不是我的)。

【讨论】:

  • 请注意,您不能使用operator &lt;&lt; 直接读入字符串,您只能使用流来读取。您可能想要创建一个wstringstream,使用operator &lt;&lt; 读取它,然后使用wstringstream::str() 提取一个字符串。
  • @templatetypedef:是的——我在编辑上点击“提交”以解决该问题后立即看到了您的评论。不过还是谢谢...
【解决方案3】:

&gt;&gt; 应该是这样工作的。它从输入流中提取格式化数据。你想要.read() 提取未格式化的数据。

在此处查看更多信息:http://www.cplusplus.com/reference/iostream/istream/read/

例如:

std::wifstream theFileHandle;
wchar_t theData[SOME_LARGE_VALUE];
theFileHandle.open( theFile.Name() );
theFileHandle.read(theData, sizeof(theData));
theFileHandle.close();

【讨论】:

    【解决方案4】:

    请参阅优秀的previous answer,了解读取整个文件的简洁方法,并有效地进行操作。

    【讨论】:

    • +1 这样您就可以在未来以正确的方式标记重复对象,使用“接近 - 完全重复”的原因。
    猜你喜欢
    • 2016-07-16
    • 2019-01-04
    • 2020-09-03
    • 2016-10-10
    • 2016-10-24
    • 2017-02-27
    • 2017-07-08
    • 2014-11-23
    • 2021-03-07
    相关资源
    最近更新 更多