2016-10-14 2 views
7

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

Я рассматриваю использование типа int, потому что бит «00000000» (1 байт) интерпретируется как 0!

Целью является сохранение этих данных (байтов) в файл и последующее извлечение из этого файла.

ПРИМЕЧАНИЕ. Файлы содержат нулевые байты («00000000» в битах)!

Я немного потерялся здесь. Помоги мне! = D Спасибо!


UPDATE 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: При использовании массива символов у меня возникли проблемы с преобразованием битов «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); 

UPDATE 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); 

UPDATE IV:

Futher читать о UPDATE III:

c++ - Save the contents of a "std::vector<unsigned char>" to a file


Заключение:

Определенно решение задачи о "00000000" бит (1 байт) было изменить который хранит байты файла до std::vector<unsigned char> в качестве руководства друзей.std::vector<unsigned char> - универсальный тип (существует во всех средах) и будет принимать любые восьмеричные (в отличие от char * в «UPDATE I»)!

Кроме того, переход от массива (char) к вектору (неподписанный символ) имеет решающее значение для успеха! С вектором я управляю своими данными более надежно и полностью независимо от его содержимого (в массиве символов у меня есть проблемы с этим).

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

+0

Что вы делаете с этими байтами? – NathanOliver

+2

'unsigned char' будет содержать общие байты. – AndyG

+4

Я бы использовал 'uint8_t' – krzaq

ответ

2

Есть 3 проблемы в вашем коде:

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

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

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

+0

Я следовал вашим рекомендациям. Мне кажется, что «unsigned char» является решением для моих «00000000» бит (байт). Я сделаю тесты. Я дам вам возвращение! Благодаря! = D –

+0

@EduardoLucio пункт 3 является важным здесь. Вам нужно указать, сколько времени данные, иначе соглашение должно означать конец значением 0 бит. Я предполагаю, что это источник ваших проблем. В противном случае не имеет значения, используете ли вы 'char',' unsigned char' или 'uint8_t', за исключением документирования того, что вы делаете, - все они будут вести себя одинаково. Сохранение байтов в массиве 'char' - это обычная вещь, которую никто не будет путать. –

1

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

  • это ровно 8 бит, или 1 байт, длинный;
  • он без знака без необходимости вводить unsigned каждый раз;
  • все одинаково на всех платформах;
  • это общий тип, который не подразумевает какого-либо конкретного использования, в отличие от char//, который связан с символами текста, даже если его можно технически использовать для любых целей, точно так же, как uint8_t.

Нижняя линия: uint8_t функционально эквивалентна unsigned char, но делает работу лучше сказать это некоторые данные неуточненной природы в исходном коде.

Поэтому используйте std::vector<uint8_t>.
#include <stdint.h>, чтобы сделать определение uint8_t.

P. S. Как указано в комментариях, стандарт C++ определяет char как 1 байт, а байт, строго говоря, не должен быть таким же, как octet (8 бит). В такой гипотетической системе char будет по-прежнему существовать и будет иметь длину 1 байт, но uint8_t определяется как 8 бит (octet) и, следовательно, может не существовать (из-за трудностей с внедрением/служебных данных). Таким образом, char более портативен, теоретически, но uint8_t более строгий и имеет более широкие гарантии ожидаемого поведения.

+0

Что делать, если у меня есть система frankenstein, где 1 байт не 8 бит? – AndyG

+0

* независимо от ширины буквы * Um, ширина 'char' ** всегда ** 1 – NathanOliver

+0

@NathanOliver: действительно ли это? Хорошо, я удалю эту строку, но 'char' все еще не так явно. –

3

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

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

+0

Мне кажется, что «unsigned char» является решением для моих битов «00000000» (байт). Я сделаю тесты. Я вернусь! Благодаря! = D –

Смежные вопросы