0

我需要读取包含任意 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 开始,因此扫描文件中的标点符号是安全的。但是对于任何代码页,是否有一些保证?

4

1 回答 1

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;
        }
    }
}
于 2019-07-31T08:30:46.967 回答