Question

Je veux lire des octets non signés à partir d'un fichier binaire. J'ai donc écrit le code suivant.

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

Cela entraîne la lecture toujours de 0 octet, comme indiqué par la variable comptée.

Il semble y avoir des références sur le Web indiquant que je dois définir les paramètres régionaux pour que cela fonctionne. Comment faire exactement cela ne m'est pas clair.

Le même code fonctionne avec le type de données 'char' au lieu de 'unsigned char'

Le code ci-dessus utilisant un caractère non signé semble fonctionner sous Windows mais ne parvient pas à fonctionner dans un Fedora colinux 2.6.22.18.

Que dois-je faire pour que cela fonctionne pour Linux?

Était-ce utile?

La solution

C ++ ne requiert l'implémentation que pour fournir des spécialisations explicites pour deux versions de traits de caractère:

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

Les flux et les chaînes utilisent ces caractéristiques pour comprendre une variété d'éléments, tels que la valeur EOF, la comparaison d'une plage de caractères, l'élargissement d'un caractère à un entier, et ainsi de suite.

Si vous instanciez un flux tel que

std::basic_ifstream<unsigned char>

Vous devez vous assurer que le flux peut utiliser une spécialisation de traits de caractères correspondante et que cette spécialisation produit des résultats utiles. En outre, les flux utilisent des facettes pour effectuer le formatage et la lecture de nombres. De même, vous devez fournir des spécialisations de celles-ci manuellement. La norme n'exige même pas que l'implémentation ait une définition complète du modèle principal. Pour que vous puissiez également obtenir une erreur de compilation:

  

erreur: la spécialisation std :: char_traits n'a pas pu être instanciée.

Je voudrais plutôt utiliser ifstream (qui est un basic_ifstream<char>), puis lire dans un vector<char>. Lors de l'interprétation des données du vecteur, vous pouvez toujours les convertir en unsigned char plus tard.

Autres conseils

N'utilisez pas basic_ifstream car il nécessite une spécialisation.

Utilisation d'un tampon statique:

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

en utilisant un vecteur:

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

utilisant reserve au lieu de redimensionner lors du premier appel:

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

Comme vous pouvez le constater, sans l’appel à .resize (compté), la taille du vecteur sera erronée. S'il vous plaît gardez cela à l'esprit. il est courant d’utiliser le casting, voir cppReference

.

Un moyen beaucoup plus simple:

#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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top