2012-01-16 37 views
5

Tôi cần truy cập tệp lớn hơn 2gb bằng C. Trong một lần chạy chương trình, số byte sẽ được đọc từ tệp và vị trí của vị trí tiếp theo được lưu. Trong lần chạy tiếp theo của chương trình, vị trí tệp được đọc và một số byte được đọc bắt đầu từ vị trí đó. Các biến chứng là đôi khi tập tin có thể được 'nén' bằng cách sao chép nó vào một tệp mới, ít hơn bất kỳ byte nào đã được đọc (tôi nghĩ rằng sao chép là cách duy nhất để thực hiện điều đó). Số byte bị loại bỏ theo cách này cũng sẽ được lưu lại.Truy cập các tệp lớn trong C

Tôi cần biết vị trí hiện tại của tệp từ khởi đầu ban đầu để đồng bộ hóa với một tệp khác. Điều này sẽ dễ dàng bởi vì nó chỉ là (current_offset + deleted_bytes).

Lý do không đơn giản là fseek chỉ sử dụng chỉ mục dài int giới hạn tệp thành 2gb và fsetpos sử dụng cấu trúc fpos_t cho chỉ mục vị trí, không phải là số và không thể chuyển đổi qua lại đến một. Tôi không biết bất kỳ cách nào để sử dụng một chỉ mục dài dài int cho định vị tập tin, đó sẽ là giải pháp lý tưởng.

Tôi phải làm gì?

+2

Nền tảng nào? 'ftello()' và 'fseeko()' có thể là một tùy chọn. –

+0

ftello và fseeko sẽ tuân thủ POSIX.1, nhưng> 2GB cũng là vấn đề phụ thuộc vào hệ thống tập tin. –

Trả lời

6

Trên cửa sổ, bạn có thể sử dụng _lseeki64() để thực hiện tìm kiếm 64 bit.

Đối với khả năng tương thích với Linux, bạn cũng có thể thêm -D_FILE_OFFSET_BITS=64 tại thời gian biên dịch, và sau đó làm điều này trong một trong những tiêu đề của bạn:

#ifdef __MINGW32__ // or whatever you use to find out you're compiling on windows 
#define lseek _lseeki64 
#endif 

sau đó sử dụng lseek() ở khắp mọi nơi như bình thường. Điều này hoạt động vì các cửa sổ bỏ qua cờ _FILE_OFFSET_BITS và Linux sẽ không thấy định nghĩa lại của lseek.

Ngoài ra còn có _fseeki64() nếu bạn muốn có một phiên bản FILE*, và có tương đương 64 bit tell()ftell() chức năng quá (_telli64()_ftelli64()).

+0

Tôi nghĩ đó là những gì tôi cần. Cảm ơn! – user1151125

+0

Bạn được chào đón. Một lưu ý khác khi làm cho nó di động - tôi không thể nhớ liệu các cửa sổ có khai báo 'off_t' hay không, vì vậy bạn cũng có thể cần' #define off_t __int64' trên các cửa sổ (để bạn có thể viết mã cho [giao diện 'lseek()' (http : //www.kernel.org/doc/man-pages/online/pages/man2/lseek.2.html)). Nhưng tôi không chắc chắn 100% - có lẽ 'off_t' được định nghĩa ở đâu đó ngay bây giờ. –

+0

@TimothyJones Làm thế nào để bạn đặt _file_offset_bits trong Windows? Tôi đang biên soạn từ Visual studio 2008 trên một máy tính Windows 7 32 bit. Tôi đã cố gắng làm theo ví dụ này http://coding.derkeiler.com/Archive/C_CPP/comp.lang.c/2006-12/msg03560.html nhưng tôi nhận được lỗi sau c2371: 'off_t': redefinition; các loại cơ bản khác nhau – savi

1

Thêm cờ biên soạn -D_FILE_OFFSET_BITS=64, làm cho fopen, fseek, off_t v.v. trở thành 64 bit và có thể sử dụng để thao tác các tệp có kích thước lớn hơn 2 GB. Xem Large File Support in Linux để biết thêm thông tin.

+0

Giải pháp tuyệt vời. Thật không may tôi nên có đề cập đến tôi đang sử dụng Windows và Visual Studio. – user1151125

+0

Tôi đoán tôi không nghĩ đến giải pháp cụ thể của trình biên dịch. Tôi đã tìm kiếm tài liệu Visual Studio và tìm thấy SetFilePointer sử dụng các chỉ mục 64 bit trong Windows. Tôi đã hy vọng để làm cho mã của tôi di động nhiều hơn mặc dù. Có lẽ tôi cần phải học cách sử dụng #ifdef để phát hiện nền tảng nào trên đó và có toàn bộ danh sách các chỉ thị của trình biên dịch hoặc một thứ gì đó. – user1151125

+0

Tôi sẽ để lại câu trả lời trong trường hợp nó hữu ích cho người dùng Linux/OS X. Một Makefile sẽ cho phép bạn xác định các tùy chọn biên dịch theo nền tảng. –

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