C ++从文件流中读取无符号字符
Posted
技术标签:
【中文标题】C ++从文件流中读取无符号字符【英文标题】:C++ reading unsigned char from file stream 【发布时间】:2010-10-10 21:43:26 【问题描述】:我想从二进制文件中读取无符号字节。 于是我写了如下代码。
#include <iostream>
#include <fstream>
#include <vector>
#include <istream>
std::string filename("file");
size_t bytesAvailable = 128;
size_t toRead = 128;
std::basic_ifstream<unsigned char> inf(filename.c_str(), std::ios_base::in | std::ios_base::binary) ;
if (inF.good())
std::vector<unsigned char> mDataBuffer;
mDataBuffer.resize(bytesAvailable) ;
inF.read(&mDataBuffer[0], toRead) ;
size_t counted = inF.gcount() ;
这会导致读取始终为 0 字节,如变量 counted 所示。
网络上似乎有参考资料说我需要设置语言环境才能完成这项工作。我不清楚如何做到这一点。
相同的代码使用数据类型“char”而不是“unsigned char”
上面使用 unsigned char 的代码似乎可以在 Windows 上运行,但在 colinux Fedora 2.6.22.18 中运行失败。
我需要做什么才能让它在 linux 上工作?
【问题讨论】:
不是问题的答案,而是相关的。请记住,C++ 中字符串类的定义是typedef basic_string<char> string;
,因此您始终可以像 typedef basic_string<unsigned char> bytestring;
一样创建无符号字符字符串类。
是的,但我想读取 BINARY 文件
.read() 和 .write() 可用于二进制/文本,流运算符 > 仅用于文本文件。计算机上的所有数据最终都是二进制的,这是您选择解释它的方式。
如果你想“二进制”使用 uint8_t... 忽略它是 unsigned char 的 typedef 别名。
这个问题已经在这里解决了:***.com/q/19205531/331024 它有一个完整的实现 char_traitsC++ 确实只需要实现为两个版本的字符特征提供明确的特化:
std::char_traits<char>
std::char_traits<wchar_t>
流和字符串使用这些特征来计算各种事物,例如 EOF 值、字符范围的比较、将字符扩展为 int 等等。
如果你像这样实例化一个流
std::basic_ifstream<unsigned char>
您必须确保流可以使用相应的字符特征特化,并且该特化确实有用。此外,流使用构面来进行数字的实际格式化和读取。同样,您必须手动提供这些专业化。该标准甚至不要求实现具有主模板的完整定义。所以你也可能会得到一个编译错误:
错误:无法实例化特化 std::char_traits。
我会改用ifstream
(这是basic_ifstream<char>
),然后读入vector<char>
。在解释向量中的数据时,您仍然可以稍后将它们转换为unsigned char
。
【讨论】:
我没有收到编译器错误,文档中没有任何提示,什么也没有,只是无声的失败和浪费了一天。谢谢 Bjarne Stroustrup 和 Dennis Ritchie。【参考方案2】:不要使用 basic_ifstream,因为它需要专业化。
使用静态缓冲区:
linux ~ $ cat test_read.cpp
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main( void )
string filename("file");
size_t bytesAvailable = 128;
ifstream inf( filename.c_str() );
if( inf )
unsigned char mDataBuffer[ bytesAvailable ];
inf.read( (char*)( &mDataBuffer[0] ), bytesAvailable ) ;
size_t counted = inf.gcount();
cout << counted << endl;
return 0;
linux ~ $ g++ test_read.cpp
linux ~ $ echo "123456" > file
linux ~ $ ./a.out
7
使用向量:
linux ~ $ cat test_read.cpp
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main( void )
string filename("file");
size_t bytesAvailable = 128;
size_t toRead = 128;
ifstream inf( filename.c_str() );
if( inf )
vector<unsigned char> mDataBuffer;
mDataBuffer.resize( bytesAvailable ) ;
inf.read( (char*)( &mDataBuffer[0]), toRead ) ;
size_t counted = inf.gcount();
cout << counted << " size=" << mDataBuffer.size() << endl;
mDataBuffer.resize( counted ) ;
cout << counted << " size=" << mDataBuffer.size() << endl;
return 0;
linux ~ $ g++ test_read.cpp -Wall -o test_read
linux ~ $ ./test_read
7 size=128
7 size=7
在第一次调用中使用保留而不是调整大小:
linux ~ $ cat test_read.cpp
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main( void )
string filename("file");
size_t bytesAvailable = 128;
size_t toRead = 128;
ifstream inf( filename.c_str() );
if( inf )
vector<unsigned char> mDataBuffer;
mDataBuffer.reserve( bytesAvailable ) ;
inf.read( (char*)( &mDataBuffer[0]), toRead ) ;
size_t counted = inf.gcount();
cout << counted << " size=" << mDataBuffer.size() << endl;
mDataBuffer.resize( counted ) ;
cout << counted << " size=" << mDataBuffer.size() << endl;
return 0;
linux ~ $ g++ test_read.cpp -Wall -o test_read
linux ~ $ ./test_read
7 size=0
7 size=7
如您所见,如果不调用 .resize(counted),向量的大小将是错误的。请记住这一点。 使用强制转换是很常见的,请参阅cppReference
【讨论】:
这是读取签名字符。我知道这行得通。我特别想阅读无符号字符 只需将 char[] 更改为 unsigned char[]。 是否可以不强制转换? 你为什么不想投?你可以使用 c++ reinterpret_cast更简单的方法:
#include <fstream>
#include <vector>
using namespace std;
int main()
vector<unsigned char> bytes;
ifstream file1("main1.cpp", ios_base::in | ios_base::binary);
unsigned char ch = file1.get();
while (file1.good())
bytes.push_back(ch);
ch = file1.get();
size_t size = bytes.size();
return 0;
【讨论】:
那是非常低效的。尝试使用 1GB 文件运行基准测试,调用的开销会显示出很大的差异。 @david:文件没有区别。如果存储在无符号字符中,则 0xFF 为 255;如果存储在有符号字符中,则为 -1。因此,为什么演员阵容不是一件坏事。如果这是多字节,唯一的区别是字节序是否不同。 @David:字节序通常只有在切换架构类型时才会出现问题,例如。 powerpc vs x86。以上是关于C ++从文件流中读取无符号字符的主要内容,如果未能解决你的问题,请参考以下文章