SQL 转储中的 UTF-8 无效
Invalid UTF-8 in SQL dump
我有一个 MySQL 转储,它不是有效的 UTF-8。两个问题:
- 这可能是某些数据库使用 utf8mb3 也就是 MySQL 的 'utf8' 造成的吗?它确实使用了这种编码。
- 如果是这样,我该如何修复它,无法访问 MySQL 来导入、更改 table 类型并重新导出?我可以使用任何编码转换工具吗?
编辑以添加无效 UTF-8 的特定数据:
uconv -f utf8 a.sql -o /dev/null
Conversion to Unicode from codepage failed at input byte position XXX. Bytes: ed Error: Illegal character found
这是一个十六进制示例。
xxd -s {XXX-16} -l 30 a.sql
YYY: 6e2e 203c 2f70 3e20 cfa1 ecaf a6eb 9ea0 n. </p> ........
aabb aabb aabb aabb aaaa bbbb bbaa aaaa
YYZ: edb6 b0e1 aea5 ee9e a027 2c27 3230 .........','20
^^^^ ^^
编辑 2:在上面添加了更多上下文。另外看起来问题序列符合UTF-8格式,它只是映射到不存在的U+1DDB0。
我使用以下方法“解决”了这个问题:
uconv --from-code utf8 --from-callback substitute --to-code utf8 a.sql -o a.sql.fixed
这只是用默认字符替换任何无效序列。 man unconv
显示其他几个选项,例如转义或删除无效序列。
在我的案例中,似乎只有极少数错误,所以我更感兴趣的是能够处理转储,而不是正确识别这些案例中发生的事情。
编辑:通过使用 --from-callback skip
我可以通过比较输入和输出文件的长度来计算无效序列的数量。
根据 UTF-8,您的第一行 YYY 包含以下字符(所有有效序列):
U+006E n 6e LATIN SMALL LETTER N
U+002E . 2e FULL STOP
U+0020 20 SPACE
U+003C < 3c LESS-THAN SIGN
U+002F / 2f SOLIDUS
U+0070 p 70 LATIN SMALL LETTER P
U+003E > 3e GREATER-THAN SIGN
U+0020 20 SPACE
U+03E1 ϡ cf a1 GREEK SMALL LETTER SAMPI
U+CBE6 쯦 ec af a6 (Hangul)
U+B7A0 랠 eb 9e a0 (Hangul)
您的第二行 YYZ 以下内容:从技术上正确但逻辑上非法的序列开始,因为不允许使用代理项,尤其是在未配对时(没有相应的高代理项)。 “私人使用” sequence/character 是允许的,但可疑:
U+DDB0 � ed b6 b0 (low surrogate = illegal, reserved for UTF-16)
U+1BA5 ᮥ e1 ae a5 SUNDANESE VOWEL SIGN PANYUKU
U+E7A0 ee 9e a0 (private use = highly unlikely it is used intentionally)
U+0027 ' 27 APOSTROPHE
U+002C , 2c COMMA
U+0027 ' 27 APOSTROPHE
U+0032 2 32 DIGIT TWO
U+0030 0 30 DIGIT ZERO
逻辑上这些字符也没有意义(一个希腊语,两个韩语...)。它也不适合任何 ANSI 编码:
a6
几乎总是翻译成 ¦
而我已经好几年没遇到这个字符了
af
几乎总是翻译成 ¯
,主要用于光学原因,但即便如此也很少只翻译一次
9e
很少使用,只有少数编码映射它
a0
到处都是不间断的 space,没有人能够直接输入,但可能来自从 MS Word 复制文本
从 SQL 上下文中,您可以看到所有这些字符仍在字符串文字中(请参阅撇号),其内容似乎是 HTML(请参阅尖括号)。由于这 17 个字节无法存储太多信息,只需使用十六进制编辑器并用 20
(space).
覆盖每个字节
我有一个 MySQL 转储,它不是有效的 UTF-8。两个问题:
- 这可能是某些数据库使用 utf8mb3 也就是 MySQL 的 'utf8' 造成的吗?它确实使用了这种编码。
- 如果是这样,我该如何修复它,无法访问 MySQL 来导入、更改 table 类型并重新导出?我可以使用任何编码转换工具吗?
编辑以添加无效 UTF-8 的特定数据:
uconv -f utf8 a.sql -o /dev/null
Conversion to Unicode from codepage failed at input byte position XXX. Bytes: ed Error: Illegal character found
这是一个十六进制示例。
xxd -s {XXX-16} -l 30 a.sql
YYY: 6e2e 203c 2f70 3e20 cfa1 ecaf a6eb 9ea0 n. </p> ........
aabb aabb aabb aabb aaaa bbbb bbaa aaaa
YYZ: edb6 b0e1 aea5 ee9e a027 2c27 3230 .........','20
^^^^ ^^
编辑 2:在上面添加了更多上下文。另外看起来问题序列符合UTF-8格式,它只是映射到不存在的U+1DDB0。
我使用以下方法“解决”了这个问题:
uconv --from-code utf8 --from-callback substitute --to-code utf8 a.sql -o a.sql.fixed
这只是用默认字符替换任何无效序列。 man unconv
显示其他几个选项,例如转义或删除无效序列。
在我的案例中,似乎只有极少数错误,所以我更感兴趣的是能够处理转储,而不是正确识别这些案例中发生的事情。
编辑:通过使用 --from-callback skip
我可以通过比较输入和输出文件的长度来计算无效序列的数量。
根据 UTF-8,您的第一行 YYY 包含以下字符(所有有效序列):
U+006E n 6e LATIN SMALL LETTER N
U+002E . 2e FULL STOP
U+0020 20 SPACE
U+003C < 3c LESS-THAN SIGN
U+002F / 2f SOLIDUS
U+0070 p 70 LATIN SMALL LETTER P
U+003E > 3e GREATER-THAN SIGN
U+0020 20 SPACE
U+03E1 ϡ cf a1 GREEK SMALL LETTER SAMPI
U+CBE6 쯦 ec af a6 (Hangul)
U+B7A0 랠 eb 9e a0 (Hangul)
您的第二行 YYZ 以下内容:从技术上正确但逻辑上非法的序列开始,因为不允许使用代理项,尤其是在未配对时(没有相应的高代理项)。 “私人使用” sequence/character 是允许的,但可疑:
U+DDB0 � ed b6 b0 (low surrogate = illegal, reserved for UTF-16)
U+1BA5 ᮥ e1 ae a5 SUNDANESE VOWEL SIGN PANYUKU
U+E7A0 ee 9e a0 (private use = highly unlikely it is used intentionally)
U+0027 ' 27 APOSTROPHE
U+002C , 2c COMMA
U+0027 ' 27 APOSTROPHE
U+0032 2 32 DIGIT TWO
U+0030 0 30 DIGIT ZERO
逻辑上这些字符也没有意义(一个希腊语,两个韩语...)。它也不适合任何 ANSI 编码:
a6
几乎总是翻译成¦
而我已经好几年没遇到这个字符了af
几乎总是翻译成¯
,主要用于光学原因,但即便如此也很少只翻译一次9e
很少使用,只有少数编码映射它a0
到处都是不间断的 space,没有人能够直接输入,但可能来自从 MS Word 复制文本
从 SQL 上下文中,您可以看到所有这些字符仍在字符串文字中(请参阅撇号),其内容似乎是 HTML(请参阅尖括号)。由于这 17 个字节无法存储太多信息,只需使用十六进制编辑器并用 20
(space).