关于解决乱码问题的一点探索之二(涉及Unicode(utf-16)和GBK)
在上篇日志中(链接),我们讨论了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)的更多相关文章
- 关于解决乱码问题的一点探索之一(涉及utf-8和GBK)
在使用Visual Studio 2005进行MFC开发的时候,发现自动添加的注释变成了乱码.像这样: // TODO: ÔÚ´ËÌí¼ÓרÓôúÂëºÍ/»òµ÷ÓûùÀà 还有这样: // ...
- mysql 使用set names 解决乱码问题的原理
解决乱码的方法,我们经常使用“set names utf8”,那么为什么加上这句代码就可以解决了呢?下面跟着我一起来深入set names utf8的内部执行原理 先说MySQL的字符集问题.Wind ...
- servlet 解决乱码问题
对于servlet大家应该都很熟悉了,今天再复习一下,如果有哪里写的不好或不对的地点希望广大的网友批评指正.今天只讨论get和post两w种方式,他们之间有很多的不同点,所以解决编码的方式也会不一样, ...
- 关于Mysql中文乱码问题该如何解决(乱码问题完美解决方案)(转)
这篇文章给大家介绍关于Mysql中文乱码问题该如何解决(乱码问题完美解决方案)的相关资料,还给大家收集些关于MySQL会出现中文乱码原因常见的几点,小伙伴快来看看吧 最近两天做项目总是被乱码问题困 ...
- SpringMVC解决乱码
SpringMVC解决乱码 在web.xml中配置如下代码
- http get/post解决乱码问题
<form method="默认为get"-> <s:form mothod="默认为post"-> ================= ...
- 上传Text文档并转换为PDF(解决乱码)
前些日子,Insus.NET有分享一篇<上传Text文档并转换为PDF>http://www.cnblogs.com/insus/p/4313092.html 它是按最简单与默认方式来处理 ...
- php 解决乱码的通用方法
一,出现乱码的原因分析 1,保存文件时候,文件有自己的文件编码,就是汉字,或者其他国语言,以什么编码来存储 2,输出的时候,要给内容指定编码,如以网页的形势输入时<meta http-equiv ...
- 为sublime安装package control 解决乱码问题 Mac版
为sublime安装package control Mac版参考 https://sublime.wbond.net/installation 防止中文乱码其实只需要2个东东 一个GBK enc ...
随机推荐
- Leecode刷题之旅-C语言/python-263丑数
/* * @lc app=leetcode.cn id=263 lang=c * * [263] 丑数 * * https://leetcode-cn.com/problems/ugly-number ...
- Oracle入门第一天(上)——简介与安装
一.Oracle介绍 Oracle 公司是全球最大的信息管理软件及服务供应商,成立于1977年 Oracle 公司因其复杂的关系数据库产品而闻名.Oracle的关系数据库是世界第一个支持SQL语言的 ...
- 20155316 2016-2017-2 《Java程序设计》第3周学习总结
教材学习内容总结 类:创建类.使用类 基本类类型与类类型 数组 封装的概念 重载 类语法 static成员 教材学习中的问题和解决过程 1.既然数组在JAVA中就是对象,那么int[] 是否是一个类呢 ...
- 20155321 《Java程序设计》实验三 敏捷开发与XP实践
实验内容 XP基础 XP核心实践 相关工具 实验步骤 敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运营和维护上的过程.软件工程包括下列领域:软件需求分析.软件设计.软件构 ...
- Tomcat设置是否可以上传文件到服务器
今天,我做的一个点菜项目要求做一个添加菜品,把菜品的路径保存进数据库,然后将菜品的图片保存进tomcat相应的目录中. 一开始,我在客户端写的代码是直接向tomcat的目录写文件,但是会出现403错误 ...
- 【LG4609】[FJOI2016]建筑师
[LG4609][FJOI2016]建筑师 题面 洛谷 题解 (图片来源于网络) 我们将每个柱子和他右边的省略号看作一个集合 则图中共有\(a+b-2\)个集合 而原来的元素中有\(n-1\)个(除去 ...
- .Net FrameWork常用类
System类 System.Environment类: 提供有关当前环境和平台的信息以及操作它们的方法. System.Console类 :表示控制台应用程序的标准输入流.输出流和错误流. ...
- Spring学习(五)-----注入bean属性的三种方式( 1: 正常的方式 2: 快捷方式 3: “p” 模式)
在Spring中,有三种方式注入值到 bean 属性. 正常的方式 快捷方式 “p” 模式 看到一个简单的Java类,它包含两个属性 - name 和 type.稍后将使用Spring注入值到这个 b ...
- APP端测试,常见功能测试点汇总
除去每个产品和版本不同的业务需求以及功能,针对于大多数的APP的共同点和移动设备的特性,本文总结了一些APP功能测试中经常遇见,需要考虑到的测试点以共参考 一.安装和卸载 应用的安装和卸载在任何一款A ...
- 415. Valid Palindrome【LintCode java】
Description Given a string, determine if it is a palindrome, considering only alphanumeric character ...