std::wstringstream按块读取数据不完整问题咨询
关于std::wstringstream读取数据不完整的问题分析
嘿,我来帮你捋捋这段代码的问题出在哪:
先看你写的代码:
#include <iostream> #include <sstream> int main(int argc, char* argv[]) { std::wstringstream buf(L"dsadsadsad dsadsadsad sadsadsadsad sa dsadsadsads dasdsadsa"); wchar_t sendbuf[5]; wmemset(sendbuf, 0, 5); while (buf.read(sendbuf, 5)) { std::wcout << sendbuf; wmemset(sendbuf, 0, 5); } return 0; }
核心原因
问题就出在while (buf.read(sendbuf, 5))这个循环条件上。std::basic_istream::read()的返回值规则是:只有当它成功读取到你指定的全部字符数(这里是5个)时,才会返回一个“真值”。如果流里剩下的字符不足5个,read()就会失败,循环直接终止,那些没读完的剩余字符就被彻底忽略了。
打个比方,假设你的字符串总共有47个宽字符,47除以5是9个完整的块(45个字符),还剩2个字符。这时候循环会执行9次,然后第10次read()尝试读5个但只能读到2个,返回false,循环结束,那2个字符就没机会被输出了。
解决办法
要把所有字符都输出,咱们得在循环结束后,检查流里有没有剩下没读完的字符,然后把它们也打印出来。修改后的代码如下:
#include <iostream> #include <sstream> int main(int argc, char* argv[]) { std::wstringstream buf(L"dsadsadsad dsadsadsad sadsadsadsad sa dsadsadsads dasdsadsa"); wchar_t sendbuf[5]; // 先读取所有完整的5字符块 while (buf.read(sendbuf, 5)) { std::wcout << sendbuf; } // 处理剩余的不足5个的字符 std::streamsize remaining = buf.gcount(); if (remaining > 0) { sendbuf[remaining] = L'\0'; // 手动添加宽字符串终止符,避免乱码 std::wcout << sendbuf; } return 0; }
补充说明
buf.gcount()这个函数会返回上一次输入操作(也就是最后一次read())实际读取到的字符数量,哪怕没读满你指定的5个。- 最后一定要给剩余字符加
L'\0',因为sendbuf是字符数组,std::wcout输出的时候需要看到终止符才会停止,不然可能会输出内存里的垃圾数据。 - 之前的
wmemset其实可以去掉,因为每次read()会覆盖数组里的旧内容,最后我们也手动加了终止符,不过如果习惯保留也完全没问题,不影响功能。
内容的提问来源于stack exchange,提问作者Pasha
相关产品推荐
相关产品推荐

