Pergunta

Eu quero ler sem assinatura bytes de um arquivo binário. Então eu escrevi o seguinte código.

#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() ;
}

Isso resulta em lendo em Sempre 0 bytes como mostrado pela variável contadas.

Parece haver referências na web dizendo que eu preciso para definir a localidade para fazer este trabalho. Como fazer isso exatamente não está claro para mim.

O mesmo código funciona usando 'char' o tipo de dados em vez de 'unsigned char'

O código acima usando unsigned char parece funcionar no Windows, mas falha em execução em um colinux Fedora 2.6.22.18.

O que eu preciso fazer para obtê-lo para trabalhar para linux?

Foi útil?

Solução

C ++ requer a implementação apenas para fornecer especializações explícitas para duas versões de traços de caráter:

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

As correntes e cordas usar essas características para descobrir uma variedade de coisas, como o valor EOF, a comparação de um intervalo de caracteres, ampliando de um personagem para um int, e tais coisas.

Se você instanciar um fluxo como

std::basic_ifstream<unsigned char>

Você tem que se certificar de que existe um correspondente especialização traço de caráter que o fluxo pode usar e que esta especialização faz fazer coisas úteis. Além disso, os fluxos de usar facetas para fazer a formatação real e leitura de números. Da mesma forma que você tem para oferecer especializações de quem também manualmente. O padrão não requer nem mesmo a implementação de ter uma definição completa do modelo primário. Então você pode aswell obter um erro de compilação:

erro:. Especialização std :: char_traits não pôde ser instanciado

Gostaria de usar ifstream vez (que é um basic_ifstream<char>) e, em seguida, ir e ler em um vector<char>. Ao interpretar os dados do vetor, você ainda pode convertê-los para unsigned char mais tarde.

Outras dicas

Não use o basic_ifstream pois requer specializtion.

Usando um buffer estático:

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

usando um vetor:

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

usando reserva em vez de redimensionamento na primeira chamada:

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

Como você pode ver, sem a chamada para .Resize (contados), o tamanho do vector será errado. Por favor, lembre-se disso. É comum para fundição uso ver cppReference

Uma maneira muito mais fácil:

#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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top