Bonjour à tous,
Il m'arrive régulièrement d'avoir besoin de lire et/ou écrire dans un fichier binaire en C++. Malheureusement, les seules fonctions disponibles dans la bibliothèque standard sont get
/put
et read
/write
, et elles ne prennent en paramètre que des valeurs de type char
ou des tableaux de char
.
En général, je code donc mes propres fonctions qui me permettent de lire/écrire une valeur de n'importe quel type arithmétique dans un flux (en binaire donc). Elles ressemblent généralement à ça :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | template<typename T> T readValue(std::istream &input, bool bigEndian = false) noexcept { assert(std::is_arithmetic<T>::value); std::array<char, sizeof(T)> buffer; input.read(buffer.data(), buffer.size()); if(bigEndian) std::reverse(buffer.begin(), buffer.end()); return *reinterpret_cast<T*>(buffer.data()); } template<typename T> void writeValue(std::ostream &output, T value, bool bigEndian = false) noexcept { assert(std::is_arithmetic<T>::value); std::array<char, sizeof(T)> buffer; std::copy_n(reinterpret_cast<char*>(&value), buffer.size(), buffer.data()); if(bigEndian) std::reverse(buffer.begin(), buffer.end()); output.write(buffer.data(), buffer.size()); } |
Et un exemple d'utilisation :
1 2 3 4 5 6 7 8 9 10 11 | std::fstream file("test.bin", std::ios::in | std::ios::out | std::ios::binary); writeValue<char>(file, 'a'); writeValue<int>(file, 123456); writeValue<float>(file, 123.456, true); file.seekg(std::ios::beg); std::cout << readValue<char>(file) << std::endl; std::cout << readValue<int>(file) << std::endl; std::cout << readValue<float>(file, true) << std::endl; |
Ce code fonctionne parfaitement.
J'ai toutefois besoin de conseils. Que pensez-vous de ces fonctions ? Sont-elles efficaces ? Performantes ? Sécurisées ? Auriez-vous aussi fait ainsi ? Y a-t-il de meilleures alternatives ?