如何修复UTF-8双编码XML文件

时间:2016-05-04 13:40:43

标签: xml encoding utf-8

我有一个XML文件,似乎包含双重编码的UTF-8字符。例如,然后十六进制转储中的“Gesch .... ft”部分应该是Geschäft:

00009f0: 4365 6c6c 3e3c 4861 7368 4365 6c6c 3e3c  Cell><HashCell><
0000a00: 5374 7220 7661 6c75 653d 2253 746f 7265  Str value="Store
0000a10: 735f 4d65 6e75 222f 3e3c 5374 7220 7661  s_Menu"/><Str va
0000a20: 6c75 653d 2247 6573 6368 c383 c2a4 6674  lue="Gesch....ft
0000a30: 6522 2f3e 3c2f 4861 7368 4365 6c6c 3e3c  e"/></HashCell><
0000a40: 4861 7368 4365 6c6c 3e3c 5374 7220 7661  HashCell><Str va

我找到了很多方法来修复UTF-8双编码数据库,文件名或数据流。但是我没有找到修复纯文本或XML文件的任何内容。

4 个答案:

答案 0 :(得分:0)

我想出了一种在UNIX™上实现它的方法。 Z-Shell脚本中的以下四行将是它:

#!/bin/zsh
setopt No_Err_Exit
iconv -f "UTF-8" -t "ISO-8859-1" "${1}" >"${1}.new"
mv "${1}"       "${1}.old"
mv "${1}.new"   "${1}"

答案 1 :(得分:0)

假设双重编码只会产生2字节的utf8序列(你可以添加一个检查),快速&amp;脏:

#include <stdio.h>
int main (void)
{
int state,ch;
unsigned val;

for(state = 0; ;  ) {
    ch = getc(stdin);
    if (ch==EOF) break;
    switch(state) {
    case 0:
            if ((ch & 0xe0) == 0xc0) {
                    val = (ch & 0x1f) << 6;
                    state = 1;
                    }
            else putc( ch, stdout);
            break;
    case 1:
            val |= (ch & 0x3f);
            putc(val, stdout);
            state = 0;
            break;
            }
    }
return 0;
}

这具有额外的优点,即不检查结果字节是否是有效的代码点(不需要) 结果:

$ ./a.out < gesel.in > gesel.out
$ hexdump -C gesel.in
00000000  47 65 73 65 6c c3 83 c2  a4 66 74 65 0a           |Gesel....fte.|
0000000d
$ hexdump -C gesel.out
00000000  47 65 73 65 6c c3 a4 66  74 65 0a                 |Gesel..fte.|
0000000b

答案 2 :(得分:0)

它不是双重UTF-8编码 - 它是一个UTF-8文件,已被解码为ISO-8859-1,然后以UTF-8编码保存。阿卡。变为乱码。

要在Python中解决此问题:

import io
with io.open('mojibake.xml', 'r+', encoding='utf-8') as mojibaked_input_file:
    input_baked = mojibaked_input_file.read()
    # Reverse the wrong interpretation
    input_fixed = input_baked.encode('latin1').decode('utf-8')

    mojibaked_input_file.seek(0)
    mojibaked_input_file.truncate()
    mojibaked_input_file.write(input_fixed)

答案 3 :(得分:0)

要删除双重编码,您需要将文件从UTF-8转换为第二次转换为utf8时被错误地用作源字符集的字符集。

对于德语和其他西欧语言,最好的选择是使用“ Windows-1252”或“ CP1252”。它与Latin-1相同,不同之处在于它还有更多字符,并且在尝试转换为Latin-1时会产生错误。

有几种工具可用于删除双重编码。在Mac和Linux上,默认情况下安装了iconv,因此您可以尝试

iconv -f utf8 -t cp1252 $YourFile > $NewFile

但是,如果您的文件也以BOM表(Byte order mark)开头,则可能会出现以下错误:

iconv: illegal input sequence at position 0

在这种情况下,请改用uconv,它使用相同的参数,但确实在文件开头处处理BOM:

uconv -f utf8 -t cp1252 $YourFile > $NewFile

在基于Debian的Linux发行版中,它随附

apt install icu-devtools

在Mac上,可以使用brew安装它:

brew install icu4c