【发布时间】:2018-05-02 06:44:53
【问题描述】:
以下 C 代码使用 fgetws() 从 stdin 读取行并将它们写入 stdout。
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#define STR_LEN 128
int main(int argc, char **argv)
{
FILE *infile = stdin, *outfile = stdout;
wchar_t str[STR_LEN];
if (setlocale(LC_ALL, "en.UTF-8") == NULL) {
fprintf(stderr, "Cannot set locale\n");
return 1;
}
for (;;) {
if (!fgetws(str, STR_LEN, infile)) {
if (feof(infile)) {
break;
}
perror("fgetws()");
continue;
}
str[wcscspn(str, L"\r\n")] = L'\0';
if (fwprintf(outfile, L"%ls\n", str) < 0) {
perror("fwprintf()");
}
}
return 0;
}
它总是与 ASCII 文件完美配合,但有时在读取 UTF-8 数据时会从 fgetws() 收到 EILSEQ 错误(非法字节序列),我不知道为什么。
在输出文件中,导致错误的行被截断,然后一些字符丢失,剩余部分在下一行。 奇怪的是,如果我只给出那一行,那么我不会得到任何错误。
例如,如果我读取一个只有几行 UTF-8 行的文件,没关系;如果我多次重复相同的行,那么我会得到EILSEQ。
我几乎可以确定文件已正确编码。
我使用带有 musl-libc 的 Linux。
我的代码有什么问题?
编辑:
我收到几个EILSEQ 错误,具体取决于输入大小,但我不知道两者之间的确切关系。
使用相同的输入,我会在相同的行中得到相同的错误。
它似乎不是触发错误的特定偏移量或字符,但我可能错了。
编辑 2: 我也在 OpenBSD 上测试了代码,它可以工作。此时我怀疑这个问题与Linux或musl-libc有关。
【问题讨论】:
-
str[strcspn(str, "\r\n")] = 0;可能是更好的方法。 -
当然可以。谢谢。
-
它总是在文件中的同一点失败吗?你会得到一两个 EILSEQ 错误吗?触发错误的字符的精确字节偏移量以及该字符的 utf-8 代码是多少?