22

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

#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 上工作?

4

3 回答 3

27

C++ 确实只需要实现为两个版本的字符特征提供明确的特化:

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

流和字符串使用这些特征来计算各种事物,例如 EOF 值、字符范围的比较、将字符扩展为 int 等等。

如果您实例化一个流,例如

std::basic_ifstream<unsigned char>

您必须确保流可以使用相应的字符特征特化,并且该特化确实有用。此外,流使用构面来进行数字的实际格式化和读取。同样,您必须手动提供这些专业化。该标准甚至不要求实现具有主模板的完整定义。所以你也可能会得到一个编译错误:

错误:无法实例化特化 std::char_traits。

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

于 2009-03-02T23:31:57.753 回答
21

不要使用 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

于 2009-03-02T23:06:28.330 回答
-1

一个更简单的方法:

#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;
}
于 2009-03-03T00:36:08.257 回答