Произвольный доступ к большим файлам (требующим поддержки 64-битных смещений файлов) в node.js?

Я подумываю перенести некоторые из своих кроссплатформенных скриптов на node.js отчасти для изучения node.js, отчасти потому, что в последнее время я лучше знаком с JavaScript, а отчасти из-за проблем с поддержкой больших файлов в других языках сценариев.

Некоторые языки сценариев, по-видимому, имеют неоднородную поддержку больших смещений файлов, в зависимости от таких вещей, как то, работают ли они на 32-/64-разрядной ОС или процессоре или должны быть специально скомпилированы с определенными флагами.

Поэтому я все равно хочу поэкспериментировать с node.js, но в Google я не нашел многого в его поддержке (или поддержке библиотеки/фреймворка и т. д.) для больших файлов с 64-битными смещениями.

Я понимаю, что в некоторой степени это будет зависеть, по крайней мере, от базовой целочисленной поддержки JavaScript. Если я правильно прочитал Что такое Max Int в JavaScript? К какому максимальному целочисленному значению может перейти число без потери точности? кажется, что JavaScript использует внутри себя числа с плавающей запятой даже для целых чисел и, следовательно,

наибольшее точное целочисленное значение равно 253

Опять же, node.js предназначен для серверов, а серверы должны рассчитывать на поддержку больших файлов.

Поддерживает ли node.js смещение 64-битных файлов?


ОБНОВЛЕНИЕ

Несмотря на флаги сборки _LARGEFILE_SOURCE и _FILE_OFFSET_BITS, теперь, когда я начал портировать свой проект, который требует этого, я обнаружил, что fs.read(files.d.fd, chunk, 0, 1023, 0x7fffffff, function (err, bytesRead, data) удается, а 0x80000000 терпит неудачу с EINVAL. Это с версией v0.6.11, работающей на 32-битной Windows 7.

Пока я не уверен, является ли это ограничением только в fs, ошибкой в ​​node.js или проблемой только на сборках Windows.

Предполагается ли, что смещения файлов больше 31 бита будут работать в node.js во всех основных модулях на всех платформах?


person hippietrail    schedule 01.12.2012    source источник
comment
Можете ли вы привести пример кода чего-то, что вы пытаетесь достичь, что может сломаться?   -  person jcolebrand    schedule 01.12.2012
comment
Ну, я еще не знаком с io-библиотеками узла, но псевдокод будет примерно таким: offset = getOffsetFromIndex(...); dumpFile.seek(offset); line = dumpFile.readLine(); Я не знаю, очень ли это полезно, это совершенно общее использование смещений файлов. По сути, у меня есть индекс, который я сделал из произвольных файлов дампа MediaWiki, который может быть огромным . У меня есть набор инструментов, которые создают эти индексные файлы и используют их для извлечения произвольной информации из файлов дампа без необходимости анализировать многие гигабайты XML. Perl и C до сих пор.   -  person hippietrail    schedule 01.12.2012
comment
Да, это должно полностью поддерживаться. Дайте ему качели и мисс и посмотреть, что произойдет. Кроме того, чтобы сделать ссылку, вы должны сделать URL-адрес выглядящим как URL-адрес, а именно: //dumps.wiki... или dumps.wiki....   -  person jcolebrand    schedule 01.12.2012
comment
Черт, вырезать и вставить из строки URL-адреса Google Chrome (-;   -  person hippietrail    schedule 01.12.2012
comment
нажатие ‹ctrl›‹l›, а затем ‹ctrl›‹c› (или команда, если вы работаете в OSX) должно полностью скопировать файл http. Не знаю, как ты это сломал. Просто научитесь пользоваться клавиатурой. Ctrl-L отлично подходит для C-c C-v.   -  person jcolebrand    schedule 01.12.2012
comment
@jcolebrand: Да, я открыл новую вкладку, ввел dumps, подождал, пока панель URL найдет соответствующие URL-адреса, использовал стрелку вниз, чтобы перейти к нужному, затем нажал CTRL + C, фактически не переходя на страницу. Я знаю, что Chrome получает часть http://, когда вы на самом деле находитесь на странице. У меня есть талант находить пограничные случаи (-;   -  person hippietrail    schedule 01.12.2012


Ответы (2)


Node.js скомпилирован с _LARGEFILE_SOURCE и _FILE_OFFSET_BITS на всех платформах, поэтому внутри он должен быть безопасным для доступа к большим файлам. (См. common.gypi в корне исходного каталога.)

Что касается библиотек, он использует число для параметров startend) при создании потоков чтения и записи (см. fs.createReadStream). Это означает, что вы можете обращаться к позиции 2 ^ 53 через node (как показано здесь: Также актуально: Какое наибольшее целочисленное значение в JavaScript, к которому может перейти число без потери точности?) Это видно в коде lib/fs.js.

person Joe    schedule 01.12.2012
comment
Спасибо, Джо, - вы, кстати, связались с тем же релевантным предыдущим вопросом, что и я (-; - person hippietrail; 02.12.2012
comment
Ха, я совершенно не заметил. Просто пытался найти что-то, чтобы покрыть эту часть ответа... - person Joe; 02.12.2012
comment
На самом деле _LARGEFILE_SOURCE / _FILE_OFFSET_BITS не упоминаются в common.gypi, если только таких файлов больше одного, и я смотрю не на тот? \-: - person hippietrail; 07.12.2012
comment
Ах! github.com/joyent/node/commit/ Они удаляются как теперь они унаследованы от libuv. - person Joe; 07.12.2012
comment
Мы отстали на несколько оборотов, и я использовал свое локальное исходное дерево. - person Joe; 07.12.2012
comment
Кажется, пока что трудной частью является отсутствие API, таких как fseek() и ftell(), в стандартном модуле fs... - person hippietrail; 18.12.2012
comment
Да, вы не делаете этого в текущем Node. Вы указываете смещение при созданииReadStream; каждый раз, когда вам нужна другая часть, вы создаете новый поток с новым start. Что может быть не так эффективно, если вам нужно много искать маленькие биты вокруг большого файла. - person Joe; 18.12.2012
comment
Несмотря на флаги сборки, теперь, когда я начал портировать свой проект, который требует этого, я обнаружил, что fs.read(files.d.fd, chunk, 0, 1023, 0x7fffffff, function (err, bytesRead, data) удается, но 0x80000000 терпит неудачу с EINVAL. Это с версией v0.6.11, работающей на 32-битной Windows 7. - person hippietrail; 24.12.2012
comment
Версия проблемы также существует с версией v0.4.8, работающей в SunOS, но в этом случае она молча терпит неудачу, пытаясь найти позицию 0 файла для любого position над 0x7fffffff. (У меня нет доступа к более поздней версии для тестирования под *nix.) - person hippietrail; 25.12.2012
comment
Интересный. Я смотрел на исходный код 0.8.9, когда отвечал на это. - person Joe; 25.12.2012
comment
Да, извините, чтобы отменить голосование / не принять. В то время у меня были всевозможные проблемы с моим кодом, пока я не отследил проблемы с версией. Я собирался отправить отчет об ошибке. Я не знал, что узел все еще так быстро развивается и исправляет проблемы новичков. Я думал, что установил его в Windows совсем недавно. - person hippietrail; 25.12.2012

Это было немного сложно отследить, но node.js поддерживает только 64-битные смещения файлов, начиная с версии 0.7. .9 (нестабильная), с конца мая 2012 г. В стабильных версиях, начиная с версии 0.8 .0, с конца июня 2012 г.

fs: 64-битные смещения для вызовов fs (Игорь Зиньковский)

В более ранних версиях режимы отказа при использовании больших смещений варьируются от молчаливого поиска начала файла до создания исключения с помощью EINVAL.

См. (теперь закрытый) отчет об ошибке:

Смещения файлов более 31 бита не поддерживаются

Чтобы программно проверить поддержку больших файлов из кода node.js

if (process.version.substring(1).split('.') >= [0,7,9]) {
  // use 64-bit file offsets...
}
person hippietrail    schedule 25.12.2012