Я рассмотрел много ответов для компиляции кода для создания этого файлами чтения-записи вне 4 ГБ макс. позволенный файловыми смещениями на 32 бита. У меня нет удачи ни с одним из "простых" решений, которые я нахожу.
Суть, у меня есть Сервер Ubuntu 11,10 работ маленького ноутбука (архитектура Intel на 32 бита). Я пытаюсь считать unicode файл, который составляет 343 868 522 737 байтов в размере (0x50102940f1). Машина Ubuntu продолжает думать, что это намного меньше (0x102940f1), который оказывается только более низкими 32 битами измеренного файла истинных на 64 бита.
Я записал небольшую программу, которую я скомпилировал на MacOS и на поле Ubuntu. Mac, кажется, ведет себя правильно, поле Ubuntu не делает.
Небольшая программа ниже. В то время как я прокомментировал блок кода, который действительно только необходим для Mac. Среда Ubuntu скомпилирует оба прекрасные блока кода - и генерирует точно тот же ответ для обоих блоков.
// Necessary for Ubuntu build?
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
//#include <features.h>
// finish Ubuntu
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
// Ubuntu version
off64_t fileMaxLen(FILE* fin) {
off64_t fmaxlen = 0;
if( (fin!=NULL) && (fseeko64(fin,0,SEEK_END) == 0) ) {
fmaxlen = ftello64(fin);
fprintf(stdout,"fileMaxLen(): file length is: %#lx \n",(long unsigned int)fmaxlen);
fseeko64(fin,0,SEEK_SET);
}
}
// Mac OS version
//off_t fileMaxLen(FILE* fin) {
// off_t fmaxlen = 0;
// if( (fin!=NULL) && (fseeko(fin,0,SEEK_END) == 0) ) {
// fmaxlen = ftello(fin);
// fprintf(stdout,"fileMaxLen(): file length is: %#lx \n",(long unsigned int)fmaxlen);
// fseeko(fin,0,SEEK_SET);
// }
//}
main(int argc, char* argv[]) {
char fname[255];
char *locale;
FILE* f = NULL;
locale = setlocale(LC_ALL, "");
if( argc>=2 ) {
// get the file for segmenting
memset(fname, '\0', 255);
sprintf(fname,"%s",argv[1]);
fprintf(stdout,"Opening: %s\n",fname);
f = fopen(fname,"r");
fileMaxLen(f);
fprintf(stdout,"Done!\n");
} else {
fprintf(stdout,"Need a filename\n");
}
}
Сохраните отрывок как file_test.c, затем компиляция действительно проста.
gcc file_test.c
Затем выполните a.out
Какие-либо предложения для того, чтобы заставлять этот код распознать файлы кроме того граница на 32 бита? В этой точке я просто озадачен.
Согласно этому , размер long unsigned int
в 32-битном Unix составляет 4 байта - может ли это быть, что значение обрезается там, где вы приводите fmaxlen (long unsigned int)? 112]
Документацию по макросам, управляющим этим поведением, можно найти в man feature_test_macros
.
Из этой документации вам нужно только установить _FILE_OFFSET_BITS
в 64
. Это должно переопределить off_t
и функционировать как fseeko
, ftello
в 64-битных безопасных версиях (это не работает в 64-битных системах и перенаправляет символы в суффиксные версии 64
в 32-битных системах). системы). Это предпочтительнее прямого использования суффиксированных функций 64
.
И, как сказал Сергей, приведение значения off_t
к long unsigned int
приведет к потере информации в 32-битных системах. Я не думаю, что есть стандартный код формата printf
для off_t
, поэтому вам, вероятно, лучше всего привести значение к unsigned long long int
и использовать %#llx
в качестве кода формата. Это должно быть предупреждением бесплатно для обоих размеров слова и не терять информацию.