所以我有一个包含 0xef 0xbf 0xbd 的代码清单。它是测试用例的一部分:
\documentclass{article}
\usepackage{listings}
\begin{document}
\begin{lstlisting}
�\x04��
\end{lstlisting}
\end{document}
十六进制转储:
000000d0 67 7b 62 65 67 69 6e 7d 0a 0a ef bf bd 5c 78 30 |g{begin}.....\x0|
000000e0 34 ef bf bd ef bf bd 0a 0a 5c 6c 73 74 6c 69 73 |4........\lstlis|
000000f0 74 69 6e 67 7b 65 6e 64 7d 0a 0a 5c 65 6e 64 7b |ting{end}..\end{|
lualatex 说!字符串包含无效的 utf-8 序列
我怎样才能让 lualatex 将其打印为黑色背景上的问号或类似的东西?
答案1
lulatex 似乎不接受 U+FFFD,即使正确编码为 UTF-8,这似乎是错误的,但无论如何,您可以使用输入缓冲区回调将其删除,这里将其更改为?
\documentclass{article}
\begin{document}
\directlua{
function zzz(buff)
return string.gsub(buff,"^^^^fffd","?")
end
luatexbase.add_to_callback ( "process_input_buffer", zzz, "zzz" )
}
hmmm�
\end{document}
查看源代码可以清楚地了解为什么会发生这种情况,如果无法解码输入流,则函数返回 FFFD,然后如果它返回 FFFD,则会发出无效序列错误。但是,这意味着您在正确编码的 FFFD 输入字符上遇到错误。
unsigned str2uni(const unsigned char *k)
{
register int ch;
int val = 0xFFFD;
const unsigned char *text = k;
if ((ch = *text++) < 0x80) {
val = (unsigned) ch;
} else if (ch <= 0xbf) { /* error */
} else if (ch <= 0xdf) {
if (*text >= 0x80 && *text < 0xc0)
val = (unsigned) (((ch & 0x1f) << 6) | (*text++ & 0x3f));
} else if (ch <= 0xef) {
if (*text >= 0x80 && *text < 0xc0 && text[1] >= 0x80 && text[1] < 0xc0) {
val = (unsigned)
(((ch & 0xf) << 12) | ((text[0] & 0x3f) << 6) |
(text[1] & 0x3f));
}
} else if (ch <= 0xf7) {
int w = (((ch & 0x7) << 2) | ((text[0] & 0x30) >> 4)) - 1, w2;
w = (w << 6) | ((text[0] & 0xf) << 2) | ((text[1] & 0x30) >> 4);
w2 = ((text[1] & 0xf) << 6) | (text[2] & 0x3f);
val = (unsigned) (w * 0x400 + w2 + 0x10000);
if (*text < 0x80 || text[1] < 0x80 || text[2] < 0x80 ||
*text >= 0xc0 || text[1] >= 0xc0 || text[2] >= 0xc0)
val = 0xFFFD;
} else {
/* the 5- and 6-byte UTF-8 sequences generate integers
that are outside of the valid UCS range, and therefore
unsupported
*/
}
if (val == 0xFFFD)
utf_error();
return (val);
}