Я рассмотрел ряд ответов для компиляции кода, чтобы он мог читать / записывать файлы за пределы 4 ГБ, разрешенные 32-разрядными смещениями файлов. Мне не повезло ни с одним из «простых» решений, которые я нахожу.
Суть в том, что Ubuntu Server 11.10 работает на небольшом ноутбуке (32-битная архитектура Intel). Я пытаюсь прочитать файл unicode размером 343868522737 байт (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)?
Согласно этому , размер long unsigned int
в 32-разрядном Unix равен 4 байтам - может ли быть, что значение обрезается, когда вы производите fmaxlen (long unsigned int)?
Вы можете найти документацию для макросов, контролирующих это поведение с помощью 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 в качестве кода формата. Это должно быть предупреждением бесплатно на обоих размерах слов и не потерять информацию.