Какой тип вектора наиболее подходит для хранения байтов файла?
Я рассматриваю использование типа int, потому что биты «00000000» (1 байт) интерпретируются как 0!
Цель состоит в том, чтобы сохранить эти данные (байты) в файл и извлечь из этого файла позже.
ПРИМЕЧАНИЕ. Файлы содержат нулевые байты («00000000» в битах)!
Я немного потерян здесь. Помоги мне! = D Спасибо!
ОБНОВЛЕНИЕ I:
Чтобы прочитать файл, я использую эту функцию:
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;
}
ПРИМЕЧАНИЕ I: Мне нужно найти способ гарантировать, что биты «00000000» могут быть восстановлены из файла!
ПРИМЕЧАНИЕ II: Любые предложения для безопасного способа сохранить эти биты «00000000» в файл?
ПРИМЕЧАНИЕ III: При использовании массива char у меня возникли проблемы с преобразованием битов «00000000» для этого типа.
Фрагмент кода:
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);
ОБНОВЛЕНИЕ II:
Следуя рекомендациям @chqrlie.
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <algorithm>
#include <random>
#include <cstring>
#include <iterator>
std::vector<unsigned char> 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<unsigned char> unsignedCharVec;
unsignedCharVec.reserve(fileSize);
// Read the data.
unsignedCharVec.insert(unsignedCharVec.begin(),
std::istream_iterator<unsigned char>(file),
std::istream_iterator<unsigned char>());
return unsignedCharVec;
}
int main(){
std::vector<unsigned char> 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;
}
ОБНОВЛЕНИЕ III:
Это код, который я использую для записи в двоичный файл:
void writeFileBytes(const char* filename, std::vector<unsigned char>& 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);
ОБНОВЛЕНИЕ IV:
Дальше читать о ОБНОВЛЕНИЕ III:
C ++ — сохранить содержимое "станд :: вектор<символ без знака>" в файл
ЗАКЛЮЧЕНИЕ:
Определенно решением проблемы «00000000» битов (1 байт) было изменение типа, в котором хранятся байты файла, на std::vector<unsigned char>
как руководство друзей. std::vector<unsigned char>
является универсальным типом (существует во всех средах) и будет принимать любой восьмеричный код (в отличие от char * в «ОБНОВЛЕНИИ I»)!
Кроме того, переход от массива (char) к вектору (unsigned char) имел решающее значение для успеха! С помощью вектора я манипулирую своими данными более безопасно и полностью независимо от их содержимого (в массиве символов у меня есть проблемы с этим).
Большое спасибо!
В вашем коде 3 проблемы:
Вы используете char
введите и верните char *
, Однако возвращаемое значение не является правильной строкой C, так как вы не выделяете дополнительный байт для '\0'
терминатор или ноль прекратить его.
Если файл может содержать нулевые байты, вы, вероятно, должны использовать тип unsigned char
или же uint8_t
сделать явным, что массив не содержит текста.
Вы не возвращаете размер массива вызывающей стороне. Вызывающая сторона не может сказать, какой длины массив. Вы, вероятно, должны использовать std::vector<uint8_t>
или же std::vector<unsigned char>
вместо массива, выделенного с new
,
использование std::vector<unsigned char>
, Не использовать std::uint8_t
: он не будет существовать в системах, которые не имеют собственного аппаратного типа ровно 8 бит. unsigned char
всегда будет существовать; обычно это наименьший адресуемый тип, поддерживаемый аппаратным обеспечением, и его ширина должна быть не менее 8 бит, поэтому, если вы используете 8-битные байты, он будет обрабатывать нужные вам биты.
Если вам действительно очень нравятся типы с фиксированной шириной, вы можете рассмотреть std::uint_least8_t
, который всегда будет существовать, и имеет как минимум восемь битов, или std::uint_fast8_t
, который также имеет как минимум восемь битов. Но файл I / O трафик в char
типы и смешивание char
и его варианты со смутно заданными типами «наименьший» и «быстрый» могут запутаться.
uint8_t
победитель в моих глазах:
unsigned
каждый раз;char
/ unsigned char
, который связан с символами текста, даже если он технически может быть использован для любых целей так же, как uint8_t
,Нижняя линия: uint8_t
функционально эквивалентно unsigned char
, но лучше говорит это некоторые данные неопределенного характера в исходном коде.
Так что используйте std::vector<uint8_t>
,
#include <stdint.h>
сделать uint8_t
определение доступно.
П. С. Как отмечено в комментариях, стандарт C ++ определяет char
как 1 байт, и байт, строго говоря, не должен совпадать с octet
(8 бит). На такой гипотетической системе, char
будет существовать и будет длиться 1 байт, но uint8_t
определяется как 8 бит (octet
) и, следовательно, может не существовать (из-за трудностей реализации / накладных расходов). Так char
более переносимо, теоретически говоря, но uint8_t
является более строгим и имеет более широкие гарантии ожидаемого поведения.