Pytanie w sprawie c++, boost-iostreams, std, boost – Jak odczytać plik do tablicy unsigned char ze std :: ifstream?

4

Więc normalnie robię takie rzeczy jak:

<code>    std::ifstream stream;
    int buff_length = 8192;
    boost::shared_array<char> buffer( new char[buff_length]);
    stream.open( path.string().c_str(), std::ios_base::binary);
    while (stream)
    {
            stream.read(buffer.get(), buff_length);
            //boost::asio::write(*socket, boost::asio::buffer(buffer.get(), stream.gcount()));
    }
    stream.close();
</code>

Zastanawiam się, jak czytaćunsigned char bufor (boost::shared_array<unsigned char> buffer( new unsigned char[buff_length]);)

Jeden z przypadków, w którychreinterpret_cast<> jest właściwie właściwym podejściem. Chad
Ponadto wolałbym shared_ptr <std :: vector <uint8_t>> do shared_array Viktor Sehr

Twoja odpowiedź

1   odpowiedź
11

W najprostszej formie:

<code>std::vector<unsigned char> vec(
      std::istreambuf_iterator<char>(std::cin)
    , std::istreambuf_iterator<char>()
    );
</code>

Zastąpićstd::cin z aktualnym strumieniem.

Powyższe może zrobić więcej niż jedną alokację pamięci (dla plików większych niż bardzo mało bajtów), ponieważstd::istreambuf_iterator<> jest iteratorem wejściowym, a nie iteratorem dostępu losowego lub iteratorem, więc długość pliku nie może być mierzona przez odejmowanie iteratorów takich jakend - begin lub dzwoniącstd::distance(begin, end). Można go zredukować do jednego przydziału pamięci, jeśli wektor zostanie utworzony jako pierwszy pustystd::vector<>::reserve() jest wywoływany, aby przydzielić pamięć dla długości pliku i wreszcie wstawić zakresvec.insert(vec.end(), beg, end) zbeg iend istotastd::istreambuf_iterator<> jak wyżej, aby przeczytać cały plik.

Jeśli rozmiar pliku jest większy niż kilka kilo-bajtów, najskuteczniejsze może być zmapowanie go do pamięci procesu, aby uniknąć kopiowania pamięci z jądra do przestrzeni użytkownika.

Powódstd::istreambuf_iterator<char> jest używany, ponieważ implementacja używastd::char_traits<> który zwykle ma tylko specjalizacjechar iwchar_t. Niezależnie od tego, standardy C i C ++ wymagają wszystkichchar typy mają ten sam układ binarny bez bitów dopełnienia, więc konwersje międzychar, unsigned char isigned char (które są różnymi typami, w przeciwieństwie dosigned int iint będąc tego samego typu) zachowuj wzory bitowe, a tym samym są bezpieczne.

[basic.fundamental / 1]

Równinachar, signed char, iunsigned char są trzy różne typy, zbiorczo nazywanewąskie typy znaków. ZAchar, asigned chari anunsigned char zajmują taką samą ilość miejsca i mają takie same wymagania dotyczące wyrównania; to znaczy, że mają taką samą reprezentację obiektu ... W przypadku wąskich typów znaków wszystkie bity reprezentacji obiektu uczestniczą w reprezentacji wartości ... W przypadku niepodpisanych wąskich typów znaków każdy możliwy wzór bitowy reprezentacji wartości reprezentuje odrębną liczbę. Wymagania te nie dotyczą innych typów. W każdej konkretnej implementacji zwykłychar obiekt może przyjąć te same wartości co asigned char lubunsigned char; który jest zdefiniowany przez implementację. Dla każdej wartościi typuunsigned char w zakresie od 0 do 255 włącznie istnieje wartośćj typuchar taki, że wynik całkowitej konwersji zi dochar jestji wynik całkowitej konwersji zj dounsigned char jesti.

@ M.M Dodano dłuższą wycenę dla Ciebie.Reprezentacja wartości jest inny (bit znaku).Reprezentacja obiektu jest takie samo. Maxim Egorushkin
@MaximEgorushkin ten tekst (dodany w C ++ 14) wydaje się tego wymagaćjeśli zwykły znak jest podpisany musi następować po uzupełnieniu 2. Ale po pierwsze, nie ma równoważnego wymogu w C, jak twierdzisz, a po drugie, nadal pozwalasigned char c = -1; aby użyć uzupełnienia (np. uzyskać wzór bitowy 11111110) i mieć zwykły znak bez znaku M.M
@ M.M Dodano ofertę dla Ciebie. Maxim Egorushkin
+1 dla ostatniego akapitu sehe

Powiązane pytania