Поиск соединения gz непредсказуем
У меня возникают проблемы с поиском gzfiles в R. Вот пример:
set.seed(123)
m=data.frame(z=runif(10000),x=rnorm(10000))
write.csv(m,"m.csv")
system("gzip m.csv")
file.info("m.csv.gz")$size
[1] 195975
Это создает m.csv.gz
, который R говорит, что он может искать, и справка для seek
, похоже, согласна:
gzf=gzfile("m.csv.gz")
open(gzf,"rb")
isSeekable(gzf)
[1] TRUE
Теперь небольшие прыжки, назад и вперед, похоже, работают, но если я попробую большой прыжок, я получаю сообщение об ошибке:
seek(gzf,10)
[1] 10
seek(gzf,20)
[1] 10
seek(gzf,10)
[1] 20
seek(gzf,1000)
[1] 100
Warning message:
In seek.connection(gzf, 1000) :
seek on a gzfile connection returned an internal error
Однако, если я reset соединение и запуск снова, я могу получить 1000, если я сделаю это с шагом в 100 байт:
for(i in seq(100,1000,by=100)){seek(gzf,i)}
seek(gzf,NA)
[1] 1000
R имеет несколько резких слов при использовании seek
в Windows: "Использование" искать в Windows "не рекомендуется". но это находится в ящике Linux (R 3.1.1, 32 бит). Аналогичный код в python, использующий библиотеку gz
, отлично работает, ища все.
R 3.2.0 немного информативнее:
Warning messages:
1: In seek.connection(gzf, 1000) : invalid or incomplete compressed data
2: In seek.connection(gzf, 1000) :
seek on a gzfile connection returned an internal error
Идеи? Я представил это как отчет об ошибке.
Ответы
Ответ 1
Это всего лишь образованное предположение: небольшие скачки обрабатываются только в декодированном буфере, когда вы ищете больше, чем размер буфера, он просто выполняет необработанный поиск, тогда он пытается декодировать gzip в середине куска, ведущего к декодированию ошибка, это, скорее всего, ошибка в библиотеке R. Я предлагаю использовать skip вместо поиска, поскольку базовая библиотека не может ничего сделать и не будет иметь никакого влияния на производительность.
Я только что проверил rfc1952 и rfc1951, в gzip вы можете узнать полный размер файла, прежде чем извлекать его, просто прочитав весь заголовок "members" и суммируйте все поля ISIZE, однако вы не можете знать, насколько велика будет дефлированный блок без его декодирования (размер каждого символа находится в словаре), вы просто не можете действительно искать общий поток gzip.
Если вы действительно хотите найти gzip, вы должны заранее проиндексировать его.
dictzip - это библиотека, которая добавляет дополнительные заголовки для поиска.