我想从二进制文件中读取无符号字节。 所以我写了下面的代码。
#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字节,如变量计数所示。
网上似乎有一些引用说我需要设置区域设置才能使其正常工作。如何做到这一点对我来说并不清楚。
相同的代码使用数据类型'char'而不是'unsigned char'
上面使用unsigned char的代码似乎可以在Windows上运行,但无法在colinux Fedora 2.6.22.18中运行。
我需要做些什么才能让它适用于Linux?
答案 0 :(得分:19)
C ++确实要求实现仅为两个版本的角色特征提供显式特化:
std::char_traits<char>
std::char_traits<wchar_t>
流和字符串使用这些特征来计算各种各样的东西,比如EOF值,一系列字符的比较,字符到int的扩展以及这些东西。
如果您实例化像
这样的流std::basic_ifstream<unsigned char>
您必须确保流可以使用相应的字符特征特化,并且此特化确实有用。此外,流使用facet进行实际格式化和读取数字。同样,您必须手动提供这些特化。该标准甚至不要求实现具有主模板的完整定义。所以你还可以得到一个编译错误:
错误:无法实例化特化std :: char_traits。
我会使用ifstream
代替(basic_ifstream<char>
),然后阅读vector<char>
。解释向量中的数据时,您仍可以在以后将它们转换为unsigned char
。
答案 1 :(得分:14)
不要使用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
在第一次通话中使用reserve而不是调整大小:
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(计数),向量的大小将是错误的。请记住这一点。 使用铸造是常见的,请参阅cppReference
答案 2 :(得分:0)
更简单的方法:
#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;
}