2011-11-25 24 views
5

staram się osiągnąć coś takiego:Czytanie fragmentów z pliku w trybie binarnym do bufora i piśmie, że bufor do innego pliku

while (ifstream has not been entirely read) 
{ 
    read a chunk of data into a buffer that has size BUFLEN 
    write this buffer to ostream 
} 

Początkowo starałem się to osiągnąć za pomocą ifstream.eof() jak mój czas warunek, ale słyszałem, że to nie jest droga. Szukałem innych funkcji std :: ios :: ifstream, ale nie wiem, co jeszcze można użyć.

PS: Używam bufora, ponieważ przesyłany plik może być bardzo duży.

Odpowiedz

7

Klasy iostream dbają o wszystkie niezbędne buforowania, więc nie musisz musisz. Zwykłym idiomem do skopiowania całego pliku jest po prostu:

fout << fin.rdbuf(); 

Program iostream zajmuje się wszystkimi niezbędnymi buforami. (Jest to nieco nietypowe wykorzystanie <<, ponieważ nie Format. Historyczne powodów, nie ma wątpliwości.)

Jeśli potrzebujesz pętlę, być może dlatego, że chcesz zrobić kilka przekształceń danych przed przepisywanie to, to jest trochę tricker, ponieważ istream::read “ nie powiedzie się ”, chyba że odczyta żądaną liczbę znaków . Z tego powodu trzeba też sprawdzić ile znaki były czytelne i przetwarzać je, nawet jeśli odczytu nie powiodła się:

int readCount; 
while (fin.read(&buf[0], buf.size()) 
     || (readCount = fin.gcount()) != 0) { 
    // ... 
    fout.write(&buf[0], readCount); 
} 

Jest to dość brzydki; lepszym rozwiązaniem może być zawinięcie bufora w klasie i zdefiniowanie operator<< dla tej klasy.

+0

Więc jeśli muszę przeczytać bardzo duży plik i zapisać go do jakiegoś innego pliku, nie muszę się martwić o używanie bufora, iostream robi to już? Robię to jednak, ponieważ wysyłam dane przez TCP na późniejszym etapie. Dzięki za kod, spróbuję go teraz. – codd

+0

Kod działa! Dzięki! – codd

+0

Inna uwaga: czy to też powinno działać, gdy pracuję z plikami nietekstowymi? Ponieważ muszę to zrobić z jakimkolwiek plikiem (pdf, mp3, ...). I wydaje się, że nie działa on na pdf, z którym go przetestowałem. – codd

0

Twoja logika jest po prostu błędna.

Trzeba zabrać więcej tak:

while (a chunk larger than zero could be read) 
{ 
    write chunk to output 
} 

Zobacz jak to jest jeszcze prostsze? Nie ma potrzeby jawnego sprawdzania "końca pliku", po prostu odczytaj dane, dopóki nie zakończysz niepowodzeniem. To koniec.

+0

Widzę, o co ci chodzi. Próbowałem osiągnąć to przy użyciu read() jako warunku, ale read() dał pusty plik i! Read() kontynuował przepisywanie mojego pliku ze śmieciami pomiędzy kopiami. Czy mógłbyś opracować i podać mi konkretne funkcje do wykorzystania? – codd

6

Funkcja istream::read zwraca strumień, który może być używany jako wyrażenie logiczne, więc można zrobić coś takiego:

while (is.read(buffer, BUFLEN)) 
{ 
    outputfile.write(buffer, is.gcount()); 
} 

if (is.eof()) 
{ 
    if (is.gcount() > 0) 
    { 
     // Still a few bytes left to write 
     outputfile.write(buffer, is.gcount()); 
    } 
} 
else if (is.bad()) 
{ 
    // Error reading 
} 

Możesz chcieć sprawdzić, czy pisać wewnątrz pętli nie powiedzie zbyt .

+0

Poniższy kod dał mi pusty nowy plik, być może wiesz, co to za problem? 'while (is.read (buffer, BUFLEN)) {plik wyjściowy (bufor, BUFLEN); } ' – codd

+0

@codd Rozszerzony mój przykładowy kod. Sam to wypróbowałem. –

+0

Dzięki za przykładowy kod Joachim. Wydaje się to również działać z innymi plikami, takimi jak pdf itp.! – codd