2011-11-25 18 views
5

tôi đang cố gắng để đạt được một cái gì đó như thế này:Reading khối từ một tập tin trong chế độ nhị phân để một bộ đệm và viết đệm đó vào tập tin khác

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

Lúc đầu, tôi đã cố gắng để đạt được điều này bằng cách sử dụng ifstream.eof() như khi tôi điều kiện, nhưng tôi đã nghe nói rằng đây không phải là cách để đi. Tôi đã nhìn vào std :: ios :: ifstream của các chức năng khác, nhưng không thể tìm ra những gì khác để sử dụng.

PS: Tôi đang sử dụng bộ đệm vì tệp đang được chuyển có thể rất lớn.

Trả lời

7

Lớp iostream sẽ xử lý tất cả các vùng đệm cần thiết, vì vậy bạn không cần . Thành ngữ thông thường để sao chép toàn bộ tệp chỉ là:

fout << fin.rdbuf(); 

iostream đảm nhiệm tất cả bộ đệm cần thiết. (Đây là một sử dụng hơi bất thường của <<, vì nó không định dạng. Lịch sử lý do, không có nghi ngờ.)

Nếu bạn cần vòng lặp, có lẽ bởi vì bạn muốn làm một số biến đổi trên dữ liệu trước khi viết lại nó, sau đó là một trình gỡ rối nhỏ, vì istream::read “ không thành công ” trừ khi nó đọc số được yêu cầu. Bởi vì điều này, bạn còn phải kiểm tra có bao nhiêu nhân vật đã được đọc, và xử lý chúng ngay cả khi đọc thất bại:

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

này là khá xấu xí; một giải pháp tốt hơn có thể là quấn bộ đệm trong lớp và xác định một lớp operator<< cho lớp này.

+0

Vì vậy, nếu tôi phải đọc một tập tin rất lớn và viết rằng để một số tập tin khác, tôi không phải lo lắng về việc sử dụng một bộ đệm, iostream hiện này đã? Tôi, tuy nhiên, làm điều đó bởi vì tôi đang gửi dữ liệu qua TCP trong một giai đoạn sau. Cảm ơn bạn đã viết mã, tôi sẽ thử ngay bây giờ. – codd

+0

Mã hoạt động mặc dù! Cảm ơn! – codd

+0

Trên một số lưu ý khác: điều này cũng có tác dụng khi tôi làm việc với các tệp không phải văn bản không? Bởi vì tôi cần để có thể làm điều này với bất kỳ loại tập tin (pdf, mp3, ...). Và nó dường như không hoạt động trên một pdf tôi đã thử nghiệm nó với. – codd

0

Logic của bạn đơn giản là sai.

Bạn cần phải đi về nó nhiều hơn như thế này:

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

Xem cách mà thậm chí còn đơn giản hơn? Không cần phải kiểm tra rõ ràng "kết thúc tệp", chỉ đọc dữ liệu cho đến khi bạn thất bại. Sau đó, bạn đã hoàn tất.

+0

Tôi hiểu ý của bạn là gì. Tôi đã cố gắng đạt được điều đó bằng cách sử dụng read() như điều kiện, nhưng read() đưa ra một tập tin rỗng và đọc() tiếp tục viết lại tập tin của tôi với rác giữa các bản sao. Bạn có phiền phức tạp và cho tôi những chức năng cụ thể để sử dụng không? – codd

6

Chức năng istream::read trả về dòng, có thể được sử dụng như một biểu thức boolean, vì vậy bạn có thể làm điều gì đó như:

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 
} 

Bạn có thể muốn xem xét rằng việc ghi bên trong vòng lặp không thất bại quá .

+0

Mã sau đây đã cho tôi một tệp mới trống, có lẽ bạn biết vấn đề với nó là gì? 'while (is.read (buffer, BUFLEN)) {outfile.write (bộ đệm, BUFLEN); } ' – codd

+0

@codd Mở rộng mã ví dụ của tôi. Tự mình thử. –

+0

Cảm ơn mã ví dụ Joachim. Điều này cũng có vẻ làm việc với các tập tin khác như pdf của vv! – codd