-0x7E
为什么JIS编码采用同 ASCII编码一样的范围呢?原因是,现在有了很多将过去0x80
以上的byte赋予特殊意义的软件和规格。特别是过去的通信软件为了将在一方发生的error告诉给另一方,因此使用第一个bit为1的byte值
(也就是 0x80 以上的byte值)。现在在internet上发送日语的 E-mail 时,也是采用
JIS编码送信的。邮件和hotnews的规格都不允许使用 0x80以上byte,还有很多的软件不能识别0x80以上的文字。
JIS 编码如果和ASCII编码同一范围的话,ASCII编码和 JIS
编码混有的字符串如何来区分呢?通过在JIS编码中标注『从这到这是 JIS编码』的文本来区别。这个标注叫做Escape
Sequence。
Escape Sequence这个词使用在很多场合。正确的意思是『具有特殊意义的byte的连续』。用于区分JIS编码
中的全角文字与半角文字,以及通信等用来表示『数据的终结』。
Escape Sequence用 ESC (0x1B)以及和它相连的一个以上的byte表示。 JIS编码用以下这样的Escape
Sequence来区分1byte和2byte文字。
开始 ESC $ @, ESC $ B, ESC & @ ESC $ B, ESC $ ( D
终了 ESC ( J, ESC ( H, ESC ( B, ESC ( I
例如,'ABCあいう'这样的文字用 JIS编码表示,就是下图这样。通过Escape
Sequence来切换1byte和2byte文字(用秀丸编辑器的JIS编码保存)。
文本 A B C SHIFT IN あ い う SHIFT OUT
HEX 41 42 43 1B 24 42 21 22 24 24 24 26 1B 28 42
ASCII A B C ESC $ B ! ' $ $ $ & ESC ( B
使用了Escape
Sequence的JIS编码制约的必须是在行末或者文本结尾以2byte文字的模式。上面的例子就是正好在文本结束时shiftout结束。如果文本包括换行,必须在换行前shiftout。
JIS 编码的缺点也就在于使用Escape Sequence。每次1byte文字和2byte文字切换时都必须插入Escape
Sequence,所以同EUC和Shift-JIS相比,需要更多的空间。而且,如果通信等不凑巧Escape
Sequence部分乱码了,那么就会在这之后不久,所有的文字都乱码。
EUC: End User Code
EUC编码主要用于在UNIX 上使用日语。可以不用 由于使用0x80以上文字而造成各种问题的Escape Sequence,但是同时在
JIS和 Shift-JIS 定义的半角假名文字也就不可以使用了。
1999年12月23日:对于 EUC = End User Code 这个解释,有很多质疑:『不是Extended Unix Code
吗?』。我当初在哪里看到的 End User Code 这个词是什么意思啊?如果有知道End User Code
这个的请和我联系。
M Hirako 先生的质疑
我注意到一点,就是关于EUC编码,在http://www4.nikkeibp.co.jp/CSG/wordindex/EUC.htm
里有 是Extended UNIX Code 的略称的记述。
由于是对词语的定义,我想怎么都可以,但是这里有这样的记述,所以告知你。
合著 先生的质疑
EUC 编码--是 Extended Unix Code 的略称。而且EUC也可以使用半角假名。(现在有点记不清了,好像是 0X8?
的编码优先)
其他的好像没写什么,我在这里追注,「所谓的半角假名」是指定义在JIS X 0201 中的。因此,想用的话,JIS
encode也可以。
EUC也可以使用半角假名文字,是吧。谢谢你的指出。
在EUC编码,为了避免使用在 JIS编码出现问题的Escape
Sequence,分别在JIS编码文字的leaderbyte和trailerbyte增加了 0x80
来使用。(因此也被叫做建立了最上位bit的JIS、8bitJIS、EUCJIS等)。通过这个无论是在字符串的哪个位置,只要判断文字的最上位bit是0还是1就可以知道是不是日语。
EUC以在JIS和Shift-JIS可以使用的半角假名文字重复的领域来定义的
(参照页下图)。当然EUC页就不能使用半角假名文字。这个就是产生问题的原因了。也就是说有可能不能将含有半角假名文字的文本转换成
EUC。另外,由于EUC使用了 0x80 以上的byte,当然也就不能用于 E-mail。但是从制作程序的角度看,
EUC是三种编码中最容易使用的文字编码。
leaderbyte 0xA1-0xFE
trailerbyte 0xA1-0xFE
Shift-JIS
Shift-JIS 编码是 Microsoft公司开发的语言编码。可以标准地使用在日语的 MS-DOS, Windows,
Macintosh 等个人电脑,最近有很多连 UNIX也可以正常使用了。
Shift-JIS 编码是以 JIS编码为基础、使用在半角英文、制御文字、半角假名文字以外的未定义领域。因此可以不使用Escape
Sequence 也能使用半角假名文字。
Shift-JIS 编码根据byte值是否在
0x80以上来决定那个文字是否要用2byte来表示(更准确地说,是判断值是否在leaderbyte范围内)。Shift-JIS
的leaderbyte通常都在 0x80以上,在字符串中出现了这个,那么包括接下来的trailerbyte就成了2byte的文字。
当然,要注意trailerbyte没有必要一定是 0x80以上。也就是说 Shift-JIS 编码的trailerbyte中可能参有
ASCII 文字。这就使得不能取出字符串的适当位置的byte来判断它是1byte还是2byte文字。Shift-JIS
的leaderbyte和trailerbyte的值的范围如下所示。
leaderbyte 0x81-0x9F, 0xE0-0xEF, 0xF0-0xFC*
trailerbyte 0x40-0x7E, 0x80-0xFC
*: 0xF0-0xFC 是为了将来的扩展做的准备,一般不需要使用。
另外,在Shift-JIS将半角假名文字定义在 0xA0~0xDF 的范围内。也就是
Shift-JIS编码的文本中包含的byte值全部是在标准 ASCII
和leaderbyte、trailerbyte以及半角假名文字的范围内。
Shift-JIS 编码中可以混有
2byte文字和半角假名文字、ASCII文字,只是有一点点小问题。请注意trailerbyte的范围。trailerbyte的
0x40-0x7E 的范围是重叠的 (和哪些文字重叠请参考 ASCII
コ?ド)。这个范围中除了所有的字母(alphabet),还有一些应用程序中使用的特殊意义的符号,比如 @, \, | 等。
由于这个重叠,所以从看上去是Shift-JIS的文本中适当地抽出1byte,即使它是比0x80小的值,也不能断定它是2byte文字的trailerbyte还是单独的1byte文字。想断定这个就必须抽出那个的前1byte,判断它是否是leaderbyte。
你们知道反斜杠 \ (0x5C: 日语键盘显示日元符号¥)在 C/C++和 Java中有特殊的意义吧。这个文字也是和
Shift-JIS的trailerbyte的范围重叠的。例如『表』(0x955C)这个字就在trailerbyte中有反斜杠。因此不支持Shift-JIS
编码的 C语言编译器就发现了如下的结构,产生error。你们知道结果会怎样吗?
printf('コ?ド表'

;
请注意字符串 'コ?ド表'部分。这个字符串是以
\'文字终结的。也就是说编译器认为这个字符串到这里没有结束。要注意像这样把文字符号赋予特定意义进行处理的软件
(例如读出文本形式的设定文件时等)。应该检查那个带有特殊意义的符号是否没有和 Shift-JIS
的trailerbyte重叠。
文 本 ' コ ? ド 表 '
HEX 22 83 52 81 5B 83 68 95 5C 22
ASCII ' R [ h \ '
Shift-JIS
编码支持半角假名文字。当然也是具有同以往存在的半角假名文字的兼容性的意思,与以往可以利用丰富的内存和硬盘的UNIX不同,从初期的日语版个人电脑可以看得出多少有些为节约内存和磁盘容量所作的努力(完全是推测)。我想做只在
内存0KB、没有硬盘、2DD的720KB的软盘的计算机 上使用的程序,所以想尽可能地使用半角假名文字。
半角假名文字
半角假名文字用1byte表示一个文字的片假名,JIS编码和 Shift-JIS编码两者都可以用。范围,两者的编码都是在
0xA0-0xDF。只是半角假名文字的领域完全同EUC 的领域重叠(请参考页下图),所以 EUC
编码中没有叫做半角假名文字的东西。在0x21-0x7F 这个范围,表示日语的JIS当然可以,Shift-JIS
也能绕过这个领域分配文字。
半角假名文字被分配在非 ASCII 领域 (也就是 0x80
以上),这本身不是什么稀罕事。人们使用的语言因国而异。英语圈以外类似英语的语言体系(例如西班牙语)的计算机为了尽可能多的使用文字,所以分配给这个领域汉字也是当然的事。
ISO-8859-1 (Latin-1: 标准的英语圈文字设置) 也使用这个领域,使用版权标志 (:
0xA9)等。使用Macintosh 的人也许会记得,偶尔外国产的软件原封不动拿到日本用,菜单就会出现显示为『Netscape
Navigatorョ』的情况,不是吗? 大概做这个的人是想表示为『Netscape
Navigator』,但是不凑巧『』在日语的半角假名文字中相当于『ョ』
(虽然称做日语版,但是也有发生这种事情的软件)。同样地,用半角假名文字表示『メニュ?』的软件,原封不动拿到外国就变成『』了。也就是说没有定义在
ASCII中的文字你就不要奢望在国际间可以兼容了。
半角假名文字的问题在于不能用在只能使用EUC编码的环境,以及由于被分配的byte值在0x80 以上,所以只能使用0x7F以下的文字
(7bit文字) 的软件或规格就不能使用。特别是在网络上不能使用。由于网络上的通信规格大多是只允许使用 7
bit文字,而且很多人的环境只能使用 EUC (特别是
UNIX),因此不能使用半角假名文字(有些规定不是作为manner、而是作为禁止事项提出的)。
我认为只要是不给别人添麻烦就可以使用半角假名文字。只是现在很少有人用它了,原来由MS-DOS一手培养起来的我,非常喜欢使用被压缩的半角假名文字。尽管这样,还是不要在网络上使用比较好。明确点说就是如果你看见了使用半角假名文字的主页,你就认为它是『外行做的』吧。以前也不是这样,最近用word
processor的感觉制作主页的人越来越多,所以也就会经常看见。这个网页也是把所有的半角假名文字替换成全角假名文字了。
半角假名文字 0xA1-0xDF
由于日语处理产生的问题
用计算机处理日语会发生各种各样的问题。最主要的就是迫使
『用1byte表示一个文字的计算机』来处理用2byte表示的一个文字,所以当然就产生了问题。最大的问题是存在若干种编码,不可能让每一个都完美到没有问题发生。每种编码都有优点和缺点。一种日语编码可能什么问题都不会有,但是一旦加入了其他编码的文件,就有可能发生error。
由于Escape Sequence产生的问题
使用Escape Sequence进行shiftin/shiftout的
JIS编码,由于其副作用会发生各种各样的问题。首先,由于文本内的嵌入Escape
Sequence,而将文本作为byte排列处理时,就出现了文字间隙。shiftin/shiftout进行得越频繁间隙就越多,就会耗费很多不必要的内存。不仅如此,比如用户输入了『ABCの列』这样7byte的文本。但是无论程序再怎么识别出是7byte,由于不得不附加Escape
Sequence,因此还是不能知道实际上用JIS编码来表示时需要几byte的领域。这个在读出文本文件时,或者从其他编码转换到JIS编码时也会发生。
对于JIS编码来说,Escape Sequence具有着非常重要的意义。因此Escape
Sequence部分的乱码就会导致那之后接下来的文本产生致命的结果 (大概不一会就会出现意义不明的符号串)。在EUC 和
Shift-JIS ,文字本身使用2byte表示的,所以受到乱码的影响的最多就是它后面紧接着的一个文字。
由于半角假名文字产生的问题
JIS 和 Shift-JIS 编码可以使用半角假名文字。但是
EUC编码不可以使用半角假名文字。也就是说不能将含有半角假名文字的文本原封不动转换到EUC。可以将半角假名文字全部转换成全角假名文字,当然有的允许这样做,有的不允许这样做。如果文本的byte数是固定的,不经意地转换到全角后,byte数就会超出。
有从JDK 1.1 变换 JIS, Shift-JIS, EUC 文字set到 UNICODE这样一个便利的功能,JDK 1.1 的
UNICODE变换功能也和 EUC一样不能处理半角假名文字。
另外,文本中含有半角假名文字的话,日语编码的自动识别动作进行的不顺利。这个是由于半角假名文字的全领域和EUC的领域重叠。设想是半角假名文字,进行日语编码的自动识别时,可以用于判断的领域就会大大减少。
由于8bit文字产生的问题
EUC 和 Shift-JIS 编码在文本中具有byte值在 0x80 以上的 8
bit文字。特别是在海外制作的软件和规格很多都注明不能使用 0x80 以上的文本。而且其中也有一些将 8
bit文字的最上位bit删除了。想在这样的系统上安全地转送数据,就请使用 JIS 编码。
在E-mail中为了防止这个,就必须用 JIS 编码发送,但是即使是使用同一internet,也不是说主页一定要用JIS
。参考HTTP 的 RFC就明白了,原本 HTTP是按照也可以使用标准的ASCII文字以外的文字set设计的。也就是说,无论选择
JIS还是 Shift-JIS 还是 EUC都可以。
从先前说的Escape Sequence乱码问题,我认为个人制作主页使用JIS还是不太好。在Shift-JIS 和 EUC
只乱码几个字的东西,使用JIS,就变得整个段落都是看不明白的文字。
由于2byte分割产生的问题
JIS, Shift-JIS, EUC
的任意一个都是使用2byte表示一个文字。这个是不能分开使用的,每一半都不具有实际意义。因此分割字符串时,先确认是否将2byte文字分割开了。特别是不能忘了在
Shift-JIS编码中,在trailerbyte可能含有ASCII文字。在制作通过某个文字区分两个字符串处理的程序时要特别注意。
也有的处理方式在向画面等输出文字时,将2byte文字分割了,而不能很好地处理。用Microsoft Visual C++
想将含有日语的字符串一个byte一个byte地输出时,中途出现error而终了。
和ASCII 编码的重码
JIS 和 Shift-JIS在表示日语编码的byte中使用 ASCII 编码的领域。这个在解析文本时会出现问题。特别是
JIS编码中包含 ASCII 文字所有的非空白文字。例如有将# (0x23)之后的行作为注释 (在UNIX 和 Java经常会有)
的文件。而且 JIS文字『横』(0x3223) 在trailerbyte中有这个文字。所以想在JIS编码进行如下设定时,
button.side = 横に移? # 横向移动按钮的名字
不识别JIS 的软件就会将『横に移?』这个日语解释成下面这个样子,button.side值设定为 ESC$B2 。
文本 SHIFT IN 横 に 移 ? SHIFT OUT
HEX 1B 24 42 32 23 24 4B 30 5C 46 30 1B 28 42
ASCII ESC $ B 2 # $ K 0 \ F 0 ESC ( B
当然像这样的问题在 trailerbyte中可能含有ASCII文字的Shift-JIS编码 也有。这样的问题在使用
strchr()函数等进行文字检索时也会发生。如果使用 strchr() 从上述字符串检索
'$',就会检索出本来没有的东西。要注意,C/C++ 标准的字符串处理库 ( 以及其他语言的许多的字符串处理库)
会不把byte排列作为日语来处理。也许 JIS编码和 Shift-JIS编码也不能识别这个。
和其他编码的重码
Shift-JIS 编码和 EUC编码具有相同的领域。这个在进行文字编码的自动识别时会产生问题。例如,对应 0x967B这个值的文字在
Shift-JIS编码是『? (しゃち)』,在EUC是で『虱 (しらみ)』。无论哪一个都是正确的日语编码,所以不能判别只指定了
0xE9CD
的文本的文字编码。像这样的文字还有一些。文本只要可以判定是那种编码就可以进行变换,但是像这样不能判定文本编码的情况就比较困难了。
程序说明
在进行程序说明之前有一个需要注意的地方。那就是虽然已经基于C/C++表现出了日语,但使用什么形式为好呢(使用Java的人也请看看)?如果是通常的方法,就是使用
char 型,但最终这样好吗?
并不是“因为是用2个byte来表示一个文字的,因此应该是 2 byte整数的 short ”的意思。这是说,没有明确定义是给 ANSI
加上char 符号处理还是作为没有符号处理一事,和关于整数型的内在的变换一事。例如,请看如下的编码。
char ch = 0xA0;
if(ch == 0xA0) printf('bingo!');
一瞥的话,看上去这个肯定是 bingo! 显示的,但未必是这样。请好好想想。ch 中代入了 0xA0,ch 显示值是 -32
。并且在数值的比较上,int 型的整数值 0xA0,也就是和 160 进行比较。ANSI 并未对只是声明了是char
的文字型是否加上了符号进行定义。可能能通过编译器的设定以及编译器选项能够进行切换,因此说“未必是这样”。
为了避免这样的故障,如果用char型来处理日语的话,一定是在作为 unsigned char
声明的基础上使用为上策。请注意,所说的处理8 bit文字,是处理 符号bit的标准 值。
实际问题是在评价一个文字时是作为 unsigned char 处理,还是作为 unsigned short
处理,意见就分歧了。确实是用 2 byte来表示一个文字,所以可能是使用 2 byte整数值 unsigned short
为好,但结果会变成必须分为Leader byte和trailer byte来进行评价。选择哪个,就看你的喜好了。
Java 下的data型 byte 是绝对带着符号的。因此,必须执行使用short 型等合适的处置。
编码变换
在编码变换上要注意的只是,基于EUC 的半角假名文字的处理和基于 JIS 编码的Escape
Sequence。角假名文字的怎么处理说的是,将其变换为全角假名文字还是向用户显示为error。在此,为了简单,就作为半角假名文字不存在。
JIS 编码的Escape Sequence的处理有很多种,因此有些麻烦。生成JIS 编码的文本时,使用任何一个都行,但由JIS
变换时,有好几种,都要对应。下面显示的例子是 使用unsigned short 型 (Leader byte是high byte )
单纯地进行一个文字(2byte)的变换。
EUC - JIS
EUC 和 JIS 文字的变换是非常单纯的。仅仅使Leader byte和trailer byte的high byte
成为1或0就完成了。
unsigned short euc2jis(unsigned short ch){
return ch & 0x7F7F;
}
unsigned short jis2euc(unsigned short ch){
return ch | 0x8080;
}
Shift-JIS - JIS
为了使Shift-JIS 很好地避免半角假名文字而进行分配,Shift-JIS 和 JIS 之间的变换就稍复杂了。
※参考了SOFTBANK 新C语言入门应用篇。sjis2jis() 的 if(leader>0x9F)
leader+=0x40;
的部分中,是这样写的,但在文章中写的是“如果HIGH是9Fh以上的话,则HIGHT+40h”。还未确认哪个是正确的。
fcat@geocities.co.jp 先生的感谢:
在中途,有就从日语的Shift-JIS变换为JIS而写的部分,SOFT BANK的《新C语言入门》中写的
若是HIGHが9Fh以上的话・・・ 编码中
leader>0x9F) leader+=0x40;
书上是这么写的,写着未确认哪个是正确的,编码正确的话,“以上”就是“更大的”错误。
也能参考技术评论社的运算法则事典。虽说是有些难懂,但我想,可能只有这个快些。
unsigned short sjis2jis(unsigned short ch){
unsigned char leader = (ch >> 8);
unsigned char trailer = (ch & 0xFF);
if(leader <= 0x9F) leader -= 0x71;
else leader -= 0xB1;
leader = (leader << 1) + 1;
if(trailer > 0x7F) trailer --;
if(trailer >= 0x9E){
trailer -= 0x7D;
leader ++;
} eles {
trailer -= 0x1F;
}
return (leader << 8) | trailer;
}
unsigned short jis2sjis(unsigned short ch){
unsigned char leader = (ch >> 8);
unsigned char trailer = (ch & 0xFF);
if((leader & 0x01) != 0) trailer += 0x1F;
else trailer += 0x7D;
if(trailer >= 0x7F) trailer ++;
leader = ((leader - 0x21) >> 1) + 0x81;
if(reader > 0x9F) leader += 0x40;
return (leader << 8) | trailer;
}
Shift-JIS - EUC
Shift-JIS 和 EUC 之间的变换,请把上面的两个函数单纯底组合起来。
unsigned short sjis2euc(unsigned short ch){
return jis2euc(sjis2jis(ch));
// or
(sjis2jis(ch) | 0x8080)
}
unsigned short euc2sjis(unsigned short ch){
return jis2sjis(euc2jis(ch));
// or
jis2sjis(ch & 0x7F7F)
}
半角假名文字 - 全角假名文字
由于从JIS 以及 Shift-JIS 变换为 EUC
时的半角-全角假名文字变换也不能用单纯的加减演算来处理,因此是要动脑的。甚至于带着浊音的文字是用“カ?”,还是用“ガ”?逗号是用“,”,还是用“、”?这就有喜好上的分歧了。关于如何map,请参照这里的文件。
Java 文字编码变更功能
在JDK 1.1 中,为变换日语编码,对String class进行扩展。由于UNICODE
对应世界上各种各样的文字,因此,并非只是进行日语的扩展。通过指定能够识别文字编码的文字能把各种各样的文字变换为 UNICODE
,也能进行相反的变换。使用日语编码时需要的字符串如下。
ISO-8859-1 (Latin-1) JIS Shift-JIS EUC
'8859_1' 'JIS' 'SJIS' 'EUCJIS'
由byte排列来制作字符串class时,使用平台的默认文字编码。在Windows上,自动使用“SJIS”,在使用EUC的UNIX上使用“EUCJIS”。此时,要注意,在自动判断文字编码的基础上不是使用适当的编码。
byte[] buffer;
....
String content = new String(buffer);
默认文字编码在 Reader class读出数据时以及Writer
class写入数据时使用。也就是说,几乎不需要意识到平台所使用的文字编码。这个值通过调查系统属性的 file.encoding
的值的方式
(通过System.getProperty('file.encoding')能够取得),就能知道是把什么样的文字编码作为缺省使用的。
但是,有时还想自己指定byte排列的文字编码。此时,如果在字符串class的结构上接着byte排列指定文字编码的话,进行适当的变换后,生成
UNICODE 字符串。例如,下面的例子是byte排列 buffer 的内容被认为是 EUC 编码,然后生成 UNICODE
字符串。
byte[] buffer;
....
String content = new String(buffer, 'EUCJIS');
那么,从 UNICODE 字符串中取得适当文字编码的byte排列,怎样做好呢?这个就用字符串class的 getBytes()
方法进行。使用这个方法后,通过 UNICODE 能将某个文字编码变换为其它的文字编码。在下面的例子中,由EUC
文字编码的byte排列生成字符串class,然后取得 JIS 编码的byte排列。省略getBytes()
的函数后,就用默认的文字编码生成byte排列。
byte[] buffer;
....
String content = new String(buffer, 'EUCJIS');
byte[] jiscode = content.getBytes('JIS');
请注意,Java 编准的这个功能不正常处理半角假名文字 (JDK 1.1.5) 。半角假名文字没有定义在 UNICODE
中。包含半角假名文字的文本用这些方法变换时,其文字部分将被置换成其他文字(大概 '?')。
要注意,使用JDBC 读出的数据区文字都是作为 '8859_1' 变换。这些,需要在变换为 '8859_1'
的byte排列后再次变换为适当的字符串。
ResultSet resultset;
....
String data = resultset.getString('some string');
byte[] binary = data.getBytes('8859_1');
data = new String(binary);
编码自动识别
不知道文本的文字编码时,应用程序可能要求独自识别编码。特别是制作在互联网上使用的应用程序后,经常根本就不知道文本使用什么样的文字编码。下图显示的是各自的文字编码区域。如果能用JavaScript
的话,请点击适当的位置看。
第1个byte
第2
个
byte
Code Area:
Encoding:
看上面的图就明白了,EUC
文字编码区域的一半以上是和半角假名文字区域重复的。因此,加上“不使用半角假名文字”的条件,则猛烈增加自动识别的精确度。
被认为是日语文字编码的自动识别的编码是 ASCII 编码、JIS 编码、EUC 编码、Shift-JIS 编码,还有Binary
编码。如果进行严密的判断的话,在进行文字编码的判断后,需要对照其编码是否正确。如果对照失败,就被认为是不正确的文字编码而作为Binary编码处理,或被作为乱码编码处理。
第一阶段: JIS 和其他编码的判断
首先,对和其他编码最容易区别的 JIS 进行考虑。如果在文本中出现了Escape Sequence的话,就能够判断它们或许是 JIS
编码。更单纯的判断是,由于在Shift-JIS 的 Trailer byte 的范围中不包含 ESC,因此,通过在文本是否出现ESC
(0x1B) 来判断。下图显示的是第一阶段的流程图。
如果假定文本中没有半角假名文字存在的话,就省略0xA0<ch<0xE0 的判断,改为 EUC &
Shift-JIS 的判断。
按照这个流程表,就是以是否出现 ESC 编码来进行的判断。如果想进行更加严密的判断,则在断定其是JIS
编码后,需要对照其是否是正确的JIS 编码的文本。恐怕 ESC 可能是最初出现的二进制码编码。
第二阶段: EUC 和 Shift-JIS 的判断
如果在第一阶段发现了 0x80 以上的文字的话,就可能是 Shift-JIS 或 EUC 。判断Shift-JIS 和
EUC,必须参照两个文字编码的范围来查找是在哪个范围内哪个范围外的文字。但是,如前面所说,由于存在着既被认为是Shift-JIS
又被认为是 EUC 的文字,如果不巧文本只是由那样的文字构成的话,就不用做判断了。此时,就需要准确决定哪个文字编码优先了。
在此,对 Shift-JIS 和 EUC 的重复区域稍做总结。能确实判断是Shift-JIS、 EUC
的范围如下。看表就明白了,如果是自动识别含有半角假名文字的文本的话,几乎就没有能被断定是EUC 的区域。
CODE Leader Byte Trailer Byte
Shift-JIS 0x81-0x9F 0x40-0x7E, 0x80-0xA0
EUC 0xF0-0xFE, 0xA1-0xDF* 0xFD-0xFE
*: 不存在半角假名文字时所包含的
可能是包含着半角假名文字的文本时,则相反,就也能使用存在的半角假名文字。作为Leader
byte取出的byte值如果是半角假名文字区域的话,如果其为 EUC 文本的话,接下来的一定是 EUC Trailer
byte。也就是说,接下来的byte值如果是 EUC Trailer byte范围外的话,就能被认为是包含半角假名文字的
Shift-JIS 。如果将条件更加严密化,就是说“接下来的文字是 0x7F 以下或 EUC Trailer byte范围外的
Shift-JIS 的Leader byte(0x81-0x9F) 的话”。
CODE Current Byte Next Byte
Shift-JIS with Kana 0xA1-0xDF 0x00-0x7F, 0x81-0x9F
基于上述,制作了判断Shift-JIS 和 EUC
编码的流程图。按照如下的顺序处理即可。在这个图中假定可能包含半角假名文字。如果知道没有包含半角假名文字的话,就请省略ch=Kana
的判断,换成ch=EUC1 の判定を ch=EUC1 or ch=Kana 。
如果假设是Binary编码的话,就判断移动到接下来的文字 next 之前的文字是否是 Shift-JIS 和 EUC
的重复区域。下面显示 Shift-JIS 和 EUC 的重复区域。如果文字在此区域范围外的话,就被认作是Binary编码。
CODE Leader Byte Trailer Byte
Shift-JIS or EUC 0xE0-0xEF, 0xA1-0xDF* 0xA1-0xFC
*: 存在半角假名文字时所包含的
第三阶段: 文字编码的推测
在第二阶段被认为是不能判断的文本中,由于只存在相同数目的 EUC 文字和Shift-JIS
文字,因此已经不能由程序进行决定性的判断了。此时,就决定执行程序的环境和用户设定哪个优先。例如,若程序是在 Windows
上执行的话,则文本是 Shift-JIS 的可能性较高。
虽然我想,由于基本不使用JIS
第二标准文字,所以,评价一下双方的文字编码后,就能根据此文字出现次数来进行推测,但没有这样做。重复区域是0xE0A1
以上的文字,JIS 第二标准是 Shift-JIS: 0x9873, EUC: 0xCFD4
以上。也就是说,重复区域不管按照任何一方评价都是 JIS
第二标准文字了。注意到这点,是在制作完确认能推测到何种程度的程序之后。
以上是从文本的开始进行评价,根据最初判断为可能存在的文字来进行评价的方法。此外,总结能够看成是各自的文字编码的出现次数,哪个编码是最适合的推测方法也可考虑。这是在判断乱码可能性高的文本时被考虑的。