2009-06-23 37 views
12

Tôi chạy vào tràn số nguyên bằng cách sử dụng tiêu chuẩn ftellfseek tùy chọn bên trong của G ++, nhưng tôi đoán tôi đã nhầm lẫn vì nó có vẻ rằng ftell64fseek64 không khả dụng. Tôi đã tìm kiếm và nhiều trang web dường như tham khảo bằng cách sử dụng lseek với các kiểu dữ liệu off64_t, nhưng tôi không tìm thấy bất kỳ ví dụ nào tham chiếu đến một cái gì đó bằng fseek. Ngay bây giờ các tệp mà tôi đang đọc là tệp 16GB + CSV với kỳ vọng ít nhất gấp đôi.Tìm kiếm và đọc các tập tin lớn trong một Linux ứng dụng C++

Không có bất kỳ thư viện bên ngoài nào là phương pháp đơn giản nhất để đạt được cấu trúc tương tự như với cặp fseek/ftell? Ứng dụng của tôi hiện đang hoạt động bằng cách sử dụng thư viện chuẩn GCC/G ++ cho 4.x.

Trả lời

24

fseek64 là hàm C. Để làm cho nó có sẵn, bạn sẽ phải định nghĩa _FILE_OFFSET_BITS = 64 trước khi bao gồm các tiêu đề hệ thống Điều đó sẽ càng ít xác định fseek thực sự là fseek64. Hoặc làm điều đó trong các đối số trình biên dịch, ví dụ: -D_FILE_OFFSET_BITS gcc = 64 ....

http://www.suse.de/~aj/linux_lfs.html có overviw lớn hỗ trợ tập tin lớn trên linux:

  • Biên dịch chương trình của bạn với "gcc -D_FILE_OFFSET_BITS = 64". Điều này buộc tất cả các cuộc gọi truy cập tập tin sử dụng các biến thể 64 bit. Một số loại cũng thay đổi, ví dụ: off_t trở thành off64_t. Do đó, điều quan trọng là luôn sử dụng đúng loại và không sử dụng, ví dụ: int thay vì off_t. Đối với tính di động với các nền tảng khác, bạn nên sử dụng getconf LFS_CFLAGS sẽ trả về -D_FILE_OFFSET_BITS = 64 trên nền tảng Linux nhưng có thể trả về một số thứ khác trên ví dụ: Solaris. Để liên kết, bạn nên sử dụng các cờ liên kết được báo cáo qua getconf LFS_LDFLAGS. Trên các hệ thống Linux, bạn không cần các cờ liên kết đặc biệt.
  • Xác định _LARGEFILE_SOURCE và _LARGEFILE64_SOURCE. Với những định nghĩa này, bạn có thể sử dụng các hàm LFS như open64 trực tiếp.
  • Sử dụng cờ O_LARGEFILE để mở để hoạt động trên các tệp lớn.
+0

Vì vậy, tôi đã làm theo hướng dẫn của bạn và mọi thứ đều đang biên soạn tệp. Nhưng tôi dường như vẫn đang bị tràn. Làm thế nào bạn sẽ sử dụng tham số O_LARGEFILE với fopen64? –

+0

Nếu bạn biên dịch với -D_FILE_OFFSET_BITS = 64, O_LARGEFILE được cung cấp tự động. Đây không phải là cờ chuẩn; nó được sử dụng trên Linux để theo dõi xem tệp đã được mở bằng giao diện tệp lớn hay chưa. – mark4o

+0

Bạn đã đặt câu hỏi là C++, bạn đang sử dụng/trộn các hoạt động tệp C với luồng C++ hay bạn chỉ sử dụng API C? Ngoài ra, bạn có một số mã thử nghiệm để tái tạo hành vi không? Đó là tối quan trọng mà bạn sử dụng các loại chính xác đối phó với độ dài/offsets. – nos

5

fseek64() không phải là tiêu chuẩn, tài liệu trình biên dịch sẽ cho bạn biết nơi tìm thấy nó.

Bạn đã thử fgetposfsetpos? Chúng được thiết kế cho các tệp lớn và việc triển khai thường sử dụng loại 64 bit làm cơ sở cho fpos_t.

2

Sử dụng fsetpos(3)fgetpos(3). Họ sử dụng các kiểu dữ liệu fpos_t, mà tôi tin rằng được đảm bảo để có thể giữ ít nhất 64 bit.

3

Các bạn đã thử fseeko() với các biểu tượng _FILE_OFFSET_BITS Preprocessor thiết lập để ?

này sẽ cung cấp cho bạn một fseek() -like giao diện nhưng với một tham số offset của loại off_t thay vì dài. Đặt _FILE_OFFSET_BITS = 64 sẽ làm cho off_t loại 64 bit.

Tương tự cho số điện thoại ftello().

9

Nếu bạn muốn tuân theo giao diện chuẩn ISO C, hãy sử dụng fgetpos()fsetpos(). Tuy nhiên, các chức năng này chỉ hữu ích để lưu vị trí tệp và quay lại vị trí tương tự sau đó. Chúng đại diện cho vị trí bằng cách sử dụng loại fpos_t, không bắt buộc phải là một kiểu dữ liệu số nguyên. Ví dụ, trên một hệ thống dựa trên bản ghi, nó có thể là một cấu trúc chứa một số bản ghi và bù đắp trong bản ghi. Điều này có thể quá hạn chế.

POSIX xác định các chức năng ftello()fseeko(), đại diện cho vị trí bằng cách sử dụng loại off_t. Điều này được yêu cầu phải là một loại số nguyên, và giá trị là một byte bù đắp từ đầu của tập tin. Bạn có thể thực hiện số học trên đó và có thể sử dụng fseeko() để thực hiện các tìm kiếm tương đối. Điều này sẽ hoạt động trên Linux và các hệ thống POSIX khác.

Ngoài ra, biên dịch với -D_FILE_OFFSET_BITS=64 (Linux/Solaris). Điều này sẽ xác định off_t là loại 64 bit (ví dụ: off64_t) thay vì long và sẽ xác định lại các chức năng sử dụng bù đắp tập tin là các phiên bản thực hiện bù đắp 64 bit. Đây là mặc định khi bạn đang biên dịch cho 64-bit, vì vậy không cần thiết trong trường hợp đó.

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