dlaczego nie wczytuje calego pliku ? i jak poprawnie wczytac plik binarny do std::vector ?

0

Chciałem plik binarny wczytać do zmiennej typu
std::vector<uint8_t>

"wersja 1" (źródło stackoverflow )

        std::ifstream is(tmpFilename, std::ios::binary);
        std::istream_iterator<uint8_t> start(is), end;
        std::vector<uint8_t> data(start, end);

Sprawdziłem na paru plikach i działało poprawnie.
Kolega zgłasza że u niego nie działa , sprawdzam pliki 1,2,3....8 wszystko działa .... plik "9" ZONK
Wszystkie pliki mam o identycznym rozmiarze (1032B) ale niektóre pliki po wczytaniu tworzą wektor o rozmiarze 1030

Wiec szukam na stackoverflow jak to zrobić inaczej : "wersja 2" i to działa poprawnie dla tych plików dla których wcześniej nie działało poprawnie

         std::ifstream source(tmpFilename, std::ios::binary);
         std::vector<uint8_t> data(std::istreambuf_iterator<char>(source), {});

Ale czy ta wersja jest poprawna ?

I "wersja 3" działająca ale bez użycia istreambuf_iterator

        int length{0};
        std::vector<uint8_t> data;
        std::ifstream file(tmpFilename, std::ios::in | std::ifstream::binary);
        if(file.is_open())
        {    
            file.seekg (0, file.end);
            length = file.tellg();
            file.seekg (0, file.beg);        
            printf("%d\n",length);

            data.resize(length);
            file.read((char*)&data[0],length);
        }
1

Chcesz powiedzieć że wersje 1 i 3 działają inaczej dla jakiegoś pliku?

7

Zgaduję, że to może ten case...

When reading characters, std::istream_iterator skips whitespace by default (unless disabled 
with std::noskipws or equivalent), while std::istreambuf_iterator does not. In addition, 
std::istreambuf_iterator is more efficient, since it avoids the overhead of constructing and 
destructing the sentry object once per character. 

https://en.cppreference.com/w/cpp/iterator/istream_iterator

0

wypchnąłem moje pliki binarne+ przyklad na git-a https://github.com/mariuszmaximus/4p_362460.git

5
Adamek Adam napisał(a):
        std::ifstream is(tmpFilename, std::ios::binary);
        std::istream_iterator<uint8_t> start(is), end;
        std::vector<uint8_t> data(start, end);

To jest źle, bo std::istream_iterator używa operatora strumienia operator>> co przy domyślnych ustawieniach powoduje przeskakiwanie białych znaków.
Nieważne w jakim trybie otwarty jest plik, użynie operatora strumienia przy odczytywaniu danych binarnych doprowadzi do dziwnych błedów.

3

Proszę bardzo (obrazek, bo nie umiem inaczej pokolorować ;) )

screenshot-20220727191419.png

0x0a to inaczej \n - dokładnie dwa razy w rog9.dat

Tu masz chyba pełną listę podejrzanych wartości (dla lokali C/POSIX)

$ echo -ne " \f\n\r\t\v" | hexdump -C
00000000  20 0c 0a 0d 09 0b                                 | .....|
2

@Adamek Adam:
Chciałem plik binarny wczytać do zmiennej typu

Ja kiedyś robiłem coś takiego zupełnie inaczej i działało bez zająknięcia, działało tak dobrze, że po zrzuceniu w drugą stronę plik binarny działał.

Dowolny plik binarny otwierałem w HEX edytorze - mój ulubiony to Bless Hex Editor kopiowałem całą zawartość która pojawiła mi się w wersji szesnastkowej i już miałem całość w zmiennej i to tyle - myślę, że niepotrzebnie komplikujesz sobie życie pisząc do tego celu swój kod, jak masz pod ręką HEX edytory, np IDA PRO, Bless i od groma innych.

A jak chciałem z tej zmiennej całą zawartość zrzucić do pliku binarnego, to używałem do tego celu którejś z klas w Qt ale już nie pamiętam której, musiałbym odkopać całe źródła.

EDIT

Już mi się przypomniało jakiej klasy użyłem do zrzucenia HEX-a do BIN-a chyba to był QByteArray - ale tak czy inaczej musiałbym odkopać źródła

1

Dziwny ten strumień w C++ z perspektywy osoby która używała Pascal

1

Jeżeli znasz maksymalny rozmiar pliku to:

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

void makebin(const char *filename)
{
	ofstream ofs(filename,ios::binary);
	for(size_t y=0;y<4;++y) for(size_t x=0;x<256;++x) ofs.write((char*)&x,1);
}

bool checkbin(const vector<uint8_t> &data)
{
	for(size_t i=0,y=0;y<4;++y) for(size_t x=0;x<256;++x,++i) if(data[i]!=x) return false;
	return true;
}

int main()
{
	makebin("test102.bin");
	vector<uint8_t> data(2048);
	ifstream ifs("test102.bin",ios::binary);
	data.resize(ifs.readsome((char*)data.data(),data.size()));
	cout<<(checkbin(data)?"ok":"bad")<<endl;
	return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1