Какой тип вектора наиболее подходит для хранения байтов файла?

Какой тип вектора наиболее подходит для хранения байтов файла?

Я рассматриваю использование типа 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) имел решающее значение для успеха! С помощью вектора я манипулирую своими данными более безопасно и полностью независимо от их содержимого (в массиве символов у меня есть проблемы с этим).

Большое спасибо!

7

Решение

В вашем коде 3 проблемы:

  • Вы используете char введите и верните char *, Однако возвращаемое значение не является правильной строкой C, так как вы не выделяете дополнительный байт для '\0' терминатор или ноль прекратить его.

  • Если файл может содержать нулевые байты, вы, вероятно, должны использовать тип unsigned char или же uint8_t сделать явным, что массив не содержит текста.

  • Вы не возвращаете размер массива вызывающей стороне. Вызывающая сторона не может сказать, какой длины массив. Вы, вероятно, должны использовать std::vector<uint8_t> или же std::vector<unsigned char> вместо массива, выделенного с new,

2

Другие решения

использование std::vector<unsigned char>, Не использовать std::uint8_t: он не будет существовать в системах, которые не имеют собственного аппаратного типа ровно 8 бит. unsigned char всегда будет существовать; обычно это наименьший адресуемый тип, поддерживаемый аппаратным обеспечением, и его ширина должна быть не менее 8 бит, поэтому, если вы используете 8-битные байты, он будет обрабатывать нужные вам биты.

Если вам действительно очень нравятся типы с фиксированной шириной, вы можете рассмотреть std::uint_least8_t, который всегда будет существовать, и имеет как минимум восемь битов, или std::uint_fast8_t, который также имеет как минимум восемь битов. Но файл I / O трафик в char типы и смешивание char и его варианты со смутно заданными типами «наименьший» и «быстрый» могут запутаться.

3

uint8_t победитель в моих глазах:

  • это ровно 8 бит или 1 байт;
  • это без знака без необходимости печатать 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 является более строгим и имеет более широкие гарантии ожидаемого поведения.

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector