0
votes

Lire un fichier binaire où chaque élément est un entier de 2 octets

J'ai un fichier binaire avec l'extension .b16 dessus, les informations contenues sont sous forme d'entier non signé (plage 0..65535, extension de fichier .b16, ordre des octets: octet bas / octet haut).

Les fichiers principaux sont otypes03.b08 à otypes08.b08, otypes09.b16 et otypes10.b16. Ils contiennent les coordonnées de tous les inéquivalents ensembles de points (types d'ordre) pour le nombre n donné de points.

J'ai lu avec succès tous les fichiers avec l'extension .b08, mais quand il s'agit de lire les fichiers .b16, je n'obtiens pas le informations attendues.

Ce que j'ai jusqu'à présent: (Ceci est une version modifiée de l'algorithme de lecture exclusivement à utiliser pour le format .b16)

//Reads a file of binary points and stores it on vector vPoints.
int readPoints(int n, string file_name, vector<Point> & vPoints){
    ifstream input(file_name, std::ios::binary);
    if(input.fail()) return 1;
    // copies all data into buffer
    //Stored as unsigned int. Arithmetic operations (+-*/) can be used! :)
    //Can be treated as signed int or unsigned int.
    vector< unsigned char> buffer(std::istreambuf_iterator<char>(input), {});
    //Copying each pair of binary points to a vector of Point objects
    Point temp;
    cout << "Buffer size: " << buffer.size() << endl;
    for( unsigned int i=0;i< buffer.size();i+=2){
        temp.x = buffer[i];
        temp.y = buffer[i+2];
        vPoints.push_back(temp);
    }
    return 0;
}

Chaque élément du fichier est une coordonnée d'un point dans le plan, cependant il semble que je lis mal, les coordonnées lues ne sont pas celles qui devraient l'être. Je ne sais pas ce que je fais de mal.

Ce que j'utilise pour le format .b08:

int readPoints(int n, string file_name, vector<Point> & vPoints){
    ifstream input(file_name, std::ios::binary);
    if(input.fail()) return 1;

    vector< unsigned char> buffer(std::istreambuf_iterator<char>(input), {});
    //Copying each pair of binary points to a vector of Point objects
    Point temp;
    for( unsigned int i=0;i< buffer.size();i+=4){
        temp.x = buffer[i] | buffer[i+1]  ;
        temp.y = buffer[i+2] | buffer[i+3]  ;
        vPoints.push_back(temp);
    }
    return 0;
}

Plus d'informations sur la base de données I ' m en utilisant est ici: http://www.ist.tugraz.at/aichholzer/research / rp / triangulations / ordertypes /

Le fichier que j'essaie de lire est otypes09.b16 qui fait 5,7 Mo juste au cas où vous voudriez l'essayer.

Merci pour votre temps.


3 commentaires

Vous avez deux options: 1) Lire le fichier 16 bits en mémoire, puis permuter les octets si nécessaire; ou 2) Lire deux octets à la fois, assembler dans le bon Endianess et stocker en mémoire.


Est-il possible que l'ordre des octets soit différent de celui de votre système? Si tel est le cas, vous devez permuter l'ordre des octets au fur et à mesure que vous lisez le fichier


BTW, si l'ordre des octets du fichier est le même que celui de votre système, lisez les données en 16 bits, aucune conversion n'est nécessaire.


3 Réponses :


4
votes
// read in big-endian 16-bit words
for( unsigned int i=0;i< buffer.size();i+=4){
    temp.x = (((unsigned short)buffer[i+0])<<8) | ((unsigned short)buffer[i+1]);
    temp.y = (((unsigned short)buffer[i+2])<<8) | ((unsigned short)buffer[i+3]);
    vPoints.push_back(temp);
}

4 commentaires

La parenthèse à la fin de la question suggère que le fichier est petit-boutiste, il serait donc probablement plus clair de mettre l'accent sur le cas petit-boutiste en le mettant en premier.


Cela fonctionne, cependant, les valeurs que j'obtiens sont vraiment grandes, je ne sais pas si cela est correct ou si je dois reculer à nouveau de 8 bits lors de leur traitement. Les valeurs affichées ont en fait la forme correcte pour chaque type de commande, c'est juste qu'elles sont trop grandes et cela me fait douter. Merci pour votre temps.


Les entiers 16 bits non signés peuvent contenir des valeurs comprises entre 0 et 65535; de cette manière, ils sont différents des entiers 8 bits non signés qui ne peuvent contenir que des valeurs de 0 à 255. Je soupçonne que les valeurs plus élevées sont le comportement attendu (car pouvoir contenir des valeurs plus importantes est le seul avantage de l'utilisation du codage 16 bits au lieu du codage 8 bits, sinon, pourquoi gaspiller de l'espace disque en rendant votre fichier deux fois plus volumineux?)


Et il est logique de simplement faire les opérations que j'essaie de faire avec ces données, merci! Marquer cette réponse comme finale.



1
votes

Voici une méthode:

uint8_t lsb;
uint8_t msb;
uint16_t value;
std::vector<uint16_t> database;
//...
input.read((char *) &lsb, sizeof(lsb));
input.read((char *) &msb, sizeof(msb));
value = msb * 256 + lsb;
database.push_back(value);

Puisqu'il s'agit d'un fichier binaire , la méthode read est utilisée. Vous pouvez remplacer l'attribution de valeur par:
valeur = msb
Bien qu'un bon compilateur doive traduire la première affectation de valeur dans la seconde.


0 commentaires

0
votes

Dans des cas comme celui-ci, en fonction de la moyenne des données, et ayant une résolution absolue, j'aime utiliser des unions. Ce que vous pouvez faire, c'est avoir une union qui a un membre int ainsi qu'une structure contenant 2 shorts. Chaque short contiendra la structure binaire des 2 entiers 16 bits.

Cela dit, les réponses ci-dessus peuvent très bien vous convenir. De nombreuses façons de faire des choses comme celle-ci, alors créez la bonne API pour vous!


0 commentaires