在上篇日志中(链接),我们讨论了utf-8编码和GBK编码之间转化的乱码问题,这一篇我们讨论Unicode(utf-16编码方式)与GBK编码之间转换的乱码问题。

    在Windows系统自带的记事本中,我们按照图中所示使用Unicode编码保存。

    在Visual Studio 2005中,单击“文件|高级保存选项”中选择Unicode-代码页1200。

文件中只有乱码与ASCII码

    按照上一篇日志中的方法,我们使用WinHex软件查看文件的16进制数据,如下:

    其中,头两个字节“FF FE”代表utf-16的BOM码,从D4开始就是数据,即:

0xd4    0x00    0xda    0x00
0xb4 0x00 0xcb 0x00
0xcc 0x00 0xed 0x00
0xbc 0x00 0xd3 0x00
0xd7 0x00 0xa8 0x00
0xd3 0x00 0xc3 0x00
0xb4 0x00 0xfa 0x00
0xc2 0x00 0xeb 0x00
0xba 0x00 0xcd 0x00
0x2f 0x00
0xbb 0x00 0xf2 0x00
0xb5 0x00 0xf7 0x00
0xd3 0x00 0xc3 0x00
0xbb 0x00 0xf9 0x00
0xc0 0x00 0xe0 0x00

    我们同时找出正确字符的GBK编码值

0xd4    0xda
0xb4 0xcb
0xcc 0xed
0xbc 0xd3
0xd7 0xa8
0xd3 0xc3
0xb4 0xfa
0xc2 0xeb
0xba 0xcd
0x2f
0xbb 0xf2
0xb5 0xf7
0xd3 0xc3
0xbb 0xf9
0xc0 0xe0

    我们很容易发现,只要将偶数列中的0x00数消除就可以了,当然,我们格式也从utf-8变为GBK了。

    对应的C语言程序如下:

#include <stdio.h>
#include <stdlib.h> int main(int argc, char const *argv[])
{
FILE* fp;
FILE* fp2;
//打开存储乱码的文件,utf-16编码格式,二进制打开
if((fp2=fopen("BadCode.txt","rb+"))==NULL)
{
printf("Open Source File Failed!\n");
system("pause");
exit(1);
}
//打开、新建存储处理后数据的文件
if((fp=fopen("BadCodeH.txt","w+"))==NULL)
{
printf("Open/Create Destination File Failed!\n");
system("pause");
exit(1);
} //乱码第一个高位字节
unsigned ch;
//乱码第一个低位字节
unsigned cl;
//乱码第二个高位字节
unsigned ch2;
//乱码第二个低位字节
unsigned cl2; ch=fgetc(fp2);
//丢弃BOM字节信息
if(ch==0xff)
{
fgetc(fp2);
ch=fgetc(fp2);
} cl=fgetc(fp2);
while(!feof(fp2))
{
//乱码,接着读取两个字节,再丢弃偶数字节
if (ch>0x7f && cl==0x00)
{
ch2=fgetc(fp2);
cl2=fgetc(fp2);
fputc(ch,fp);
fputc(ch2,fp);
}
//ASCII码,丢弃偶数字节
else
{
fputc(ch,fp); }
ch=fgetc(fp2);
cl=fgetc(fp2);
}
fclose(fp);
fclose(fp2);
system("pause");
return 0;
}

运行结果如下:

更一般的情况(文件中有正常的中文字符,乱码和ASCII字符)

    和上一篇日志中分析的差不多,对于正常的utf-16编码的字符,我们只要将其转换为GBK编码输出就可以了,需要注意的是,正常的utf-16字符编码在文件中的存储方式:高位字节存放编码的后两位,低位字节存放编码的前两位。

C语言程序如下,戳此处下载UnicodeToGBK.txt文件:

#include <stdio.h>
#include <stdlib.h> //读取utf-16和GBK转换表中的数据
bool ReadMap(unsigned* mapValue)
{
//声明文件指针
FILE* fp; //以可读写方式打开映射数据的文本文件
if (NULL == (fp = fopen("UnicodeToGBK.txt", "r+")))
{
printf("Error!");
system("pause");
return false;
} //存储Unicode的16进制数据的字符串
char utfStr[4];
//存储gbk的16进制数据的字符串
char gbkStr[4];
//存储Unicode16进制数据
unsigned utfId;
//存储gbk的16进制数据
unsigned gbkId;
//处理字符的临时变量
char c;
//读取数据 while(!feof(fp))
{
//读Unicode值的字符串
fread(utfStr,4,1,fp);
//转换为整型
sscanf(utfStr,"%4x",&utfId);
fgetc(fp);
//读gbk值的字符串
fread(gbkStr,4,1,fp);
//转化为整型
sscanf(gbkStr,"%4x",&gbkId);
fgetc(fp); //赋值
mapValue[utfId]=gbkId;
} fclose(fp);
return true;
} int main(int argc, char const *argv[])
{
FILE* fp;
FILE* fp2;
//打开存储乱码的文件,utf-16编码格式,二进制打开
if((fp2=fopen("BadCode.txt","rb+"))==NULL)
{
printf("Open Source File Failed!\n");
system("pause");
exit(1);
}
//打开、新建存储处理后数据的文件
if((fp=fopen("BadCodeH.txt","w+"))==NULL)
{
printf("Open/Create Destination File Failed!\n");
system("pause");
exit(1);
} unsigned mapValue[65536];
if(!ReadMap(mapValue))
{
printf("Convert Failed!\n");
system("pause");
exit(1);
}
//乱码第一个高位字节
unsigned ch;
//乱码第一个低位字节
unsigned cl;
//乱码第二个高位字节
unsigned ch2;
//乱码第二个低位字节
unsigned cl2;
//存储utf-16编码的值
unsigned utf;
//存储gbk编码的值
unsigned gbk; ch=fgetc(fp2);
//丢弃BOM字节信息
if(ch==0xff)
{
fgetc(fp2);
ch=fgetc(fp2);
} cl=fgetc(fp2);
while(!feof(fp2))
{
//乱码,接着读取两个字节,再丢弃偶数字节
if (ch>0x7f && cl==0x00)
{
ch2=fgetc(fp2);
cl2=fgetc(fp2);
fputc(ch,fp);
fputc(ch2,fp);
}
//ASCII码,丢弃偶数字节
else if(ch<=0x7f && cl==0x00)
{
fputc(ch,fp); }
//否则就是正常字符,进行编码转换后输出
else
{ utf=cl*256+ch;
gbk=mapValue[utf];
fputc(gbk/256,fp);
fputc(gbk%256,fp);
}
ch=fgetc(fp2);
cl=fgetc(fp2);
}
fclose(fp);
fclose(fp2);
system("pause");
return 0;
}

例子如下:

    未来我会将两篇文章中的程序进行整合,写一个图形界面的程序出来。

    若有错误,恳请各位大侠指教~~

关于解决乱码问题的一点探索之二(涉及Unicode(utf-16)和GBK)的更多相关文章

  1. 关于解决乱码问题的一点探索之一(涉及utf-8和GBK)

    在使用Visual Studio 2005进行MFC开发的时候,发现自动添加的注释变成了乱码.像这样: // TODO: ÔÚ´ËÌí¼ÓרÓôúÂëºÍ/»òµ÷ÓûùÀà 还有这样: // ...

  2. mysql 使用set names 解决乱码问题的原理

    解决乱码的方法,我们经常使用“set names utf8”,那么为什么加上这句代码就可以解决了呢?下面跟着我一起来深入set names utf8的内部执行原理 先说MySQL的字符集问题.Wind ...

  3. servlet 解决乱码问题

    对于servlet大家应该都很熟悉了,今天再复习一下,如果有哪里写的不好或不对的地点希望广大的网友批评指正.今天只讨论get和post两w种方式,他们之间有很多的不同点,所以解决编码的方式也会不一样, ...

  4. 关于Mysql中文乱码问题该如何解决(乱码问题完美解决方案)(转)

    这篇文章给大家介绍关于Mysql中文乱码问题该如何解决(乱码问题完美解决方案)的相关资料,还给大家收集些关于MySQL会出现中文乱码原因常见的几点,小伙伴快来看看吧   最近两天做项目总是被乱码问题困 ...

  5. SpringMVC解决乱码

    SpringMVC解决乱码 在web.xml中配置如下代码

  6. http get/post解决乱码问题

    <form method="默认为get"-> <s:form mothod="默认为post"-> ================= ...

  7. 上传Text文档并转换为PDF(解决乱码)

    前些日子,Insus.NET有分享一篇<上传Text文档并转换为PDF>http://www.cnblogs.com/insus/p/4313092.html 它是按最简单与默认方式来处理 ...

  8. php 解决乱码的通用方法

    一,出现乱码的原因分析 1,保存文件时候,文件有自己的文件编码,就是汉字,或者其他国语言,以什么编码来存储 2,输出的时候,要给内容指定编码,如以网页的形势输入时<meta http-equiv ...

  9. 为sublime安装package control 解决乱码问题 Mac版

    为sublime安装package control   Mac版参考 https://sublime.wbond.net/installation 防止中文乱码其实只需要2个东东  一个GBK enc ...

随机推荐

  1. Java实例 Part6:Java中的克隆

    目录 Part6:Java中的克隆 Example01:Java对象的假克隆 Example02:Java对象的浅克隆 Example03:Java对象的深克隆 Example04:序列化与对象克隆 ...

  2. goland实现函数式链式编程

    先来看一段代码 package main import ( "fmt" elastic "gopkg.in/olivere/elastic.v2" ) type ...

  3. 详解Linux运维工程师高级篇(大数据安全方向).

    hadoop安全目录: kerberos(已发布) elasticsearch(已发布)http://blog.51cto.com/chenhao6/2113873 knox oozie ranger ...

  4. C语言实现可复用栈

    一.思考 最开始写的栈,通过宏来改变元素数据类型,在同一程序中只能用于一种数据类型,想要用于多种数据类型则要复制代码并改名.那么,有没有方法不复制代码就可以用于多种数据类型? 二.基本思路 在我的经验 ...

  5. 20155331 丹增旦达 2006-2007-2 《Java程序设计》第二周学习总结

    20155331 丹增旦达 2006-2007-2 <Java程序设计>第二周学习总结 教材学习内容总结 一 ,类型.变量与运算符 一.数据类型 1, 分类: 基本数据类型 byte:字节 ...

  6. 微信小程序解决地图上的层级关系

    在有带地图的手机页面上,view无法显示在地图上方,所以,在wxml中,使用: <cover-view></cover-view> 能使view显示在地图上 注: 在该标签内部 ...

  7. 苏州Uber优步司机奖励政策(4月18日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  8. 【转载】DXUT11框架浅析(4)--调试相关

    原文:DXUT11框架浅析(4)--调试相关 DXUT11框架浅析(4)--调试相关 1. D3D8/9和D3D10/11的调试区别 只要安装了DXSDK,有个调试工具DirectX ControlP ...

  9. js灵活处理日期(函实例)

    基础方法: var dd = new Date() dd.getFullYear() dd.getMonth() dd.getDate() dd.getDay() //获取星期几(0~6) dd.ge ...

  10. HTML基本代码教学,第三天

    HTML 今天由于个人情况,身体不适,但是为了大家的学习进度,咱们以纯文字得形式来简单了解下今天的学习内容 今儿咱们来了解下表单 <form id=" "  name=&qu ...