unicode编码转gb2312编码并显示中文(c&java)
- unicode编码与gb2312编码没有线性关系,只能通过使用编码表的方式查找。
C语言
- 编码表中,前半部分是gb2312编码,后部才是unicode编码。在程序中我们要用值来寻找键。
- C语言的思路是,把两个对应的编码表作为头文件引入到程序中。可以让我们能够,很好的使用它。在使用之前,我们需要把编码表进行处理。让unicode编码按顺序排列。
- 文字部分,我们不需要存储,当我们找出gb2312编码之后。只用把高低两个字节的16进制数,存储到两个char类型的变量中,使用%c%c进行输出。电脑会判断出是中文,会把中文显示出来。
原始设计
- 开始我的设计是unicode与gb2312都可以互相转换,但是由于时间问题。gb2312只完成了一部分,这部分代码,我注释掉了。如果想要使用,可以自行修改。
- gb2312转unicode,需要把取6位变取4位。这步完成之后,应该就可以使用了。
- 选择一次处理一位,而不是全部读取出来,是因为避免文件太大。节省空间。
吐槽
- 代码,开始只想在main中调用函数。可是由于字符串传递,不熟悉。被放弃了。导致main函数中一堆垃圾,还分出一堆子函数。传参只能传递,int类型。垃圾!!!
- 由于头文件过大,在编译时可能出现卡顿现象。别急,等等就好了。
- 建议使用我排好序的头文件,自己编写。因为代码太乱。我自己都不想看,艹。
- 程序没有鲁棒性,没有输入码的判断,最大的问题。
流程图
- 判断字符数量,主要作用为下一次的分割计算需要分割的次数。
- 每次取六位,前两位是\u,后四位是其对应的16进制编码。
- 因为unicode编码有大致的范围,所以先判断是否在gb2312与之对应的范围。如果不在,就不用查找了。减少查找的次数。
- 如果在大概范围之类,就可以进行查找。因为unicode编码是按顺序的。所以使用二分法进行查找。
源.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"g.h"
#include"u.h"
//#define u_code 1
//#define g_code 2
int readfile();//读取文件,处理文件,判断大小
int isright(unsigned short origin_code,int method);//判断编码正确与否
int search_gb2132(unsigned short origin_code, int method);//搜索
void main()
{
int u_code=1;
int some;
int int_code;
char str_begin[3] = { 0 };
int flag;
int str_begin_num;
long long_code;
char str[4] = {0};
char* end;
int code_right;
int str_num;
/* printf("1.unicode转gb2132\n2.gb2132转unicode\n输入你的选择:");
scanf("%d",&some);
if (some==1)
{
u_code = 1;
}*/
FILE* fp;
fp = fopen("D:\\vs\\target.txt", "rb");
//printf("%d", flag);
flag = readfile();
while (flag > 0)
{
flag--;
//printf("%d", flag);
str_begin_num = fread(str_begin, sizeof(char), 2, fp);
str_num = fread(str, sizeof(char), 4, fp);
long_code = strtol(str, &end, 16);
int_code = (int*)long_code;
code_right = isright(int_code, u_code);
if (code_right == 1)
{
search_gb2132(int_code, u_code);
}
}
fclose(fp);//关闭文件并保存
FILE* fpp;
fpp = fopen("c:\\123.txt", "a+");
fprintf(fpp, "\n\n\n");
fclose(fpp);
fclose(fp);
return 0;
}
//搜索,处理
//method,1 u-->gb
int search_gb2132(unsigned short origin_code, int method)
{
char code_c[2];
unsigned short end_code;
int code = -1;
int left = 0;
int right = 7444;
int num;
int num2=0;
FILE* fp;
if (method == 1)//通过unicode,查gb2132
{
while (left <= right)
{//在while循环中直到有一个条件结束搜索
num = (left + right) / 2;
if (uni_map[num].value > origin_code)
{
left = num + 1;
//printf("%d\n",left);
}
else if (uni_map[num].value < origin_code)
{
right = num - 1;
//printf("%d\n", right);
}
else
{
code = uni_map[num].key;
break;//一定要break跳出循环
}
}
}
//else
//{
// while (left <= right)
// {//在while循环中直到有一个条件结束搜索
// num = (left + right) / 2;
// if (gb2312_map[num].key < origin_code)
// {
// left = num + 1;
// //printf("%d\n",left);
// }
// else if (gb2312_map[num].key > origin_code)
// {
// right = num - 1;
// //printf("%d\n", right);
// }
// else
// {
// code = gb2312_map[num].value;
// break;//一定要break跳出循环
// }
// }
//}
if (code == -1)
{
printf("[\\u%X编码有误]", origin_code);
fp = fopen("c:\\123.txt", "a+");
fprintf(fp, "[\\u%X编码有误]", origin_code);
}
else
{
end_code = code;
//printf("%x\n", a);
code_c[0] = end_code & 0x0ff;
//printf("%x\n",c[0]);
code_c[1] = end_code >> 8 & 0x0ff;
//printf("%x\n", c[1]);
printf("%c%c", code_c[1], code_c[0]);
fp = fopen("c:\\123.txt", "a+");
fprintf(fp, "%c%c", code_c[1], code_c[0]);
}
fclose(fp);
return code;
}
//判断编码正确与否
int isright(unsigned short origin_code,int method)
{
FILE* fp;
if (method==1)
{
if (origin_code < 0x00a4 || origin_code>0xffe5)
{
printf("[\\u%X编码有误]", origin_code);
FILE* fp;
fp = fopen("c:\\123.txt", "a+");
fprintf(fp, "[\\u%X编码有误]", origin_code);
fclose(fp);
return 0;
}
}
/*else
{
if (origin_code < 0xa1a1 || origin_code > 0xf7fe)
{
printf("[%X编码有误]", origin_code);
FILE* fp;
fp = fopen("c:\\123.txt", "a+");
fprintf(fp, "[\\u%X编码有误]", origin_code);
fclose(fp);
return 0;
}
}*/
return 1;
}
//读取文件,处理文件,判断大小
int readfile()
{
int address[50];
int len=0;
int flag;
//printf("输入编码文件地址,注意地址最长50字节且\\需输入两次");
//gets(address);
FILE* fp;
fp=fopen("D:\\vs\\target.txt", "rb");
if (fp == NULL) //当文件不存在,或者无法创建时会报错;
{
printf("读取文件失败!!!\n");
}
while (!feof(fp))
{
fgetc(fp);
len++;
}
rewind(fp);//文件指针回到开头
flag = (len - 1) / 6;
fclose(fp);//关闭文件并保存
return flag;
}
g.h
- gb2312按顺序排列的头文件
u.h
- unicode按顺序排列
unicode顺序排列头文件
结果展示
java
流程图
- java可以直接对gbk编码进行显示中文。但是gb2312是gbk的子集,为了避免显示出某些gb2312中没有的字符,所以还要查表。
- 把unicode作为key,把gb2312编码作为value。存储到propertises文件中,进行查找。为什么这样,因为在我脑海中这样查的快。(不知道对不对)
- 在查询到之后,在显示就好了。
吐槽
- 看起来不错,就是没有鲁棒性。一堆垃圾。
- 如果要做,建议添加一个检查模块,就可以使程序更好。本来是要做的,但是时间不够,就放弃了。
java文件
package demo;
import java.io.*;
import java.util.Properties;
public class Demo03 {
public static String stringToGbk(String string) throws Exception{
System.out.println(string);
byte[] bytes = new byte[string.length() / 2];
for(int i = 0; i < bytes.length; i ++){
byte high = Byte.parseByte(string.substring(i * 2, i * 2 + 1), 16); //0 1 2 3
byte low = Byte.parseByte(string.substring(i * 2 + 1, i * 2 + 2), 16);//1 2 3 4
bytes[i] = (byte) (high << 4 | low);
}
String result = new String(bytes, "gbk");
return result;
}
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
//1.创建一个FileInputStream对象,构造方法中需要绑定数据源
FileInputStream fis = new FileInputStream("D:\\ja\\target.txt");
//1.创建FileOutputStream对象,构造方法中传入写入的目的地
FileOutputStream fos = new FileOutputStream("D:\\ja\\1.txt");
//2.使用FileInputStream对象中的方法,read,读取文件
int l=0;
byte[] bytes = new byte[6];
while((l=fis.read(bytes,0,6))!=-1){//结束标记-1
String key = new String(bytes);
//2.使用Properties集合中的load,把硬盘中的数据(键值对),读取到集合中使用
prop.load(new FileReader("D:\\idea\\ma\\untitled\\src\\demo\\utogb.properties"));
//3.取出16进制数
String[] key1=key.split("u",2);
//System.out.println(key1[1]);
//通过键找值
String value = prop.getProperty(key1[1]);
//System.out.println(key+"="+value);
//判断表中是否包含此码
if(value==null){
System.out.println(key1[1]+"未找到此码");
fos.write(("["+key1[1]+"未找到此码]").getBytes());
continue;
}
String result = stringToGbk(value);
//2.调用FileOutputStream对象中的方法write,把数据写入文件中
fos.write(result.getBytes());
System.out.println(result);
}
//3.释放资源
fis.close();
fos.close();
}
}
propertises键值对
unicode与gb2312键值对propertises文件
结果展示