2011-01-21 28 views
34

Tôi muốn tránh các bản sao không cần thiết. Tôi đang nhắm đến một cái gì đó dọc theo dòng:Cách hiệu quả để đọc tệp thành một tiêu chuẩn :: vector <char>?

std::ifstream testFile("testfile", "rb"); 
std::vector<char> fileContents; 
int fileSize = getFileSize(testFile); 
fileContents.reserve(fileSize); 
testFile.read(&fileContents[0], fileSize); 

(mà không làm việc vì reserve không thực sự chèn bất cứ điều gì vào vector, vì vậy tôi không thể truy cập [0]).

Tất nhiên, std::vector<char> fileContents(fileSize) hoạt động, nhưng có chi phí khởi tạo tất cả các phần tử (fileSize có thể khá lớn). Tương tự cho resize().

Câu hỏi này không quá quan trọng về mức độ quan trọng của chi phí. Thay vào đó, tôi chỉ tò mò muốn biết nếu có một cách khác.

+1

Nếu bạn muốn tránh chi phí phân bổ lại được yêu cầu bởi 'push_back' _and_ bạn muốn tránh chi phí lấy zeroing bộ đệm cần thiết bằng cách sử dụng' resize', không sử dụng 'std :: vector': sử dụng 'boost :: scoped_array' hoặc một cái gì đó tương tự. –

Trả lời

54

Các hình thức kinh điển là thế này:

#include<iterator> 
// ... 

std::ifstream testFile("testfile", std::ios::binary); 
std::vector<char> fileContents((std::istreambuf_iterator<char>(testFile)), 
           std::istreambuf_iterator<char>()); 

Nếu bạn đang lo lắng về tái phân bổ sau đó không gian dự trữ trong vector:

#include<iterator> 
// ... 

std::ifstream testFile("testfile", std::ios::binary); 
std::vector<char> fileContents; 
fileContents.reserve(fileSize); 
fileContents.assign(std::istreambuf_iterator<char>(testFile), 
        std::istreambuf_iterator<char>()); 
+0

Sẽ không tái phân bổ khi vector đang phát triển? (Vì các trình vòng lặp có thể không hỗ trợ phép trừ, hàm tạo không thể xác định kích thước trước.) – Thomas

+0

Vâng, nó sẽ như thế. Nếu đó thực sự là một mối quan tâm, hãy dự trữ và sử dụng 'std :: copy()'. Đã cập nhật. – wilhelmtell

+0

Trong ví dụ thứ hai, 'dự trữ' cần phải là' thay đổi kích thước', không? –

0

Nếu tôi hiểu chính xác bạn, bạn muốn đọc từng phần tử nhưng không muốn tải tất cả vào fileContents, đúng không? Cá nhân tôi không nghĩ rằng điều này sẽ tạo các bản sao không cần thiết vì các tệp mở nhiều lần sẽ làm giảm hiệu suất nhiều hơn. Đọc một lần vào một vector fileContents là một giải pháp hợp lý trong trường hợp này.

+0

Tôi không có nghĩa là bỏ phiếu này xuống, nhưng nó bị khóa. Nếu bạn chỉnh sửa câu trả lời tôi có thể/sẽ loại bỏ phiếu bầu xuống. – ditkin

5

Nếu bạn muốn thực sự đọc zero-sao chép, có nghĩa là, để loại bỏ việc sao chép từ hạt nhân sang không gian người dùng, chỉ cần ánh xạ tệp vào bộ nhớ. Viết trình bao bọc tệp được ánh xạ của riêng bạn hoặc sử dụng một tệp từ boost::interprocess.

Các vấn đề liên quan