Открытие больших файлов с fopen [duplicate]

Если вы используете Spark с HDFS, я решаю проблему, обычно записывая файлы csv и используя HDFS для слияния. Я непосредственно делаю это в Spark (1.6):

import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs._

def merge(srcPath: String, dstPath: String): Unit =  {
   val hadoopConfig = new Configuration()
   val hdfs = FileSystem.get(hadoopConfig)
   FileUtil.copyMerge(hdfs, new Path(srcPath), hdfs, new Path(dstPath), true, hadoopConfig, null) 
   // the "true" setting deletes the source files once they are merged into the new output
}


val newData = << create your dataframe >>


val outputfile = "/user/feeds/project/outputs/subject"  
var filename = "myinsights"
var outputFileName = outputfile + "/temp_" + filename 
var mergedFileName = outputfile + "/merged_" + filename
var mergeFindGlob  = outputFileName

    newData.write
        .format("com.databricks.spark.csv")
        .option("header", "false")
        .mode("overwrite")
        .save(outputFileName)
    merge(mergeFindGlob, mergedFileName )
    newData.unpersist()

Не могу вспомнить, где я узнал этот трюк, но он может сработать для вас.

9
задан Vilhelm Gray 22 May 2013 в 17:06
поделиться

3 ответа

в long int

long int должно быть AT LEAST 32-бит, но стандарт C99 НЕ ограничивает его 32-разрядным. Стандарт C99 предоставляет удобные типы, такие как int16_t и amp; int32_t и т. д., которые соответствуют размерам бит для целевой платформы.

на ftell / fseek

ftell() и fseek() ограничены 32 битами (включая знаковый бит) на подавляющем большинстве 32-битных систем архитектуры. Поэтому, когда есть большая поддержка файлов, вы сталкиваетесь с этой проблемой 2 ГБ.

Функции POSIX.1-2001 и SysV для fseek и ftell - fseeko и ftello, потому что они используют off_t как параметр для смещения.

вам нужно определить компиляцию с помощью -D_FILE_OFFSET_BITS=64 или определить его где-нибудь, прежде чем включать stdio.h, чтобы убедиться, что off_t - 64-разрядный.

Прочитайте об этом в cert.org безопасном руководстве по кодированию .

О путанице о ftell и размере long int

C99 говорит, что long int должен быть не менее 32-бит, он НЕ говорит, что он не может быть больше

попробуйте следующее в архитектуре x86_64:

#include <stdio.h>

int main(int argc, char *argv[]) {
    FILE *fp;
    fp = fopen( "test.out", "w");
    if ( !fp ) 
        return -1;
    fseek(fp, (1L << 34), SEEK_SET);
    fprintf(fp, "\nhello world\n");
    fclose(fp);
    return 0;
}

Обратите внимание, что 1L просто long, это приведет к созданию файла с 17 ГБ и прикрепляет "\nhello world\n" до конца. Вы можете проверить это путем тривиального использования tail -n1 test.out или явно используя:

dd if = test.out skip = $ ((1 & lt; 25))

< / blockquote>

Обратите внимание, что dd обычно использует размер блока (1 << 9), поэтому 34 - 9 = 25 выгрузит '\nhello world\n'

10
ответ дан ArtB 22 August 2018 в 19:50
поделиться

По крайней мере, на 32-битной ОС ftell() он переполняется или ошибочен или просто запускается в Undefined Behavior.

Чтобы обойти это, вы можете использовать off_t ftello(FILE *stream); и #define _FILE_OFFSET_BITS 64.

Verbatim from man ftello:

Функции fseeko () и ftello () идентичны функциям fseek (3) и ftell (3) (см. fseek (3)), соответственно, за исключением того, что аргумент offset fseeko () и возвращаемое значение ftello () имеет тип off_t вместо long.

На многих архитектурах off_t и long являются 32-битными типами, но компиляция с

   #define _FILE_OFFSET_BITS 64

выключит_t в 64-разрядный тип.


Обновление:

Согласно IEEE Std 1003.1, выпуск 2013 года ftell() должен возвращать -1 и устанавливать errno на EOVERFLOW в таких случаях:

EOVERFLOW

Для ftell ( ), текущее смещение файла не может быть правильно отображено в объекте типа long.

4
ответ дан alk 22 August 2018 в 19:50
поделиться
  • 1
    У некоторых людей было сказано, что ftell всегда возвращает 0 в таких случаях, но переполнение, по-видимому, подразумевает возможность отрицательного возврата. Являются ли переполнения гарантированными "обертывание" в стандарте C99 , или это определяется реализацией? – Vilhelm Gray 22 May 2013 в 17:00
  • 2
    @VilhelmGray: Я сомневаюсь, что он вернется 0, я не вижу никакого резонанса для этого. Наверное, все это столкнется с UB? Просто избегайте этого! Однако UB может привести ко всему ... он также может вернуться тогда! ;-) – alk 22 May 2013 в 17:02
  • 3
    Я думаю, что это сводится к UB. В разделе раздела 6.5 параграфа 5 стандарта C99 ( ISO / IEC 9899: TC3 ): If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined. – Vilhelm Gray 22 May 2013 в 17:12
  • 4
    @VilhelmGray: Спасибо, что посмотрели стандарт, чтобы доказать это ... :-) – alk 22 May 2013 в 17:14
  • 5
    Однако есть ли что-нибудь в стандарте, чтобы предположить, что сам ftell вызывает переполнение - или это значение, которое оно возвращает для этих случаев, не указано? – Vilhelm Gray 22 May 2013 в 17:14

В стандарте C99 отсутствует метод распознавания 64b. Какую ОС / среду вы используете? На окнах есть _ftelli64.

На других платформах посмотрите http://forums.codeguru.com/showthread.php?277234-Cannot-use-fopen () -open -file-больше, чем 4-ГБ [/ д2]

3
ответ дан nothrow 22 August 2018 в 19:50
поделиться
  • 1
    ftell - стандарт C89 и C99 – Ahmed Masud 22 May 2013 в 16:57
  • 2
    @AhmedMasud: Я чувствую, что здесь есть недоразумение. Я подозреваю, что такого метода нет в C99 ... & quot; ссылается на _ftelli64() и не на на ftell(). – alk 22 May 2013 в 17:00
  • 3
    @alk, я не вижу ссылки на _ftelli64 () в вопросе OP, поэтому я до сих пор не понимаю, как ваш ответ вносит свой вклад. – Ahmed Masud 22 May 2013 в 17:06
  • 4
    @AhmedMasud: см. Обновленный ответ. – alk 22 May 2013 в 17:10
  • 5
    @AhmedMasud: Пожалуйста, извините, но требуя, чтобы long & quot; имел длину не менее 32 бит & quot; означает, что может быть точно длиной 32 бит. Существует нет необходимости , чтобы он был 64 бит. Кроме того, I do соглашается с вами в том, что для 64-битной ОС будет тихо странно иметь long менее 64 бит длиной ... ;-) Однако, исходя из моей аргументации, ответ будет правильно, не так ли? – alk 22 May 2013 в 17:16
Другие вопросы по тегам:

Похожие вопросы: