Как прочитать raw из произвольного файла, не зная его размера?

avatar
user1424739
9 августа 2021 в 02:49
29
1
0

Я вижу следующую ошибку. Связана ли эта ошибка с объемом памяти на моей машине? Если я хочу, чтобы он мог читать произвольный файл, разрешенный R, но размер которого неизвестен, как заставить readBin() работать таким образом?

$ Rscript main.R
R> con=file('testbin', 'wb')
R> object=list(1:10)
R> print(serialize(object, NULL))
  [1] 58 0a 00 00 00 03 00 04 00 03 00 03 05 00 00 00 00 05 55 54 46 2d 38 00 00 00 13 00 00 00 01 00 00 00 ee 00 00 00 02 00 00
 [42] 00 01 00 04 00 09 00 00 00 0e 63 6f 6d 70 61 63 74 5f 69 6e 74 73 65 71 00 00 00 02 00 00 00 01 00 04 00 09 00 00 00 04 62
 [83] 61 73 65 00 00 00 02 00 00 00 0d 00 00 00 01 00 00 00 0d 00 00 00 fe 00 00 00 0e 00 00 00 03 40 24 00 00 00 00 00 00 3f f0
[124] 00 00 00 00 00 00 3f f0 00 00 00 00 00 00 00 00 00 fe
R> writeBin(serialize(object, NULL), con)
R> close(con)
R> con=file('testbin', 'rb')
R> unserialize(readBin(con, what=raw(), n=2L**36-1))
Error: vector memory exhausted (limit reached?)
Execution halted
Источник
MrFlick
9 августа 2021 в 02:53
0

используйте file.info()$size, чтобы найти размер файла, чтобы вы знали, сколько байтов вам нужно будет прочитать.

user1424739
9 августа 2021 в 02:54
0

нет. Мне не нужно находить размер файла, так как ввод может быть из канала.

smci
9 августа 2021 в 02:55
0

а ты на 64-битной ОС?

user1424739
9 августа 2021 в 02:55
0

Пожалуйста, откройте его.

user1424739
9 августа 2021 в 02:56
0

Да. 64-битная Mac OS. Но решение должно быть кроссплатформенным.

MrFlick
9 августа 2021 в 02:56
0

Но в вашем примере трубы вообще не используются. Если бы он был потоковым в канале, вам нужно было бы читать данные кусками в цикле.

user1424739
9 августа 2021 в 02:58
0

Я уже сказал, не зная его размера. Любое решение должно знать, что его размер не имеет значения.

Ответы (1)

avatar
MrFlick
9 августа 2021 в 03:08
0

Возможно, что входной поток никогда не закончится. Вам нужен верхний предел данных, которые вы читаете в одном фрагменте. Невозможно обработать любой ввод (возможно) бесконечного размера. Начните с числа, намного меньшего, чем 2L**36-1, и при необходимости переберите ввод. Например, вы можете сделать

bindata <- raw(0)
con=file('testbin', 'rb')
while (TRUE) {
  chunk <- readBin(con, what=raw(), n=1024)
  if (length(chunk)==0) {
    break
  } else {
    bindata <- c(bindata, chunk)
  }
}
close(con)

Здесь также нет проверки размера, но вы можете добавить проверку в цикл while и предупреждать об ошибках до исчерпания памяти.

user1424739
9 августа 2021 в 03:26
0

Это неэффективно (t ~ n^2) из-за использования c. Нужно эффективное решение.

user1424739
9 августа 2021 в 03:27
0

Я думаю, что есть недостаток readBin. Кажется, что n может быть отрицательным числом, чтобы указать, что чтение выполняется до EOF.

user1424739
9 августа 2021 в 03:27
0

Входная длина произвольна, но конечна.

MrFlick
9 августа 2021 в 03:35
1

Измените свой n на то, что лучше подходит для ваших данных. На каком-то уровне вам нужно сделать динамическое выделение памяти. Если вы не знаете, насколько большим будет что-то, вам нужно продолжать запрашивать более крупные куски при рекомбинации в памяти. Это действительно бутылочное горлышко для вас? Если это то, что вам нужно оптимизировать, вы всегда можете написать собственный код C++ для своих целей. Это просто не обычный вариант использования R.