Oui, si vous avez le formatage de taille fixe, donc 10 caractères pour index, 3 caractères pour la longueur, et votre exemple serait encodée comme:
" 1 1c 2 2cc 3 3ccc"
.
Vous parlez également de fstream
, mais il semble que vous recherchiez une sérialisation texte (lisible par l'homme), pas une binaire. Si tel est le cas, mais que vous n'avez pas besoin d'une forme réellement lisible, vous pouvez marquer le premier octet de longueur avec un peu (les chiffres en ASCII sont codés comme 0x30
à 0x39
, donc vous pouvez par exemple définir 0x40
bit sans détruire les données . octets Ensuite, votre exemple ressemblerait à ceci:
1qc2rcc3sccc
(q
= 0x71
= 0x40|0x31
= 0x40|'1'
)
pour une valeur plus il regarderait que: 113q0
... ARGH Je voulais sérialisation 10 caractères longue chaîne "", et regardez ce qui s'est passé, j'ai eu la longueur 100
au lieu de 10
(ou pire encore 10, si vous ne voulez pas limiter), le début et la fin de la longueur doivent être altérés d'une manière ou d'une autre, en utilisant éventuellement le bit 0x80
pour marquer la fin de la longueur.
1\361c2\362cc3\363ccc
(\361
= 0xF1
= 0x40|0x80|0x31
= 0x40|0x80|'1'
)
valeur plus longue deuxième essai:
113q°
(indice 113, la longueur 10, les données "", q
= 0x40|'1'
, °
= 0x80|'0'
).
Vous ne voulez pas plutôt la forme binaire? Serait plus court.
BTW, si cela ne vous dérange pas les valeurs entachant, mais vous voulez rester en ASCII 7 bits, vous pouvez entacher ne démarre pas et à la fin de la longueur, mais les extrémités des deux index et la longueur, et seulement avec 0x40
. Donc le 11c
deviendrait qqc
. Et 113
10
serait 11s1p
.
écriture binaire/lecture avec la plate-forme agnostique ENDIANNESS (ce fichier écrit sur little-endian travaillera sur d'autres plate-forme avec big-endian).
#include <iostream>
#include <cstdint>
#include <vector>
/**
* Writes index+length+data in binary form to "out" stream.
*
* Returns number of bytes written to out stream.
*
* Does no data validation (the variable types are only limits for input data).
*
* writeData and readData are done in endiannes agnostic way.
* So file saved at big-endian platform will be restored correctly on little-endian platform.
**/
size_t writeData(std::ostream & out,
const uint32_t index, const uint16_t length, const uint8_t *data) {
// Write index and length bytes to out stream, resolve endiannes of host platform.
out.put((char)((index>>0)&0xFF));
out.put((char)((index>>8)&0xFF));
out.put((char)((index>>16)&0xFF));
out.put((char)((index>>24)&0xFF));
out.put((char)((length>>0)&0xFF));
out.put((char)((length>>8)&0xFF));
// If any data, write them to stream
if (0 < length) out.write(reinterpret_cast<const char *>(data), length);
return 4 + 2 + length;
}
/**
* Read data from stream "in" stream into variables index, length and data.
*
* If "in" doesn't contain enough bytes for index+length, zero index/length is returned
*
* If "in" contains more than index+length bytes, but the data are shorter than length,
* then "repaired" shorter data are returned with shorter "length" (not the read one).
**/
void readData(std::istream & in,
uint32_t & index, uint16_t & length, std::vector<uint8_t> & data) {
// clear current values in index, length, data
index = length = 0; data.clear();
// read index+length header from stream
uint8_t buffer[6];
in.read(reinterpret_cast<char *>(buffer), 6);
if (6 != in.gcount()) return; // header data (index+legth) not found
// Reassemble read bytes together to index/length numbers in host endiannes.
index = (buffer[0]<<0) | (buffer[1]<<8) | (buffer[2]<<16) | (buffer[3]<<24);
length = (buffer[4]<<0) | (buffer[5]<<8);
if (0 == length) return; // zero length, nothing more to read
// Read the binary data of expected length
data.resize(length); // reserve memory for read
in.read(reinterpret_cast<char *>(data.data()), length);
if (length != in.gcount()) { // data read didn't have expected length, damaged file?
// TODO you may want to handle damaged data in other way, like returning index 0
// This code will simply accept shorter data, and "repair" length
length = in.gcount();
data.resize(length);
}
}
Pour le voir en action, vous pouvez l'essayer sur cpp.sh.
Seulement si votre index est seulement un seul chiffre. Vous avez besoin d'un index de longueur fixe et d'un champ de longueur de longueur fixe, puis remplissez les données avec des zéros. –
non, l'index n'est pas un seul chiffre. ce pourrait être une valeur de tout entier supérieur à 0. – pepero
Si 'IndexLength' contient' 1234', quelle est la valeur de 'Index' et la valeur de' Length': 1, 234 ou 12, 34 ou 123, 4? –