重定向的标准输入过早结束Lua for Windows

ztmd8pv5  于 2023-02-05  发布在  Windows
关注(0)|答案(2)|浏览(119)

我在Windows下的cmd窗口中使用Lua,我使用“cat”(来自UnxUtils)将一个文件馈送给Lua脚本,脚本使用“io.read(1)”一次读取一个字节。

local b, n ;
n = -1 ;
b = true ;
while b do
  n = n + 1 ;
  b = io.read(1) ;
end ;
print( n, "bytes read" ) ;

当我向脚本提供一个333K.EXE文件时,它声称“已读取24025字节”。将相同的.EXE文件提供给“wc”(另一个UnxUtils),wc正确地显示为333008。

> cat "Firefox Installer.exe" | lua count.lua
24025   bytes read
cat: write error: Invalid argument
> cat "Firefox Installer.exe" | wc
   1408    8674  333008

因为当我“猫”的时候我得到了预期的答案|wc”,我不认为“cat”程序有什么问题,或者Windows的重定向实现有什么问题。
我不是在寻求如何让Lua脚本更高效的建议,也不需要如何让脚本直接从文件中读取(如预期那样工作)的建议,而是在寻找一个线索,告诉我在哪里可以找到我不能使用Lua编写过滤器(并能够信任结果)的原因。
我查看了输入文件,以确定Ctrl-Z或Ctrl-D是否是早期关闭的原因--它们在文件中出现得非常早。
在“io.read()”返回“false”后,我尝试阅读:脚本承认看到了更多的字节,但仍然不超过333 K输入文件的45 K。

t98cgbkg

t98cgbkg1#

从我的评论复制:
可能是Windows的问题(例如this answer)。Windows对待二进制和文本"流"/文件的方式不同。我假设你的程序的stdin默认是一个文本流;在使用普通Lua时,不可能将stdin的模式更改为二进制模式,您需要一个库来实现这一点。类似lfs = require("lfs"); lfs.setmode(io.stdin, "binary")的东西可能会起作用(使用LuaFileSystem库)。
您还可以尝试修复脚本调用,以便在调用Lua脚本之前使用将stdin更改为二进制模式的脚本设置正确的模式:

./stdbin.c
#include <stdio.h>
#include <unistd.h>
#include <assert.h>

int main(int argc, char** argv) {
    if (argc < 1) {
        printf("Arguments: <program> {args}\n");
        return 1;
    }

    // See  https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setmode?redirectedfrom=MSDN&view=msvc-170
    if (_setmode(_fileno(stdin), _O_BINARY) == -1)
        perror("_setmode failed");

    execvp("lua", ++argv);
    // execvp only returns if there is an error
    perror("execvp failed");
    return 1;
}

注:未经测试。用法:./stdbin lua count.lua.

vhipe2zx

vhipe2zx2#

(This是对LMD答案的补充)
在LuaJIT中,不需要外部库和可执行文件:

local ffi = require"ffi"
ffi.cdef"int _setmode(int,int)"
ffi.C._setmode(0, 0x8000)
-- Now io.read() will return binary data

相关问题