【问题标题】:Is it guaranteed that trailing bytes in mbcs encodings are in specific range?是否保证 mbcs 编码中的尾随字节在特定范围内?
【发布时间】:2019-07-30 19:35:36
【问题描述】:

我需要读取包含任意 MBCS 编码字符串的文本文件。文件格式(简化)如下:

CODEPAGE "STRING"
CODEPAGE STRING
...

其中 CODEPAGE 可以是任何 MBCS 代码页:UTF-8、cp1251(西里尔文)、cp932(日语)等。

我无法在一次调用 MultiByteToWideChar 时解码整个文件。我需要提取引号之间的字符串,或者直到空格或回车并在提取的字符串上调用 MultiByteToWideChar。

但在 MBCS(多字节编码方案)中,一个字符可以用多个字节表示。如果我想在多字节编码文件中查找拉丁语“A”,我不能只搜索代码 65,因为 65 可能是某些编码序列中的尾随字节。

所以我不确定是否允许在 MBCS 字符串中搜索 '"' 或空格或 CR。我浏览了几个代码页(例如中文 936 代码页:https://ssl.icu-project.org/icu-bin/convexp?conv=windows-936-2000&s=ALL),据我所知尾随字节从 0x40 开始,因此扫描文件中的标点符号是安全的。但是对于任何代码页,是否有一些保证?

【问题讨论】:

    标签: unicode mbcs


    【解决方案1】:

    分析哪些八位位组可以出现在编码的八位位组序列中,丢弃前导。结果是 0x40..0x7E, 0x80..0xFE。

    #!/usr/bin/env perl
    use Encode qw(encode);
    my @encodings = qw(
        cp1006 cp1026 cp1047 cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256
        cp1257 cp1258 cp37 cp424 cp437 cp500 cp737 cp775 cp850 cp852 cp855 cp856
        cp857 cp858 cp860 cp861 cp862 cp863 cp864 cp865 cp866 cp869 cp874 cp875
        cp932 cp936 cp949 cp950
    );
    my %continuation_octets;
    for my $e (@encodings) {
        for my $c (0..0x10_ffff) {
            my $encoded = encode $e, chr($c), sub { -1 };
            if ($encoded ne -1 && length($encoded) > 1) {
                my @octets = split //, $encoded;
                shift @octets;
                $continuation_octets{$_}++ for @octets;
            }
        }
    }
    

    【讨论】:

    • 谢谢!但不幸的是,这并不能回答我的问题。我想要的是扫描八位字节序列中的空格、引号或 CR,并确保我不会遇到这些字符作为编码符号的一部分。我绝对知道我不能为“A”字符做这件事,因为代码 65 可以是其他字符的一部分。但我不确定标点符号是否如此。我也可以忽略所有不直接将 asciii-7 字符映射到自身的代码页。我只受代码页的限制,这些代码页可以在 Windows 中为非 unicode 程序设置为默认代码页。谢谢你的脚本!
    • 超级!谢谢!我绝对应该记得 Perl :-) 好消息是可以在任何列出的代码页中扫描序列以查找 cr、空格或引号。虽然很遗憾 "\" 不安全:%continuation_octets = ( "\@" => 307, "[" => 308, "\\" => 305, "]" => 309, "^" => 302, "`" => 307, "{" => 302, "|" => 308, "}" => 306, "~" => 304, "\200" => 177, ....
    猜你喜欢
    • 1970-01-01
    • 2020-01-30
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多