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类型。垃圾!!!
  • 由于头文件过大,在编译时可能出现卡顿现象。别急,等等就好了。
  • 建议使用我排好序的头文件,自己编写。因为代码太乱。我自己都不想看,艹。
  • 程序没有鲁棒性,没有输入码的判断,最大的问题。

流程图

Java怎么实现Unicode和中文转换_unicode

  • 判断字符数量,主要作用为下一次的分割计算需要分割的次数。
  • 每次取六位,前两位是\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按顺序排列的头文件

gb2312顺序排列头文件下载

u.h

结果展示

Java怎么实现Unicode和中文转换_c语言_02

java

流程图

Java怎么实现Unicode和中文转换_gbk_03

  • 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文件

结果展示

Java怎么实现Unicode和中文转换_c语言_04