简体   繁体   English

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

[英]redirected stdin ends prematurely Lua for Windows

I'm using Lua in a cmd window under Windows. I use "cat" (from UnxUtils) to feed a file to a Lua script.我在 Windows 下的 cmd window 中使用 Lua。我使用“cat”(来自 UnxUtils)将文件提供给 Lua 脚本。 The script uses "io.read(1)" to read one byte at a time.该脚本使用“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" ) ;

When I feed the script a 333K.EXE file, it claims "24025 bytes read".当我向脚本提供一个 333K.EXE 文件时,它声称“读取了 24025 个字节”。 Feed the same.EXE to "wc" (another UnxUtils), and wc correctly says 333008.将 same.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

Since I get the expected answer when I "cat | wc", I don't think there's anything wrong with the "cat" program, or with Windows' implementation of redirection.因为我在“cat | wc”时得到了预期的答案,所以我认为“cat”程序或 Windows 的重定向实现没有任何问题。

I am not looking for advice on how to make the Lua script more efficient.我不是在寻找有关如何提高 Lua 脚本效率的建议。 I do not need advice on how to make the script read directly from a file (that works as expected).我不需要关于如何使脚本直接从文件中读取(按预期工作)的建议。 I am looking for a clue as to where to look for the reason I can't use Lua to write a filter (and be able to trust the results).我正在寻找关于在哪里寻找我不能使用 Lua 编写过滤器(并且能够信任结果)的原因的线索。

I have looked at the input file to see if a Ctrl-Z or Ctrl-D was the reason for the early shut-off -- they occur very early in the file.我查看了输入文件,看看 Ctrl-Z 或 Ctrl-D 是否是提前关闭的原因——它们出现在文件的早期。

I tried reading after "io.read()" returned "false": the script admitted to seeing more bytes, but still no more than 45K of the 333K input file.我尝试在“io.read()”返回“false”后读取:脚本承认看到了更多字节,但仍然不超过 333K 输入文件的 45K。

Copied from my comments:从我的评论中复制:

Likely to be a Windows issue (see eg this answer ).可能是 Windows 问题(参见例如这个答案)。 Windows treats binary and text "streams" / files differently. Windows 以不同方式对待二进制和文本“流”/文件。 I would assume that your program's stdin is a text stream by default;我假设你的程序的标准输入默认是文本 stream; it isn't possible to change the mode of stdin to binary later on using plain Lua, you'll need a library for that.稍后使用普通 Lua 无法将 stdin 的模式更改为二进制,您需要一个库。 Something like lfs = require("lfs"); lfs.setmode(io.stdin, "binary")lfs = require("lfs"); lfs.setmode(io.stdin, "binary") lfs = require("lfs"); lfs.setmode(io.stdin, "binary") might work (using the LuaFileSystem library). lfs = require("lfs"); lfs.setmode(io.stdin, "binary")可能有效(使用LuaFileSystem库)。

You could also try to fix your script invocation to set the correct mode using a script which changes stdin to binary mode before invoking your Lua script:您还可以尝试修复脚本调用以使用脚本设置正确的模式,该脚本在调用 Lua 脚本之前将stdin更改为二进制模式:

./stdbin.c : ./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;
}

Note: Untested.注意:未经测试。 Usage: ./stdbin lua count.lua .用法: ./stdbin lua count.lua

(This is an addition to LMD's answer) (这是对 LMD 答案的补充)
In LuaJIT no external libraries and executables are needed:在 LuaJIT 中不需要外部库和可执行文件:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM