2014-11-05 2 views
6

Я использую скрипт Lua для определения размера файла:Lua - io.open() только до 2 ГБ?

local filesize=0 
local filePath = "somepath.bin" 
local file,msg = io.open(filePath, "r") 
if file then 
    filesize=file:seek("end") 
    file:close() 
    filePresent = true 
end 

Однако, это только кажется, работает для файлов до 2 Гб. Для больших файлов filesize всегда nil. Есть ли ограничения на io.open? И если да, то как я могу обойти это?

Запуск Lua 5.1.4 на Windows Server 2008 R2 64bit

+2

Btw, вы должны открыть двоичные файлы с помощью '«радиоканал»' вместо '" г «'. – siffiejoe

+0

Возможно ли обновление до Lua 5.2? – lhf

+0

Как явствует, я не думаю, что я мог бы легко обновить :(What would 5.2 решить проблему? – silent

ответ

3

Внутренне, Lua использует функцию ISO C long int ftell(FILE *stream); для определения возвращаемого значения для file:seek(). A long int всегда 32 бит в Windows, поэтому вам здесь не повезло. Если вы можете, вы должны использовать некоторую внешнюю библиотеку для определения размера файла - рекомендую luafilesystem.

5

Проблема не в io.open, но file:seek. Вы можете проверить ошибки, как это:

filesize, err = file:seek("end") 
if not filesize then 
    print(err) 
end 

сообщение об ошибке, вероятно, Invalid argument. Это связано с тем, что для файлов размером более 2 ГБ его размер превышает то, что может содержать 32-разрядный long, что приводит к невозможности работы функции C fseek.

В системах POSIX, Lua использует fseeko, который принимает размер off_t вместо long в fseek. В Windows есть _fseeki64, который, как я думаю, выполняет аналогичную работу. Если они недоступны, используется fseek, и это вызовет проблему.


Соответствующий источник: liolib.c (Lua 5.2). Как указывает @lhf, в Lua 5.1 всегда используется fseek (source). Модернизация до Lua 5.2 могла бы решить проблему.

+1

Но вы все еще можете читать/писать данные крупнее, чем 2G. Я прочитал файл 9G на Win2k3 (x32). Вы не можете делать 'seek' – moteus

+0

К сожалению, Lua 5.1 использует' fseek' только и не пытается использовать 'fseeko'. – lhf

+0

Да, правильно, я получаю неверный аргумент. Итак, единственный вариант - использовать другую библиотеку ?! – silent

0

На старых версиях Lua (где file:seek() ограничивается 2Gb), вы можете попросить cmd.exe, чтобы получить размер файла:.

function filesize(filename) 
    -- returns file size (or nil if the file doesn't exist or unable to open) 
    local command = 'cmd /d/c for %f in ("'..filename..'") do @echo(%~zf' 
    return tonumber(io.popen(command):read'*a') 
end 

print(filesize[[C:\Program Files\Windows Media Player\wmplayer.exe]]) 
     --> 73728 
print(filesize[[E:\City.of.the.Living.Dead.1980.720p.BluRay.x264.Skazhutin.mkv]]) 
     --> 8505168882 
Смежные вопросы