Quel est le type de vecteur le plus approprié pour conserver les octets d’un fichier?
J’envisage d’utiliser le type int, car les bits “00000000” (1 octet) sont interprétés à 0!
L’objective est de sauvegarder ces données (octets) dans un fichier et de les récupérer ultérieurement.
REMARQUE: les fichiers contiennent des octets nuls (“00000000” en bits)!
Je suis un peu perdu ici. Aidez moi! = D Merci!
MISE À JOUR I:
Pour lire le fichier, j’utilise cette fonction:
char* readFileBytes(const char *name){ std::ifstream fl(name); fl.seekg( 0, std::ios::end ); size_t len = fl.tellg(); char *ret = new char[len]; fl.seekg(0, std::ios::beg); fl.read(ret, len); fl.close(); return ret; }
NOTE I: Je dois trouver un moyen de m’assurer que les bits “00000000” peuvent être récupérés à partir du fichier!
NOTE II: Des suggestions sur un moyen sûr de sauvegarder ces bits “00000000” dans un fichier?
NOTE III: Lors de l’utilisation du tableau de caractères, j’avais des problèmes pour convertir les bits “00000000” pour ce type.
Extrait de code:
int bit8Array[] = {0, 0, 0, 0, 0, 0, 0, 0}; char charByte = (bit8Array[7] ) | (bit8Array[6] << 1) | (bit8Array[5] << 2) | (bit8Array[4] << 3) | (bit8Array[3] << 4) | (bit8Array[2] << 5) | (bit8Array[1] << 6) | (bit8Array[0] << 7);
MISE À JOUR II:
Suivre les recommandations de @chqrlie.
#include #include #include #include #include #include #include #include std::vector readFileBytes(const char* filename) { // Open the file. std::ifstream file(filename, std::ios::binary); // Stop eating new lines in binary mode! file.unsetf(std::ios::skipws); // Get its size std::streampos fileSize; file.seekg(0, std::ios::end); fileSize = file.tellg(); file.seekg(0, std::ios::beg); // Reserve capacity. std::vector unsignedCharVec; unsignedCharVec.reserve(fileSize); // Read the data. unsignedCharVec.insert(unsignedCharVec.begin(), std::istream_iterator(file), std::istream_iterator()); return unsignedCharVec; } int main(){ std::vector unsignedCharVec; // txt file contents "xz" unsignedCharVec=readFileBytes("xz.txt"); // Letters -> UTF8/HEX -> bits! // x -> 78 -> 0111 1000 // z -> 7a -> 0111 1010 for(unsigned char c : unsignedCharVec){ printf("%c\n", c); for(int o=7; o >= 0; o--){ printf("%i", ((c >> o) & 1)); } printf("%s", "\n"); } // Prints... // x // 01111000 // z // 01111010 return 0; }
MISE À JOUR III:
C’est le code que j’utilise pour écrire dans un fichier binary:
void writeFileBytes(const char* filename, std::vector& fileBytes){ std::ofstream file(filename, std::ios::out|std::ios::binary); file.write(fileBytes.size() ? (char*)&fileBytes[0] : 0, std::streamsize(fileBytes.size())); } writeFileBytes("xz.bin", fileBytesOutput);
MISE À JOUR IV:
Plus d’informations sur UPDATE III :
c ++ – Sauvegarde le contenu d’un “std :: vector ” dans un fichier
CONCLUSION:
La solution au problème des bits “00000000” (1 octet) a été de changer le type qui stocke les octets du fichier en std::vector
pour guider les amis. std::vector
est un type universel (existe dans tous les environnements) et accepte n’importe quel octal (contrairement à char * dans “UPDATE I”)!
De plus, passer de tableau (caractère) à vecteur (caractère non signé) était crucial pour le succès! Avec vector, je manipule mes données de manière plus sécurisée et totalement indépendante de son contenu (dans char array, j’ai des problèmes avec cela).
Merci beaucoup!
Il y a 3 problèmes dans votre code:
Vous utilisez le type char
et vous retournez un char *
. Cependant, la valeur de retour n’est pas une chaîne C appropriée, car vous n’atsortingbuez pas d’octet supplémentaire pour le terminateur '\0'
ni la terminaison null.
Si le fichier peut contenir des octets nuls, vous devez probablement utiliser le type unsigned char
ou uint8_t
pour indiquer explicitement que le tableau ne contient pas de texte.
Vous ne renvoyez pas la taille du tableau à l’appelant. L’appelant n’a aucun moyen de dire combien de temps le tableau est. Vous devriez probablement utiliser std::vector
ou std::vector
au lieu d’un tableau alloué avec new
.
Utilisez std::vector
. N’utilisez pas std::uint8_t
: il n’existera pas sur les systèmes ne disposant pas d’un type de matériel natif de 8 bits exactement. unsigned char
existera toujours. il s’agira généralement du plus petit type adressable pris en charge par le matériel. Il doit avoir une largeur minimale de 8 bits. Par conséquent, si vous effectuez un trafic sur 8 octets, il traitera les bits dont vous avez besoin.
Si vous aimez vraiment les types à largeur fixe, vous pouvez envisager std::uint_least8_t
, qui existera toujours et comportera au moins huit bits, ou std::uint_fast8_t
, qui comportera également au moins huit bits. Cependant, les trafics d’entrées / sorties de fichiers dans les types de caractères, et le mélange de caractères et de variantes avec des types “moins” et “rapide” spécifiés de manière vague peuvent bien devenir confus.
uint8_t
est le gagnant à mes yeux:
unsigned
chaque fois; char
/ unsigned char
, qui est associé à des caractères de texte, même s’il peut techniquement être utilisé à des fins identiques à celles de uint8_t
. En uint8_t
ligne: uint8_t
est fonctionnellement équivalent à unsigned char
, mais fait mieux de dire qu’il s’agit de données de nature non spécifiée dans le code source.
Utilisez donc std::vector
.
#include
pour rendre la définition de uint8_t
disponible.
PS Comme indiqué dans les commentaires, la norme C ++ définit char
comme 1 octet, et l’octet n’est pas, à proprement parler, identique à l’ octet
(8 bits). Sur un tel système hypothétique, char
existera toujours et durera 1 octet, mais uint8_t
est défini comme 8 bits ( octet
) et peut donc ne pas exister (en raison de difficultés de mise en œuvre / de temps système). Donc, char
est plus portable, théoriquement, mais uint8_t
est plus ssortingct et offre des garanties plus larges quant au comportement attendu.