(Declaration: This Article It is original. If it is reproduced, please indicate the author and the original link)
/* Author: Wu. Jian (WU Jian) English name: Sword
/* Date: 2007-12-13
/* Purpose: Knowledge Sharing
These days I encountered the problem of converting UTF-8 to gb2312, and in the embedded environment, there is no API available, check a lot of online information, most of them call interfaces provided by VC or Linux. Here I will summarize my work over the past two days.
In general, there are two major steps (here we will not introduce the basic knowledge ):
1. utf8-> Unicode
because utf8 is related to Unicode, conversion can be performed directly without any libraries. First of all to understand the utf8 encoding format:
U-00000000-U-0000007F: 0 xxxxxxx
U-00000080-U-000007FF: 110 XXXXX 10 xxxxxx
U-00000800-U-0000FFFF: 1110 XXXX 10 xxxxxx 10 xxxxxx
U-00010000-U-001FFFFF: 11110xxx 10 xxxxxx 10 xxxxxx 10 xxxxxx
U-00200000-U-03FFFFFF: 111110xx 10 xxxxxx 10 xxxxxx 10 xxxxxx 10 xxxxxx
U-04000000-U-7FFFFFFF: 1111110x 10 xxxxxx 10 xxxxxx 10 xxxxxx 10 xxxxxx 10 xxxxxx
The first few ones indicate that the last few bytes belong together. This is useful if you want to parse a long string in utf8 format. The following function is used to determine the first few ones (define app_print printf is available here. In this way, when release is used, this macro can be defined as null and it does not need to be modified one by one, debugging is also convenient ):
Int getutf8bytenumforword (u8 firstch)
{
U8 temp = 0x80;
Int num = 0;
While (temp & firstch)
{
Num ++;
Temp = (temp> 1 );
}
App_print ("the num is: % d", num );
Return num;
}
Using this function, we can obtain the several bytes in the string. Because utf8 has a maximum of 6 bytes, I only process the UTF-8 encoding of 3 bytes and 1 byte Based on the returned value, generally, Chinese is 3 bytes in utf8.
// Convert the Len UTF-8 format to the gb2312 format and store it in the pre-applied buffer zone of temp.
Void utf8togb2312 (const char * utf8, int Len, char * temp)
{
App_print ("utf8-> UNICODE: \ n ");
App_print ("utf8 :[");
For (int K = 0; k <Len; k ++)
{
App_print ("% 02x", utf8 [k]);
}
App_print ("] \ n ");
Int bytecount = 0;
Int I = 0;
Int J = 0;
2017-11-unicodekey = 0;
B2gbkey = 0;
// Loop Parsing
While (I <Len)
{
Switch (getutf8bytenumforword (u8) utf8 [I])
{
Case 0:
Temp [J] = utf8 [I];
Bytecount = 1;
Break;
Case 2:
Temp [J] = utf8 [I];
Temp [J + 1] = utf8 [I + 1];
Bytecount = 2;
Break;
case 3:
// utf8-> Unicode
temp [J + 1] = (utf8 [I] & 0x0f) <4) | (utf8 [I + 1]> 2) & 0x0f);
temp [J] = (utf8 [I + 1] & 0x03) <6) + (utf8 [I + 2] & 0x3f);
// Obtain the Unicode Value
Memcpy (& unicodekey, (temp + J), 2 );
App_print ("Unicode key is: 0x % 04x \ n", unicodekey );
// Obtain the corresponding gb2312 value based on this value.
Gbkey = searchcodetable (unicodekey );
App_print ("gb2312 key is: 0x % 04x \ n", gbkey );
If (gbkey! = 0)
{
// Here change the byte
// If the value is not 0, it indicates that the search is successful, and the high and low bytes are converted into the desired format.
Gbkey = (gbkey> 8) | (gbkey <8 );
App_print ("after changing, gb2312 key is: 0x % 04x \ n", gbkey );
Memcpy (temp + J), & gbkey, 2 );
}
Bytecount = 3;
Break;
case 4:
bytecount = 4;
break;
case 5:
bytecount = 5;
break;
case 6:
bytecount = 6;
break;
default:
app_print ("the Len is more than 6 \ n");
break;
}
I + = bytecount;
If (bytecount = 1)
{
J ++;
}
Else
{
J + = 2;
}
}
App_print ("utf8 :[");
For (k = 0; k <j; k ++)
{
App_print ("% 02x", temp [k]);
}
App_print ("] \ n ");
}
Ii. Next we will talk about Unicode-> gb2312 conversion using the look-up table method. First, we will download the code table. Generally, the code table will put gb2312 in front and Unicode in the back, which is inconvenient for us to use, so I converted the Unicode to the front and sorted it in ascending order. (Here, we only need to consider the situation that both are two bytes, because the preceding utf8-> Unicode does not convert the single-byte ASCII to Unicode)
(1) Do table :( can download here: http://blog.91bs.com /? Action = show & id = 20. Thank you.Pig of Dregs )
This is the original format:
0x8140 0x4e02 # CJK uniied ideograph
0x8141 0x4e04 # CJK uniied ideograph
0x8142 0x4e05 # CJK uniied ideograph
First (this can be a small one. Program I am doing this on VC. If necessary, contact me ):
{0x4e02, 0x8140}, // CJK uniied ideograph
{0x4e04, 0x8141}, // CJK uniied ideograph
{0x4e05, 0x8142}, // CJK uniied ideograph
In this way, you can put these in the. h file. below is my definition:
Typedef struct unicode_gb
{
Unsigned short Unicode;
Unsigned short GB;
} Unicode_gb;
unicode_gb code_table [] =
{< br> {0x4e02, 0x8140}, // CJK uniied ideograph
{0x4e04, 0x8141 }, // CJK uniied ideograph
{0x4e05, 0x8142}, // CJK uniied ideograph
...... Omitted
The following step is also very simple. In VC, the whole table is sorted by the bubble sort method. Here, the sorting result is printed according to the Unicode value, run Name> 1.txt in cmd and output it to the file. In this way, a Unicode-> gb2312 code table is prepared in order of Unicode. Below isSource code:
Int main (INT argc, char * argv [])
{
Int num = 0;
Unicode_gb temp;
Int I = 0;
Int J = 0;
Num = sizeof (code_table)/sizeof (unicode_gb );
Printf ("struct size: % d | Total size: % d | num is: % d \ n ",
Sizeof (unicode_gb), sizeof (code_table), num );
For (I = 0; I <num; I ++)
{
For (j = 1; j <num-I; j ++)
{
If (code_table [J-1]. Unicode> code_table [J]. Unicode)
{
Temp. Unicode = code_table [J-1]. Unicode;
Temp. GB = code_table [J-1]. GB;
Code_table [J-1]. Unicode = code_table [J]. Unicode;
Code_table [J-1]. GB = code_table [J]. GB;
Code_table [J]. Unicode = temp. Unicode;
Code_table [J]. GB = temp. GB;
}
}
}
Printf ("here is the code table sorted by Unicode \ n ");
For (I = 0; I <num; I ++)
{
Printf ("{\ t0x % 04x, \ t0x % 04x \ t}, \ t \ n", code_table [I]. Unicode, code_table [I]. GB );
}
Printf ("\ n print over! \ N ");
// The comment below is actually used to add, {,}, and so on to the original code table.
/*
Char buff [100];
Char buff_1 [2, 100];
File * fp = NULL;
File * fp_1 = NULL;
Memset (buff, 0,100 );
Memset (buff_1, 0,100 );
Fp = fopen ("table.txt", "RW ");
Fp_1 = fopen ("table_1.txt", "A + ");
If (FP = NULL) | (fp_1 = NULL ))
{
Printf ("Open File error! \ N ");
Return 1;
}
While (fgets (buff, 100, FP )! = NULL)
{
Buff [8] = ',';
Fputs (buff, fp_1 );
}
*/
Return 0;
}
Finally, searchAlgorithmNow we have sorted the orders in the front. Now we put the sorted code table in the. h file we really need. You should guess what algorithm I used to search for it. The binary method.
# Define code_table_size 21791
// This table is dead, so the length is expressed using a macro instead of using the size each time. However, this may not be good for portability.
Service.ap-southeast-1.maxcompute.aliyun-inc.com/api)
{
Int first = 0;
Int end = code_table_size-1;
Int mid = 0;
While (first <= end)
{
Mid = (first + end)/2;
If (code_table [Mid]. unicode = unicodekey)
{< br> return code_table [Mid]. GB;
}< br> else if (code_table [Mid]. unicode> unicodekey)
{< br> end = mid-1;
}< br> else
{< br> first = Mid + 1;
}< BR >}< br> return 0;
}< br>
At this point, the utf8 string can be converted to gb2312. It is a long string, rather than encoding and conversion of a single Chinese character.