2009-03-02 150 views
8

我想从二进制文件中读取无符号字节。 所以我写了下面的代码。从文件流中读取无符号字符的C++

#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字节,如变量计数所示。

似乎有网上的参考资料,说我需要设置语言环境来完成这项工作。如何做到这一点是不明确的。

相同的代码工作使用的数据类型,而不是“无符号的字符”

使用无符号字符似乎在Windows上运行上面的代码“字符”,但在coLinux的Fedora的2.6.22.18失败运行。

我需要做些什么才能让它适用于Linux?

+0

不是一个问题的答案,但相关的。请记住,C++中字符串类的定义是`typedef basic_string string;`,所以你总是可以使一个unsigned char字符串类成为``typedef basic_string bytestring;`。 – 2009-03-02 23:47:11

+0

是真的,但我想读取一个BINARY文件 – David 2009-03-03 06:29:06

+0

.read()和.write()可用于二进制/文本,流操作符<< and >>仅用于文本文件。计算机上的所有数据最终都是二进制的,这就是你如何选择解释它。 – sfossen 2009-03-03 15:35:11

回答

15

C++确实需要只执行为性格特征的两个版本提供明确的限定:

std::char_traits<char> 
std::char_traits<wchar_t> 

的流和字符串使用这些特质找出各种的东西,比如EOF值,一系列字符的比较,一个字符扩展到一个int等等。

如果你喜欢实例

std::basic_ifstream<unsigned char> 

流你必须确保有相应的性格特征专业化的流可以使用,并且这种专业化确实做有用的事情。另外,流使用facet来进行实际的格式设置和数字的读取。同样,你也必须手动提供这些专业化。该标准甚至不要求实现具有主模板的完整定义。所以,你可以得到藏汉编译错误:

error: specialization std::char_traits could not be instantiated.

我会用ifstream,而不是(这是一个basic_ifstream<char>),然后去读入vector<char>。在解释向量中的数据时,您仍然可以稍后将它们转换为unsigned char

13

不要使用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(计数),矢量的大小将是错误的。请记住这一点。 它是一种常见的使用铸造看cppReference

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; 
}