Codepage的定义和历史
Codepage的定義和歷史
?作者Blog:http://blog.csdn.net/fmddlmyy/
1. Codepage的定義和歷史
字符內碼(charcter code)指的是用來代表字符的內碼.讀者在輸入和存儲文檔時都要使用內碼,內碼分為
- 單字節內碼 -- Single-Byte character sets (SBCS),可以支持256個字符編碼.
- 雙字節內碼 -- Double-Byte character sets)(DBCS),可以支持65000個字符編碼.主要用來對大字符集的東方文字進行編碼.
codepage 指的是一個經過挑選的以特定順序排列的字符內碼列表,對于早期的單字節內碼的語種,codepage中的內碼順序使得系統可以按照此列表來根據鍵盤的輸入值給出一個對應的內碼.對于雙字節內碼,則給出的是MultiByte到Unicode的對應表,這樣就可以把以Unicode形式存放的字符轉化為相應的字符內碼,或者反之,在Linux核心中對應的函數就是utf8_mbtowc和utf8_wctomb.
在1980年前,仍然沒有任何國際標準如ISO-8859或Unicode來定義如何擴展US-ASCII編碼以便非英語國家的用戶使用.很多IT 廠商發明了他們自己的編碼,并且使用了難以記憶的數目來標識:
?
?
例如936代表簡體中文. 950代表繁體中文.
?
?
1.1 CJK Codepage
同 Extended Unix Coding ( EUC )編碼大不一樣的是,下面所有的遠東 codepage 都利用了C1控制碼 { =80..=9F } 做為首字節, 使用ASCII值 { =40..=7E { 做為第二字節,這樣才能包含多達數萬個雙字節字符,這表明在這種編碼之中小于3F的ASCII值不一定代表ASCII字符.
CP932
Shift-JIS包含日本語 charset JIS X 0201 (每個字符一個字節) 和 JIS X 0208 (每個字符兩個字節),所以 JIS X 0201平假名包含一個字節半寬的字符,其剩馀的60個字節被用做7076個漢字以及648個其他全寬字符的首字節.同EUC-JP編碼區別的是, Shift-JIS沒有包含JIS X 202中定義的5802個漢字.
CP936
GBK 擴展了 EUC-CN 編碼( GB 2312-80編碼,包含 6763 個漢字)到Unicode (GB13000.1-93)中定義的20902個漢字,中國大陸使用的是簡體中文zh_CN.
CP949
UnifiedHangul (UHC) 是韓文 EUC-KR 編碼(KS C 5601-1992 編碼,包括2350 韓文音節和 4888 個漢字a)的超集,包含 8822個附加的韓文音節( 在C1中 )
CP950
是代替EUC-TW (CNS 11643-1992)的 Big5 編碼(13072 繁體 zh_TW 中文字) 繁體中文,這些定義都在Ken Lunde的 CJK.INF中或者 Unicode 編碼表中找到.
注意: Microsoft采用以上四種Codepage,因此要訪問Microsoft的文件系統時必需采用上面的Codepage .
?
1.2 IBM的遠東語言Codepage
IBM的Codepage分為SBCS和DBCS兩種:
IBM SBCS Codepage
?
- 37 (英文) *
- 290 (日文) *
- 833 (韓文) *
- 836 (簡體中文) *
- 891 (韓文)
- 897 (日文)
- 903 (簡體中文)
- 904 (繁體中文)
IBM DBCS Codepage
- 300 (日文) *
- 301 (日文)
- 834 (韓文) *
- 835 (繁體中文) *
- 837 (簡體中文) *
- 926 (韓文)
- 927 (繁體中文)
- 928 (簡體中文)
將SBCS的Codepage和DBCS的Codepage混合起來就成為: IBM MBCS Codepage
- 930 (日文) (Codepage 300 加 290) *
- 932 (日文) (Codepage 301 加 897)
- 933 (韓文) (Codepage 834 加 833) *
- 934 (韓文) (Codepage 926 加 891)
- 938 (繁體中文) (Codepage 927 加 904)
- 936 (簡體中文) (Codepage 928 加 903)
- 5031 (簡體中文) (Codepage 837 加 836) *
- 5033 (繁體中文) (Codepage 835 加 37) *
*代表采用EBCDIC編碼格式
由此可見,Mircosoft的CJK Codepage來源于IBM的Codepage.
2. Linux下Codepage的作用
在Linux下引入對Codepage的支持主要是為了訪問FAT/VFAT/FAT32/NTFS/NCPFS等文件系統下的多語種文件名的問題,目前在NTFS和FAT32/VFAT下的文件系統上都使用了Unicode,這就需要系統在讀取這些文件名時動態將其轉換為相應的語言編碼.因此引入了NLS支持.其相應的程序文件在/usr/src/linux/fs/nls下:
?
- Config.in
- Makefile
- nls_base.c
- nls_cp437.c
- nls_cp737.c
- nls_cp775.c
- nls_cp850.c
- nls_cp852.c
- nls_cp855.c
- nls_cp857.c
- nls_cp860.c
- nls_cp861.c
- nls_cp862.c
- nls_cp863.c
- nls_cp864.c
- nls_cp865.c
- nls_cp866.c
- nls_cp869.c
- nls_cp874.c
- nls_cp936.c
- nls_cp950.c
- nls_iso8859-1.c
- nls_iso8859-15.c
- nls_iso8859-2.c
- nls_iso8859-3.c
- nls_iso8859-4.c
- nls_iso8859-5.c
- nls_iso8859-6.c
- nls_iso8859-7.c
- nls_iso8859-8.c
- nls_iso8859-9.c
- nls_koi8-r.c
實現了下列函數:
- extern int utf8_mbtowc(__u16 *, const __u8 *, int);
- extern int utf8_mbstowcs(__u16 *, const __u8 *, int);
- extern int utf8_wctomb(__u8 *, __u16, int);
- extern int utf8_wcstombs(__u8 *, const __u16 *, int);
?
這樣在加載相應的文件系統時就可以用下面的參數來設置Codepage:
對于Codepage 437 來說
mount -t vfat /dev/hda1 /mnt/1 -o codepage=437,iocharset=cp437
?
這樣在Linux下就可以正常訪問不同語種的長文件名了.
3. Linux下支持的Codepage
?
?
- nls codepage 437 -- 美國/加拿大英語
?
- nls codepage 737 -- 希臘語
?
- nls codepage 775 -- 波羅的海語
?
- nls codepage 850 -- 包括西歐語種(德語,西班牙語,意大利語)中的一些字符
?
- nls codepage 852 -- Latin 2 包括中東歐語種(阿爾巴尼亞語,克羅地亞語,捷克語,英語,芬蘭語,匈牙利語,愛爾蘭語,德語,波蘭語,羅馬利亞語,塞爾維亞語,斯洛伐克語,斯洛文尼亞語,Sorbian語)
?
- nls codepage 855 -- 斯拉夫語
?
- nls codepage 857 -- 土耳其語
?
- nls codepage 860 -- 葡萄牙語
?
- nls codepage 861 -- 冰島語
?
- nls codepage 862 -- 希伯來語
?
- nls codepage 863 -- 加拿大語
?
- nls codepage 864 -- 阿拉伯語
?
- nls codepage 865 -- 日爾曼語系
?
- nls codepage 866 -- 斯拉夫語/俄語
?
- nls codepage 869 -- 希臘語(2)
?
- nls codepage 874 -- 泰語
?
- nls codepage 936 -- 簡體中文GBK
?
- nls codepage 950 -- 繁體中文Big5
?
- nls iso8859-1 -- 西歐語系(阿爾巴尼亞語,西班牙加泰羅尼亞語,丹麥語,荷蘭語,英語,Faeroese語,芬蘭語,法語,德語,加里西亞語,愛爾蘭語,冰島語,意大利語,挪威語,葡萄牙語,瑞士語.)這同時適用于美國英語.
?
- nls iso8859-2 -- Latin 2 字符集,斯拉夫/中歐語系(捷克語,德語,匈牙利語,波蘭語,羅馬尼亞語,克羅地亞語,斯洛伐克語,斯洛文尼亞語)
?
- nls iso8859-3 -- Latin 3 字符集, (世界語,加里西亞語,馬耳他語,土耳其語)
?
- nls iso8859-4 -- Latin 4 字符集, (愛莎尼亞語,拉脫維亞語,立陶宛語),是Latin 6 字符集的前序標準
?
- nls iso8859-5 -- 斯拉夫語系(保加利亞語,Byelorussian語,馬其頓語,俄語,塞爾維亞語,烏克蘭語) 一般推薦使用 KOI8-R codepage
?
- nls iso8859-6 -- 阿拉伯語.
?
- nls iso8859-7 -- 現代希臘語
?
- nls iso8859-8 -- 希伯來語
?
- nls iso8859-9 -- Latin 5 字符集, (去掉了 Latin 1中不經常使用的一些冰島語字符而代以土耳其語字符)
?
- nls iso8859-10 -- Latin 6 字符集, (因紐特(格陵蘭)語,薩摩斯島語等Latin 4 中沒有包括的北歐語種)
?
- nls iso8859-15 -- Latin 9 字符集, 是Latin 1字符集的更新版本,去掉一些不常用的字符,增加了對愛莎尼亞語的支持,修正了法語和芬蘭語部份,增加了歐元字符)
?
- nls koi8-r -- 俄語的缺省支持
4. 簡體中文GBK/繁體中文Big5的Codepage
如何制作簡體中文GBK/繁體中文Big5的Codepage?
?
- 從 Unicode 組織取得GBK/Big5的Unicode的定義.
由于GBK是基于ISO 10646-1:1993標準的,而相應的日文是JIS X 0221-1995,韓文是KS C 5700-1995,他們被提交到Unicode標準的時間表為:
Unicode Version 1.0
Unicode Version 1.1 <-> ISO 10646-1:1993, JIS X 0221-1995, GB 13000.1-93
Unicode Version 2.0 <-> KS C 5700-1995從Windows 95開始均采用GBK編碼. 您需要的是 CP936.TXT和 BIG5.TXT
- 然后使用下面的程序就可以將其轉化為Linux核心需要的Unicode<->GBK碼表
./genmap BIG5.txt | perl uni2big5.pl
./genmap CP936.txt | perl uni2gbk.pl - 再修改fat/vfat/ntfs的相關函數就可以完成對核心的修改工作. 具體使用時可以使用下面的命令:
- 簡體中文: mount -t vfat /dev/hda1 /mnt/1 -o codepage=936,iocharset=cp936
- 繁體中文: mount -t vfat /dev/hda1 /mnt/1 -o codepage=950,iocharset=cp936
有趣的是,由于GBK包含了全部的GB2312/Big5/JIS的內碼,所以使用936的Codepage也可以顯示Big5的文件名.
5. 附錄
?
5.1 作者和相關文檔
制作codepage950支持的是臺灣的 cosmos先生, 主頁為 http://www.cis.nctu.edu.tw:8080/~is84086/Project/kernel_cp950/
制作GBK的cp936支持的是TurboLinux的中文研發小組的 方漢和 陳向陽
5.2 genmap
?
#!/bin/sh
cat $1 | awk '{if(index($1,"#")==0)print $0}' | awk 'BEGIN{FS="0x"}{print $2 $3}' | awk '{if(length($1)==length($2))print $1,$2}'
?
5.3 uni2big5.pl
?
?
#!/usr/bin/perl
@code = (
"00", "01", "02", "03", "04", "05", "06", "07",
"08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"10", "11", "12", "13", "14", "15", "16", "17",
"18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"20", "21", "22", "23", "24", "25", "26", "27",
"28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"30", "31", "32", "33", "34", "35", "36", "37",
"38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"40", "41", "42", "43", "44", "45", "46", "47",
"48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"50", "51", "52", "53", "54", "55", "56", "57",
"58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"60", "61", "62", "63", "64", "65", "66", "67",
"68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"70", "71", "72", "73", "74", "75", "76", "77",
"78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87",
"88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97",
"98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
"A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7",
"B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7",
"C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7",
"E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7",
"F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF");
while (<STDIN>){
($unicode, $big5) = split;
($high, $low) = $unicode =~ /(..)(..)/;
$table2{$high}{$low} = $big5;
($high, $low) = $big5 =~ /(..)(..)/;
$table{$high}{$low} = $unicode;
}
print <<EOF;
/*
* linux/fs/nls_cp874.c
*
* Charset cp874 translation tables.
* Generated automatically from the Unicode and charset
* tables from the Unicode Organization (www.unicode.org).
* The Unicode to charset table has only exact mappings.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/nls.h>
/* A1 - F9*/
static struct nls_unicode charset2uni[(0xF9-0xA1+1)*(0x100-0x60)] = {
EOF
for ($high=0xA1; $high <= 0xF9; $high++){
for ($low=0x40; $low <= 0x7F; $low++){
$unicode = $table2{$code[$high]}{$code[$low]};
$unicode = "0000" if (!(defined $unicode));
print "/n/t" if ($low%4 == 0);
print "/* $code[$high]$code[$low]*//n/t" if ($low%0x10 == 0);
($uhigh, $ulow) = $unicode =~ /(..)(..)/;
printf("{0x%2s, 0x%2s}, ", $ulow, $uhigh);
}
for ($low=0xA0; $low <= 0xFF; $low++){
$unicode = $table2{$code[$high]}{$code[$low]};
$unicode = "0000" if (!(defined $unicode));
print "/n/t" if ($low%4 == 0);
print "/* $code[$high]$code[$low]*//n/t" if ($low%0x10 == 0);
($uhigh, $ulow) = $unicode =~ /(..)(..)/;
printf("{0x%2s, 0x%2s}, ", $ulow, $uhigh);
}
}
print "/n};/n/n";
for ($high=1; $high <= 255;$high++){
if (defined $table{$code[$high]}){
print "static unsigned char page$code[$high]/[512/] = {/n/t";
for ($low=0; $low<=255;$low++){
$big5 = $table{$code[$high]}{$code[$low]};
$big5 = "3F3F" if (!(defined $big5));
if ($low > 0 && $low%4 == 0){
printf("/* 0x%02X-0x%02X *//n/t", $low-4, $low-1);
}
print "/n/t" if ($low == 0x80);
($bhigh, $blow) = $big5 =~ /(..)(..)/;
printf("0x%2s, 0x%2s, ", $bhigh, $blow);
}
print "/* 0xFC-0xFF *//n};/n/n";
}
}
print "static unsigned char *page_uni2charset[256] = {";
for ($high=0; $high<=255;$high++){
print "/n/t" if ($high%8 == 0);
if ($high>0 && defined $table{$code[$high]}){
print "page$code[$high], ";
}
else{
print "NULL, ";
}
}
print <<EOF;
};
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
0x98, 0x99, 0x9a, 0x00, 0x9c, 0x00, 0x00, 0x00, /* 0x98-0x9f */
0x00, 0x00, 0x00, 0x00, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0x00, 0x00, /* 0xd0-0xd7 */
0x00, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0x00, 0x00, 0x00, 0xf5, 0x00, 0xf7, /* 0xf0-0xf7 */
0xf8, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, /* 0xf8-0xff */
};
static void inc_use_count(void)
{
MOD_INC_USE_COUNT;
}
static void dec_use_count(void)
{
MOD_DEC_USE_COUNT;
}
static struct nls_table table = {
"cp950",
page_uni2charset,
charset2uni,
inc_use_count,
dec_use_count,
NULL
};
int init_nls_cp950(void)
{
return register_nls();
}
#ifdef MODULE
int init_module(void)
{
return init_nls_cp950();
}
void cleanup_module(void)
{
unregister_nls();
return;
}
#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
*
---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/
EOF
?
5.4 uni2gbk.pl
?
#!/usr/bin/perl
@code = (
"00", "01", "02", "03", "04", "05", "06", "07",
"08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"10", "11", "12", "13", "14", "15", "16", "17",
"18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"20", "21", "22", "23", "24", "25", "26", "27",
"28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"30", "31", "32", "33", "34", "35", "36", "37",
"38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"40", "41", "42", "43", "44", "45", "46", "47",
"48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"50", "51", "52", "53", "54", "55", "56", "57",
"58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"60", "61", "62", "63", "64", "65", "66", "67",
"68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"70", "71", "72", "73", "74", "75", "76", "77",
"78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87",
"88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97",
"98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
"A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7",
"B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7",
"C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7",
"E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7",
"F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF");
while (<STDIN>){
($unicode, $big5) = split;
($high, $low) = $unicode =~ /(..)(..)/;
$table2{$high}{$low} = $big5;
($high, $low) = $big5 =~ /(..)(..)/;
$table{$high}{$low} = $unicode;
}
print <<EOF;
/*
* linux/fs/nls_cp936.c
*
* Charset cp936 translation tables.
* Generated automatically from the Unicode and charset
* tables from the Unicode Organization (www.unicode.org).
* The Unicode to charset table has only exact mappings.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/nls.h>
/* 81 - FE*/
static struct nls_unicode charset2uni[(0xFE-0x81+1)*(0x100-0x40)] = {
EOF
for ($high=0x81; $high <= 0xFE; $high++){
for ($low=0x40; $low <= 0x7F; $low++){
$unicode = $table2{$code[$high]}{$code[$low]};
$unicode = "0000" if (!(defined $unicode));
print "/n/t" if ($low%4 == 0);
print "/* $code[$high]$code[$low]*//n/t" if ($low%0x10 == 0);
($uhigh, $ulow) = $unicode =~ /(..)(..)/;
printf("{0x%2s, 0x%2s}, ", $ulow, $uhigh);
}
for ($low=0x80; $low <= 0xFF; $low++){
$unicode = $table2{$code[$high]}{$code[$low]};
$unicode = "0000" if (!(defined $unicode));
print "/n/t" if ($low%4 == 0);
print "/* $code[$high]$code[$low]*//n/t" if ($low%0x10 == 0);
($uhigh, $ulow) = $unicode =~ /(..)(..)/;
printf("{0x%2s, 0x%2s}, ", $ulow, $uhigh);
}
}
print "/n};/n/n";
for ($high=1; $high <= 255;$high++){
if (defined $table{$code[$high]}){
print "static unsigned char page$code[$high]/[512/] = {/n/t";
for ($low=0; $low<=255;$low++){
$big5 = $table{$code[$high]}{$code[$low]};
$big5 = "3F3F" if (!(defined $big5));
if ($low > 0 && $low%4 == 0){
printf("/* 0x%02X-0x%02X *//n/t", $low-4, $low-1);
}
print "/n/t" if ($low == 0x80);
($bhigh, $blow) = $big5 =~ /(..)(..)/;
printf("0x%2s, 0x%2s, ", $bhigh, $blow);
}
print "/* 0xFC-0xFF *//n};/n/n";
}
}
print "static unsigned char *page_uni2charset[256] = {";
for ($high=0; $high<=255;$high++){
print "/n/t" if ($high%8 == 0);
if ($high>0 && defined $table{$code[$high]}){
print "page$code[$high], ";
}
else{
print "NULL, ";
}
}
print <<EOF;
};
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
0x98, 0x99, 0x9a, 0x00, 0x9c, 0x00, 0x00, 0x00, /* 0x98-0x9f */
0x00, 0x00, 0x00, 0x00, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0x00, 0x00, /* 0xd0-0xd7 */
0x00, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0x00, 0x00, 0x00, 0xf5, 0x00, 0xf7, /* 0xf0-0xf7 */
0xf8, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, /* 0xf8-0xff */
};
static void inc_use_count(void)
{
MOD_INC_USE_COUNT;
}
static void dec_use_count(void)
{
MOD_DEC_USE_COUNT;
}
static struct nls_table table = {
"cp936",
page_uni2charset,
charset2uni,
inc_use_count,
dec_use_count,
NULL
};
int init_nls_cp936(void)
{
return register_nls();
}
#ifdef MODULE
int init_module(void)
{
return init_nls_cp936();
}
void cleanup_module(void)
{
unregister_nls();
return;
}
#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
*
---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/
EOF
?
?
5.5 轉換CODEPAGE的工具
?
/*
* CPI.C: A program to examine MSDOS codepage files (*.cpi)
* and extract specific codepages.
* Compiles under Linux & DOS (using BC++ 3.1).
*
* Compile: gcc -o cpi cpi.c
* Call: codepage file.cpi [-a|-l|nnn]
*
* Author: Ahmed M. Naas (ahmed@oea.xs4all.nl)
* Many changes: aeb@cwi.nl [changed until it would handle all
* *.cpi files people have sent me; I have no documentation,
* so all this is experimental]
* Remains to do: DRDOS fonts.
*
* Copyright: Public domain.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int handle_codepage(int);
void handle_fontfile(void);
#define PACKED __attribute__ ((packed))
/* Use this (instead of the above) to compile under MSDOS */
/*#define PACKED */
struct {
unsigned char id[8] PACKED;
unsigned char res[8] PACKED;
unsigned short num_pointers PACKED;
unsigned char p_type PACKED;
unsigned long offset PACKED;
} FontFileHeader;
struct {
unsigned short num_codepages PACKED;
} FontInfoHeader;
struct {
unsigned short size PACKED;
unsigned long off_nexthdr PACKED;
unsigned short device_type PACKED; /* screen=1; printer=2 */
unsigned char device_name[8] PACKED;
unsigned short codepage PACKED;
unsigned char res[6] PACKED;
unsigned long off_font PACKED;
} CPEntryHeader;
struct {
unsigned short reserved PACKED;
unsigned short num_fonts PACKED;
unsigned short size PACKED;
} CPInfoHeader;
struct {
unsigned char height PACKED;
unsigned char width PACKED;
unsigned short reserved PACKED;
unsigned short num_chard PACKED;
} ScreenFontHeader;
struct {
unsigned short p1 PACKED;
unsigned short p2 PACKED;
} PrinterFontHeader;
FILE *in, *out;
void usage(void);
int opta, optc, optl, optL, optx;
extern int optind;
extern char *optarg;
unsigned short codepage;
int main (int argc, char *argv[])
{
if (argc < 2)
usage();
if ((in = fopen(argv[1], "r")) == NULL) {
printf("/nUnable to open file %s./n", argv[1]);
exit(0);
}
opta = optc = optl = optL = optx = 0;
optind = 2;
if (argc == 2)
optl = 1;
else
while(1) {
switch(getopt(argc, argv, "alLc")) {
case 'a':
opta = 1;
continue;
case 'c':
optc = 1;
continue;
case 'L':
optL = 1;
continue;
case 'l':
optl = 1;
continue;
case '?':
default:
usage();
case -1:
break;
}
break;
}
if (optind != argc) {
if (optind != argc-1 || opta)
usage();
codepage = atoi(argv[optind]);
optx = 1;
}
if (optc)
handle_codepage(0);
else
handle_fontfile();
if (optx) {
printf("no page %d found/n", codepage);
exit(1);
}
fclose(in);
return (0);
}
void
handle_fontfile(){
int i, j;
j = fread(, 1, sizeof(FontFileHeader), in);
if (j != sizeof(FontFileHeader)) {
printf("error reading FontFileHeader - got %d chars/n", j);
exit (1);
}
if (!strcmp(FontFileHeader.id + 1, "DRFONT ")) {
printf("this program cannot handle DRDOS font files/n");
exit(1);
}
if (optL)
printf("FontFileHeader: id=%8.8s res=%8.8s num=%d typ=%c offset=%ld/n/n",
FontFileHeader.id, FontFileHeader.res,
FontFileHeader.num_pointers,
FontFileHeader.p_type,
FontFileHeader.offset);
j = fread(, 1, sizeof(FontInfoHeader), in);
if (j != sizeof(FontInfoHeader)) {
printf("error reading FontInfoHeader - got %d chars/n", j);
exit (1);
}
if (optL)
printf("FontInfoHeader: num_codepages=%d/n/n",
FontInfoHeader.num_codepages);
for (i = FontInfoHeader.num_codepages; i; i--)
if (handle_codepage(i-1))
break;
}
int
handle_codepage(int more_to_come) {
int j;
char outfile[20];
unsigned char *fonts;
long inpos, nexthdr;
j = fread(, 1, sizeof(CPEntryHeader), in);
if (j != sizeof(CPEntryHeader)) {
printf("error reading CPEntryHeader - got %d chars/n", j);
exit(1);
}
if (optL) {
int t = CPEntryHeader.device_type;
printf("CPEntryHeader: size=%d dev=%d [%s] name=%8.8s /
codepage=%d/n/t/tres=%6.6s nxt=%ld off_font=%ld/n/n",
CPEntryHeader.size,
t, (t==1) ? "screen" : (t==2) ? "printer" : "?",
CPEntryHeader.device_name,
CPEntryHeader.codepage,
CPEntryHeader.res,
CPEntryHeader.off_nexthdr, CPEntryHeader.off_font);
} else if (optl) {
printf("/nCodepage = %d/n", CPEntryHeader.codepage);
printf("Device = %.8s/n", CPEntryHeader.device_name);
}
#if 0
if (CPEntryHeader.size != sizeof(CPEntryHeader)) {
/* seen 26 and 28, so that the difference below is -2 or 0 */
if (optl)
printf("Skipping %d bytes of garbage/n",
CPEntryHeader.size - sizeof(CPEntryHeader));
fseek(in, CPEntryHeader.size - sizeof(CPEntryHeader),
SEEK_CUR);
}
#endif
if (!opta && (!optx || CPEntryHeader.codepage != codepage) && !optc)
goto next;
inpos = ftell(in);
if (inpos != CPEntryHeader.off_font && !optc) {
if (optL)
printf("pos=%ld font at %ld/n", inpos, CPEntryHeader.off_font);
fseek(in, CPEntryHeader.off_font, SEEK_SET);
}
j = fread(, 1, sizeof(CPInfoHeader), in);
if (j != sizeof(CPInfoHeader)) {
printf("error reading CPInfoHeader - got %d chars/n", j);
exit(1);
}
if (optl) {
printf("Number of Fonts = %d/n", CPInfoHeader.num_fonts);
printf("Size of Bitmap = %d/n", CPInfoHeader.size);
}
if (CPInfoHeader.num_fonts == 0)
goto next;
if (optc)
return 0;
sprintf(outfile, "%d.cp", CPEntryHeader.codepage);
if ((out = fopen(outfile, "w")) == NULL) {
printf("/nUnable to open file %s./n", outfile);
exit(1);
} else printf("/nWriting %s/n", outfile);
fonts = (unsigned char *) malloc(CPInfoHeader.size);
fread(fonts, CPInfoHeader.size, 1, in);
fwrite(, sizeof(CPEntryHeader), 1, out);
fwrite(, sizeof(CPInfoHeader), 1, out);
j = fwrite(fonts, 1, CPInfoHeader.size, out);
if (j != CPInfoHeader.size) {
printf("error writing %s - wrote %d chars/n", outfile, j);
exit(1);
}
fclose(out);
free(fonts);
if (optx) exit(0);
next:
/*
* It seems that if entry headers and fonts are interspersed,
* then nexthdr will point past the font, regardless of
* whether more entries follow.
* Otherwise, first all entry headers are given, and then
* all fonts; in this case nexthdr will be 0 in the last entry.
*/
nexthdr = CPEntryHeader.off_nexthdr;
if (nexthdr == 0 || nexthdr == -1) {
if (more_to_come) {
printf("mode codepages expected, but nexthdr=%ld/n",
nexthdr);
exit(1);
} else
return 1;
}
inpos = ftell(in);
if (inpos != CPEntryHeader.off_nexthdr) {
if (optL)
printf("pos=%ld nexthdr at %ld/n", inpos, nexthdr);
if (opta && !more_to_come) {
printf("no more code pages, but nexthdr != 0/n");
return 1;
}
fseek(in, CPEntryHeader.off_nexthdr, SEEK_SET);
}
return 0;
}
void usage(void)
{
printf("/nUsage: cpi code_page_file [-c] [-L] [-l] [-a|nnn]/n");
printf(" -c: input file is a single codepage/n");
printf(" -L: print header info (you don't want to see this)/n");
printf(" -l or no option: list all codepages contained in the file/n");
printf(" -a: extract all codepages from the file/n");
printf(" nnn (3 digits): extract codepage nnn from the file/n");
printf("Example: cpi ega.cpi 850 /n");
printf(" will create a file 850.cp containing the requested codepage./n/n");
exit(1);
}
?
作者Blog:http://blog.csdn.net/findsun/ posted on 2006-07-20 14:31 汪杰 閱讀(342) 評論(1) ?編輯?收藏 引用 <script type="text/javascript"> // </script>
FeedBack: #?re: Codepage的定義和歷史 2006-07-20 14:32 | 汪杰
這是一篇程序員寫給程序員的趣味讀物。所謂趣味是指可以比較輕松地了解一些原來不清楚的概念,增進知識,類似于打RPG游戲的升級。整理這篇文章的動機是兩個問題:
問題一:
使用Windows記事本的“另存為”,可以在GBK、Unicode、Unicode big endian和UTF-8這幾種編碼方式間相互轉換。同樣是txt文件,Windows是怎樣識別編碼方式的呢?
我 很早前就發現Unicode、Unicode big endian和UTF-8編碼的txt文件的開頭會多出幾個字節,分別是FF、FE(Unicode),FE、FF(Unicode big endian),EF、BB、BF(UTF-8)。但這些標記是基于什么標準呢?
問題二:
最近在網上看到 一個ConvertUTF.c,實現了UTF-32、UTF-16和UTF-8這三種編碼方式的相互轉換。對于Unicode(UCS2)、GBK、 UTF-8這些編碼方式,我原來就了解。但這個程序讓我有些糊涂,想不起來UTF-16和UCS2有什么關系。
查了查相關資料,總算將這些問題弄清楚了,順帶也了解了一些Unicode的細節。寫成一篇文章,送給有過類似疑問的朋友。本文在寫作時盡量做到通俗易懂,但要求讀者知道什么是字節,什么是十六進制。
0、big endian和little endian
big endian和little endian是CPU處理多字節數的不同方式。例如“漢”字的Unicode編碼是6C49。那么寫到文件里時,究竟是將6C寫在前面,還是將49寫在前 面?如果將6C寫在前面,就是big endian。還是將49寫在前面,就是little endian。
“endian”這個詞出自《格列佛游記》。小人國的內戰就源于吃雞蛋時是究竟從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開,由此曾發生過六次叛亂,其中一個皇帝送了命,另一個丟了王位。
我們一般將endian翻譯成“字節序”,將big endian和little endian稱作“大尾”和“小尾”。
1、字符編碼、內碼,順帶介紹漢字編碼
字符必須編碼后才能被計算機處理。計算機使用的缺省編碼方式就是計算機的內碼。早期的計算機使用7位的ASCII編碼,為了處理漢字,程序員設計了用于簡體中文的GB2312和用于繁體中文的big5。
GB2312(1980年)一共收錄了7445個字符,包括6763個漢字和682個其它符號。漢字區的內碼范圍高字節從B0-F7,低字節從A1-FE,占用的碼位是72*94=6768。其中有5個空位是D7FA-D7FE。
GB2312 支持的漢字太少。1995年的漢字擴展規范GBK1.0收錄了21886個符號,它分為漢字區和圖形符號區。漢字區包括21003個字符。2000年的 GB18030是取代GBK1.0的正式國家標準。該標準收錄了27484個漢字,同時還收錄了藏文、蒙文、維吾爾文等主要的少數民族文字。現在的PC平 臺必須支持GB18030,對嵌入式產品暫不作要求。所以手機、MP3一般只支持GB2312。
從ASCII、GB2312、GBK到 GB18030,這些編碼方法是向下兼容的,即同一個字符在這些方案中總是有相同的編碼,后面的標準支持更多的字符。在這些編碼中,英文和中文可以統一地 處理。區分中文編碼的方法是高字節的最高位不為0。按照程序員的稱呼,GB2312、GBK到GB18030都屬于雙字節字符集 (DBCS)。
有的中文Windows的缺省內碼還是GBK,可以通過GB18030升級包升級到GB18030。不過GB18030相對GBK增加的字符,普通人是很難用到的,通常我們還是用GBK指代中文Windows內碼。
這里還有一些細節:
GB2312的原文還是區位碼,從區位碼到內碼,需要在高字節和低字節上分別加上A0。
在DBCS中,GB內碼的存儲格式始終是big endian,即高位在前。
GB2312 的兩個字節的最高位都是1。但符合這個條件的碼位只有128*128=16384個。所以GBK和GB18030的低字節最高位都可能不是1。不過這不影 響DBCS字符流的解析:在讀取DBCS字符流時,只要遇到高位為1的字節,就可以將下兩個字節作為一個雙字節編碼,而不用管低字節的高位是什么。
2、Unicode、UCS和UTF
前面提到從ASCII、GB2312、GBK到GB18030的編碼方法是向下兼容的。而Unicode只與ASCII兼容(更準確地說,是與ISO-8859-1兼容),與GB碼不兼容。例如“漢”字的Unicode編碼是6C49,而GB碼是BABA。
Unicode 也是一種字符編碼方法,不過它是由國際組織設計,可以容納全世界所有語言文字的編碼方案。Unicode的學名是"Universal Multiple-Octet Coded Character Set",簡稱為UCS。UCS可以看作是"Unicode Character Set"的縮寫。
根據維基百科全書(http://zh.wikipedia.org/wiki/)的記載:歷史上存在兩個試圖獨立設計 Unicode的組織,即國際標準化組織(ISO)和一個軟件制造商的協會(unicode.org)。ISO開發了ISO 10646項目,Unicode協會開發了Unicode項目。
在1991年前后,雙方都認識到世界不需要兩個不兼容的字符集。于是它們開始合并雙方的工作成果,并為創立一個單一編碼表而協同工作。從Unicode2.0開始,Unicode項目采用了與ISO 10646-1相同的字庫和字碼。
目前兩個項目仍都存在,并獨立地公布各自的標準。Unicode協會現在的最新版本是2005年的Unicode 4.1.0。ISO的最新標準是10646-3:2003。
UCS規定了怎么用多個字節表示各種文字。怎樣傳輸這些編碼,是由UTF(UCS Transformation Format)規范規定的,常見的UTF規范包括UTF-8、UTF-7、UTF-16。
IETF 的RFC2781和RFC3629以RFC的一貫風格,清晰、明快又不失嚴謹地描述了UTF-16和UTF-8的編碼方法。我總是記不得IETF是 Internet Engineering Task Force的縮寫。但IETF負責維護的RFC是Internet上一切規范的基礎。
3、UCS-2、UCS-4、BMP
UCS有兩種格式:UCS-2和UCS-4。顧名思義,UCS-2就是用兩個字節編碼,UCS-4就是用4個字節(實際上只用了31位,最高位必須為0)編碼。下面讓我們做一些簡單的數學游戲:
UCS-2有2^16=65536個碼位,UCS-4有2^31=2147483648個碼位。
UCS -4根據最高位為0的最高字節分成2^7=128個group。每個group再根據次高字節分為256個plane。每個plane根據第3個字節分為 256行 (rows),每行包含256個cells。當然同一行的cells只是最后一個字節不同,其余都相同。
group 0的plane 0被稱作Basic Multilingual Plane, 即BMP。或者說UCS-4中,高兩個字節為0的碼位被稱作BMP。
將UCS-4的BMP去掉前面的兩個零字節就得到了UCS-2。在UCS-2的兩個字節前加上兩個零字節,就得到了UCS-4的BMP。而目前的UCS-4規范中還沒有任何字符被分配在BMP之外。
4、UTF編碼
UTF-8就是以8位為單元對UCS進行編碼。從UCS-2到UTF-8的編碼方式如下:
UCS-2編碼(16進制) UTF-8 字節流(二進制)
0000 - 007F 0xxxxxxx
0080 - 07FF 110xxxxx 10xxxxxx
0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx
例如“漢”字的Unicode編碼是6C49。6C49在0800-FFFF之間,所以肯定要用3字節模板了:1110xxxx 10xxxxxx 10xxxxxx。將6C49寫成二進制是:0110 110001 001001, 用這個比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。
讀者可以用記事本測試一下我們的編碼是否正確。
UTF -16以16位為單元對UCS進行編碼。對于小于0x10000的UCS碼,UTF-16編碼就等于UCS碼對應的16位無符號整數。對于不小于 0x10000的UCS碼,定義了一個算法。不過由于實際使用的UCS2,或者UCS4的BMP必然小于0x10000,所以就目前而言,可以認為UTF -16和UCS-2基本相同。但UCS-2只是一個編碼方案,UTF-16卻要用于實際的傳輸,所以就不得不考慮字節序的問題。
5、UTF的字節序和BOM
UTF -8以字節為編碼單元,沒有字節序的問題。UTF-16以兩個字節為編碼單元,在解釋一個UTF-16文本前,首先要弄清楚每個編碼單元的字節序。例如收 到一個“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節流“594E”,那么這是“奎”還是 “乙”?
Unicode規范中推薦的標記字節順序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一個有點小聰明的想法:
在UCS 編碼中有一個叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,所以不應該出現在實際傳輸中。UCS規范建議我們在傳輸字節流前,先傳輸 字符"ZERO WIDTH NO-BREAK SPACE"。
這樣如果接收者收到FEFF,就表明這個字節流是Big-Endian的;如果收到FFFE,就表明這個字節流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。
UTF -8不需要BOM來表明字節順序,但可以用BOM來表明編碼方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF(讀者可以用我們前面介紹的編碼方法驗證一下)。所以如果接收者收到以EF BB BF開頭的字節流,就知道這是UTF-8編碼了。
Windows就是使用BOM來標記文本文件的編碼方式的。
6、進一步的參考資料
本文主要參考的資料是 "Short overview of ISO-IEC 10646 and Unicode" (http://www.nada.kth.se/i18n/ucs/unicode-iso10646-oview.html)。
我還找了兩篇看上去不錯的資料,不過因為我開始的疑問都找到了答案,所以就沒有看:
"Understanding Unicode A general introduction to the Unicode Standard" (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&item_id=IWS-Chapter04a)
"Character set encoding basics Understanding character set encodings and legacy encodings" (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&item_id=IWS-Chapter03)
我寫過UTF-8、UCS-2、GBK相互轉換的軟件包,包括使用Windows API和不使用Windows API的版本。以后有時間的話,我會整理一下放到我的個人主頁上(http://fmddlmyy.home4u.china.com)。
我是想清楚所有問題后才開始寫這篇文章的,原以為一會兒就能寫好。沒想到考慮措辭和查證細節花費了很長時間,竟然從下午1:30寫到9:00。希望有讀者能從中受益。
http://topic.csdn.net/t/20030225/14/1464046.html
codepage ?
? ? 用一個整數表示把數據寫入的目標文件時的編碼。如果這個值是0,那么當前系統編碼為文件編碼,可查閱編碼附錄列表來參考在WIN32系統中的編碼使用方法。編碼65001(UTF-8)是在多語言環境中最實用的編碼。如果產生的是HTML文件,請確認一下HTML字符設置(characterset)是否相對應。簡體中文應用編碼936(GB2312)。 ? ?
? ?
? 語言默認設置 ?
? 下面列表是“靈蛙管理”中默認的語言標識,和相應的代碼頁的設置。關系可以在“hr.ini”初始化文件中更改。之后有代碼頁與字符集的關系列表,僅作參考。 ?
? ?
? 語言標識和相應的代碼頁 ?
? localeID ? CodePage ? Description ? ?
? 0x0436 ? 1252 ? Afrikaans ? ?
? 0x041c ? 1252 ? Albanian ? ?
? 0x0001 ? 1256 ? Arabic ? ?
? 0x0401 ? 1256 ? Arabic(Saudi ? Arabia) ? ?
? 0x0801 ? 1256 ? Arabic(Iraq) ? ?
? 0x0C01 ? 1256 ? Arabic(Egypt) ? ?
? 0x1001 ? 1256 ? Arabic(Libya) ? ?
? 0x1401 ? 1256 ? Arabic(Algeria) ? ?
? 0x1801 ? 1256 ? Arabic(Morocco) ? ?
? 0x1C01 ? 1256 ? Arabic(Tunisia) ? ?
? 0x2001 ? 1256 ? Arabic(Oman) ? ?
? 0x2401 ? 1256 ? Arabic(Yemen) ? ?
? 0x2801 ? 1256 ? Arabic(Syria) ? ?
? 0x2C01 ? 1256 ? Arabic(Jordan) ? ?
? 0x3001 ? 1256 ? Arabic(Lebanon) ? ?
? 0x3401 ? 1256 ? Arabic(Kuwait) ? ?
? 0x3801 ? 1256 ? Arabic(U.A.E.) ? ?
? 0x3C01 ? 1256 ? Arabic(Bahrain) ? ?
? 0x4001 ? 1256 ? Arabic(Qatar) ? ?
? 0x042D ? 1252 ? Basque ? ?
? 0x0402 ? 1252 ? Bulgarian ? ?
? 0x0423 ? 1252 ? Belarusian ? ?
? 0x0403 ? 1252 ? Catalan ? ?
? 0x0004 ? 936 ? Chinese ? ?
? 0x0404 ? 950 ? Chinese(Taiwan ? Region) ? ?
? 0x0804 ? 936 ? Chinese(PRC) ? ?
? 0x0C04 ? 950 ? Chinese(Hong ? Kong ? SAR, ? PRC) ? ?
? 0x1004 ? 936 ? Chinese(Singapore) ? ?
? 0x041a ? 1252 ? Croatian ? ?
? 0x0405 ? 1252 ? Czech ? ?
? 0x0406 ? 1252 ? Danish ? ?
? 0x0413 ? 1252 ? Dutch(Standard) ? ?
? 0x0813 ? 1252 ? Dutch(Belgian) ? ?
? 0x0009 ? 1252 ? English ? ?
? 0x0409 ? 1252 ? English(United ? States) ? ?
? 0x0809 ? 1252 ? English(British) ? ?
? 0x0c09 ? 1252 ? English(Australian) ? ?
? 0x1009 ? 1252 ? English(Canadian) ? ?
? 0x1409 ? 1252 ? English(New ? Zealand) ? ?
? 0x1809 ? 1252 ? English(Ireland) ? ?
? 0x1c09 ? 1252 ? English(South ? Africa) ? ?
? 0x2009 ? 1252 ? English(Jamaica) ? ?
? 0x2409 ? 1252 ? English(Caribbean) ? ?
? 0x2809 ? 1252 ? English(Belize) ? ?
? 0x2c09 ? 1252 ? English(Trinidad) ? ?
? 0x0425 ? 1252 ? Estonian ? ?
? 0x0438 ? 1252 ? Faeroese ? ?
? 0x0429 ? 1252 ? Farsi ? ?
? 0x040b ? 1252 ? Finnish ? ?
? 0x040c ? 1252 ? French(Standard) ? ?
? 0x080c ? 1252 ? French(Belgian) ? ?
? 0x0c0c ? 1252 ? French(Canadian) ? ?
? 0x100c ? 1252 ? French(Swiss) ? ?
? 0x140c ? 1252 ? French(Luxembourg) ? ?
? 0x043c ? 1252 ? Gaelic(Scots) ? ?
? 0x083c ? 1252 ? Gaelic(Irish) ? ?
? 0x0407 ? 1252 ? German(Standard) ? ?
? 0x0807 ? 1252 ? German(Swiss) ? ?
? 0x0c07 ? 1252 ? German(Austrian) ? ?
? 0x1007 ? 1252 ? German(Luxembourg) ? ?
? 0x1407 ? 1252 ? German(Liechtenstein) ? ?
? 0x0408 ? 1253 ? Greek ? ?
? 0x040D ? 1255 ? Hebrew ? ?
? 0x0439 ? 1252 ? Hindi ? ?
? 0x040e ? 1252 ? Hungarian ? ?
? 0x040F ? 1252 ? Icelandic ? ?
? 0x0421 ? 1252 ? Indonesian ? ?
? 0x0410 ? 1252 ? Italian(Standard) ? ?
? 0x0810 ? 1252 ? Italian(Swiss) ? ?
? 0x0411 ? 932 ? Japanese ? ?
? 0x0412 ? 949 ? Korean ? ?
? 0x0812 ? 949 ? Korean(Johab) ? ?
? 0x0426 ? 1252 ? Latvian ? ?
? 0x0427 ? 1252 ? Lithuanian ? ?
? 0x042f ? 1252 ? Macedonian ? ?
? 0x043e ? 1252 ? Malaysian ? ?
? 0x043a ? 1252 ? Maltese ? ?
? 0x0414 ? 1252 ? Norwegian(Bokmal) ? ?
? 0x0814 ? 1252 ? Norwegian(Nynorsk) ? ?
? 0x0415 ? 1252 ? Polish ? ?
? 0x0416 ? 1252 ? Portuguese(Brazilian) ? ?
? 0x0816 ? 1252 ? Portuguese(Standard) ? ?
? 0x0417 ? 1252 ? Rhaeto-Romanic ? ?
? 0x0418 ? 1252 ? Romanian ? ?
? 0x0818 ? 1252 ? Romanian(Moldavia) ? ?
? 0x0419 ? 1252 ? Russian ? ?
? 0x0819 ? 1252 ? Russian(Moldavia) ? ?
? 0x043b ? 1252 ? Sami(Lappish) ? ?
? 0x0c1a ? 1252 ? Serbian(Cyrillic) ? ?
? 0x081a ? 1252 ? Serbian(Latin) ? ?
? 0x041b ? 1252 ? Slovak ? ?
? 0x0424 ? 1252 ? Slovenian ? ?
? 0x042e ? 1252 ? Sorbian ? ?
? 0x000a ? 1252 ? Spanish ? ?
? 0x040a ? 1252 ? Spanish(Spain ? - ? Traditional ? Sort) ? ?
? 0x080a ? 1252 ? Spanish(Mexican) ? ?
? 0x0c0a ? 1252 ? Spanish(Spain ? - ? Modern ? Sort) ? ?
? 0x100a ? 1252 ? Spanish(Guatemala) ? ?
? 0x140a ? 1252 ? Spanish(Costa ? Rica) ? ?
? 0x180a ? 1252 ? Spanish(Panama) ? ?
? 0x1c0a ? 1252 ? Spanish(Dominican ? Republic) ? ?
? 0x200a ? 1252 ? Spanish(Venezuela) ? ?
? 0x240a ? 1252 ? Spanish(Colombia) ? ?
? 0x280a ? 1252 ? Spanish(Peru) ? ?
? 0x2c0a ? 1252 ? Spanish(Argentina) ? ?
? 0x300a ? 1252 ? Spanish(Ecuador) ? ?
? 0x340a ? 1252 ? Spanish(Chile) ? ?
? 0x380a ? 1252 ? Spanish(Uruguay) ? ?
? 0x3c0a ? 1252 ? Spanish(Paraguay) ? ?
? 0x400a ? 1252 ? Spanish(Bolivia) ? ?
? 0x440a ? 1252 ? Spanish(El ? Salvador) ? ?
? 0x480a ? 1252 ? Spanish(Honduras) ? ?
? 0x4c0a ? 1252 ? Spanish(Nicaragua) ? ?
? 0x500a ? 1252 ? Spanish(Puerto ? Rico) ? ?
? 0x0430 ? 1252 ? Sutu ? ?
? 0x041D ? 1252 ? Swedish ? ?
? 0x081d ? 1252 ? Swedish(Finland) ? ?
? 0x041E ? 874 ? Thai ? ?
? 0x0431 ? 1252 ? Tsonga ? ?
? 0x0432 ? 1252 ? Tswana ? ?
? 0x041f ? 1254 ? Turkish ? ?
? 0x0422 ? 1252 ? Ukrainian ? ?
? 0x0420 ? 1252 ? Urdu ? ?
? 0x0433 ? 1252 ? Venda ? ?
? 0x042a ? 1252 ? Vietnamese ? ?
? 0x0434 ? 1252 ? Xhosa ? ?
? 0x043d ? 1252 ? Yiddish ? ?
? 0x0435 ? 1252 ? Zulu ? ?
? ?
? 語言標識和相應的字符集 ?
? Codepage ? CharacterSet ? Description ? ?
? 1252 ? iso-8859-1 ? Western ? ?
? 20105 ? us-ascii ? us-ascii ? ?
? 28592 ? iso-8859-2 ? Central ? European ? (ISO) ? ?
? 1250 ? Windows-1250 ? Central ? European ? (Windows) ? ?
? 1251 ? Windows-1251 ? Cyrillic ? (Windows) ? ?
? 1253 ? Windows-1253 ? Greek ? (Windows) ? ?
? 1254 ? Windows-1254 ? Turkish ? (Windows) ? ?
? 932 ? shift_jis ? Japanese ? (Shift-JIS) ? ?
? 51932 ? x-euc-jp ? Japanese ? (EUC) ? ?
? 50220 ? iso-2022-jp ? Japanese ? (JIS) ? ?
? 1257 ? Windows-1257 ? Baltic ? (Windows) ? ?
? 950 ? big5 ? Traditional ? Chinese ? (BIG5) ? ?
? 936 ? gb2312 ? Simplified ? Chinese ? (GB2312) ? ?
? 20866 ? koi8-r ? Cyrillic ? (KOI8-R) ? ?
? 949 ? ks_c_5601 ? Korean ? (KSC5601) ? ?
? 1255 ? Windows-1255 ? Hebrew ? (ISO-logical) ? -- ? 1255 ? (visual) ? Hebrew ? (ISO-Visual) ? iso-8859-8 ? ?
? 862 ? dos-862 ? Hebrew ? (DOS) ? ?
? 1256 ? Windows-1256 ? Arabic ? (Windows) ? ?
? 720 ? dos-720 ? Arabic ? (DOS) ? ?
? 874 ? Windows-874 ? Thai ? ?
? 1258 ? Windows-1258 ? Vietnamese ? ?
? 65001 ? UTF-8 ? Unicode ? UTF-8 ? ?
? 65000 ? UTF-7 ? Unicode ? UTF-7 ? ?
? 50225 ? ISO-2022-KR ? Korean ? (ISO) ? ?
? 52936 ? HZ-GB-2312 ? Simplified ? Chinese ? (HZ) ? ?
? 28594 ? iso-8869-4 ? Baltic ? (ISO) ? ?
? 28585 ? iso_8859-5 ? Cyrillic ? (ISO) ? ?
? 28597 ? iso-8859-7 ? Greek ? (ISO) ? ?
? 28599 ? iso-8859-9 ? Turkish ? (ISO)????
MultiByteToWideChar
?
總結
以上是生活随笔為你收集整理的Codepage的定义和历史的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring cloud alibaba
- 下一篇: 项目质量管理中的新老7工具