2014-11-05 22 views
6

我使用的是Lua的腳本來確定文件大小:Lua - io.open()只能達到2 GB?

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 

不過,這似乎只是對文件的工作最大2GB。對於較大的文件filesize總是nilio.open有沒有限制?如果是這樣,我怎麼能解決這個問題?

在Windows Server 2008 R2的64位運行的Lua 5.1.4

+2

順便說一句,你應該使用'「RB」',而不是'「R打開二進制文件「'。 – siffiejoe 2014-11-05 10:42:09

+0

是升級到Lua 5.2的可能性嗎? – lhf 2014-11-05 10:57:12

+0

由於lua是acutally嵌入式,我不認爲我可以輕鬆升級:(將5.2解決問題? – silent 2014-11-05 11:57:26

回答

3

內部,Lua使用了ISO C函數long int ftell(FILE *stream);確定file:seek()返回值。 A long int在Windows上總是32位,所以你在這裏運氣不好。如果可以的話,你應該使用一些外部庫來檢測文件大小 - 我建議luafilesystem

5

問題不在io.open,而是file:seek。你可以檢查這樣的錯誤:

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

錯誤消息可能是Invalid argument。這是因爲對於大於2GB的文件,其大小超過了32位long可容納的大小,這導致C函數fseek無法工作。

在POSIX系統中,Lua使用fseeko,其大小爲off_t而不是longfseek。在Windows中,有一個_fseeki64,我猜這是類似的工作。如果這些不可用,則使用fseek,這會導致問題。


相關來源是liolib.c(Lua 5.2)。正如@lhf指出的,在Lua 5.1中,總是使用fseeksource)。升級到Lua 5.2可能可以解決問題。

+1

但是你仍然可以讀寫大於2G的數據。我在Win2k3(x32)上讀取9G文件。你只能不找'seek' – moteus 2014-11-05 10:55:52

+0

不幸的是,Lua 5.1只使用'fseek',而不會嘗試使用'fseeko'。 – lhf 2014-11-05 10:56:11

+0

是的,對,我得到了無效的參數。 那麼唯一的選擇是使用另一個庫?! – silent 2014-11-05 11:59:11

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