`
webcenterol
  • 浏览: 951000 次
文章分类
社区版块
存档分类
最新评论

说说字符集

 
阅读更多

说说字符集<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

03-8-8 18:02 by leezy_2000

由于作者是美国人的缘故,我发现Windows下的几本名著(如《Windows程序设计》,Jeffrey Richter的《Windows 核心编程》)对字符集的讲解都不甚透彻。现在这里对一些易让人迷惑的问题进行澄清,并指明一些编程时容易出错的问题(我自己就犯过)。

先解释几个概念:

字符集:根据编码特性而分,字符集可分为三类。

l 窄字符集(SBCS 每个代码由一个字节进行表示,比如ANSI

l 多字节字符集(MBCS 字符集中的代码或者是单字节,或者是多字节,比如DBCSGB2312等。

l 宽字节字符集 字符集中每个字符由两个字节表示。比如UNICODE

代码页:UNICODEDBCS中由于包含的代码十分多,为了使用方便就需要对这些代码进行组织。组织的方法就是把不同国家的代码分别放入不同的代码页。

字符集与代码页的关系:由上可知,对于UNICODEDBCS,代码页是从属于字符集的。但对于SBCS类的字符集(比如ANSI)和DBCS之外的MBCS字符集(比如GB2312等)他们则只对应于一个代码页。

下面看一段潜在有问题的程序:

void ConverAndOutputString(HDC hdc,LPWSTR wstr, int length,int x,int y)

{

int nret;

int sizebuffer= 2*length;

char* lpBuffer=new char[sizebuffer];

nret=WideCharToMultiByte(CP_ACP,0,wstr , length,

lpBuffer, sizebuffer ,NULL,NULL);

TextOut(hdc,x,y, lpBuffer,nret);

delete[]lpBuffer;

}

这段程序很简单,只是把一个宽字符串转为DBCS串而后按指定的坐标进行输出。Jeffrey Richter在他的《Windows核心编程》中的第26页也用几乎的相同的方法进行字符串转换。但这段程序其实是有问题的。问题出在转换字符串时不应该硬编码指定代码页,而应该根据当前字体进行动态获取。否则在某些情况下将无法把wstr中的UNICODE字符转换到正确的代码。如果你用上述代码进行中文输出,你将很有幸看到很多问号被自动添加到你的字符串中。

解决的办法也很简单,但首先你要熟悉如下两个个API函数:

 int GetTextCharset(HDC hdc);//这个API用来得到当前字体的字符集。

 BOOL TranslateCharsetInfo(

  DWORD* pSrc, // information
  LPCHARSETINFO lpCs, // character set information
  DWORD dwFlags // translation option
 );
 这个函数可以把字符集、代码页和FONTSIGNATURE互相转换。转换后的信息
    放在lpCS中。dwFlags指明需要进行那种转换,是把字符集转换到代码页还是其他。
    特别需要注意的是,pSRC参数,这个参数在你进行字符集到代码页转换的时候,需
    要的是一个具有指针类型的值而非指向某个值的指针。因此对上述字符串输出函数你
    只要加上如下两行,就可以保证字符串在转换期间不会遇到找不到字符代码的情况。

void ConverAndOutputString(HDC hdc,LPWSTR wstr, int length,int x,int y)

{

int nret;

int sizebuffer= 2*length;

char* lpBuffer=new char[sizebuffer];

int charset=GetTextCharset(hDC);

CHARSETINFO csinfo={0};

TranslateCharsetInfo((DWORD*)charset,&csinfo,TCI_SRCCHARSET);

nret=WideCharToMultiByte(csinfo. .ciACP,0,wstr , length,

lpBuffer, sizebuffer ,NULL,NULL);

TextOut(hdc,x,y, lpBuffer,nret);

delete[]lpBuffer;

}

 最后总结一下,这篇文章的主题就是在做字符集间的转换时,一定要动态确定代码页。
所涉及函数和结构的进一步细节请参考MSDN。

分享到:
评论

相关推荐

    简单说说JAVA的String和byte[]的关系

    - **字符集兼容性**: 不同的操作系统可能使用不同的默认字符集,因此在进行转换时要确保字符集的一致性。 - **乱码问题**: 如果在编码或解码时使用的字符集不一致,可能会导致乱码问题。 - **Unicode编码**: Java中...

    唯美好句子合集,唯美说说参考.pdf

    OCR,即光学字符识别技术,可以将图片、纸质文档上的文字转换成可编辑、可搜索的电子文档。这种技术的应用,极大地便利了人们的生活,尤其是对于那些包含文字的图片或者古老书籍的数字化工作。想象一下,在寻找一些...

    易语言提取QQ说说源码-易语言

    你需要解析网页源代码,找到包含说说内容的HTML元素,并通过易语言的字符串处理函数来提取相关信息。 在"说说提取.e"这个源文件中,我们可以预见到程序会包含以下几个主要部分: 1. **登录模块**:利用易语言的...

    常用的几个字体库---ASC16、HZK16、HZK12,附HZK16的使用资料

    ASC16是一种支持ASCII字符集的16x16像素点阵字体,主要应用于早期的计算机系统或者资源有限的设备上。ASCII字符集包含了英文大小写字母、数字、标点符号以及一些特殊字符,覆盖了基本的文本输入需求。由于其小尺寸和...

    易语言计算QQ空间G_tk值

    ANSI编码是一种基于区域设置的字符编码方式,而在Windows操作系统中,UNICODE是使用两个字节表示每个字符的编码标准,能支持更广泛的字符集。在处理字符串时,如果从ANSI编码转换为UNICODE,需要进行字符编码的转换...

    UNICODE&GBK&UTF8编码查看工具

    首先,`UNICODE`,全称为Unicode Transformation Format,是一种全球通用的字符集,旨在统一世界上所有语言的字符编码,避免乱码问题。它使用16位的编码空间,理论上可以表示1048576个不同的字符,覆盖了世界上几乎...

    GBK UTF8 UNICODE C++

    GBK编码是基于ASCII的,因此它兼容ASCII字符集,但不支持Unicode,这可能会导致在处理多语言文本时出现问题。 其次,Unicode 是一个国际标准,旨在为世界上所有语言提供一个统一的字符编码方式。Unicode通过分配...

    C#实用类集-DotNet.Utilities

    这个类库可能包含了对AES、DES、RSA等常见加密算法的支持,允许开发者对字符串、文件或流进行加密和解密。这些方法通常提供了一种安全的方式来保护敏感信息,确保数据在传输或存储过程中的安全性。 再来说说XML操作...

    关于汉字编码方面的知识,大部分是询问人工智能机器人得到的回答

    接着,我们来到Unicode,这是一个统一的字符集,包含了世界上几乎所有的文字,包括汉字。Unicode采用固定长度的编码,常见的有UTF-8、UTF-16和UTF-32。其中,UTF-8是最广泛使用的,它使用1至4个字节来表示一个字符,...

    2021春招MySQL高频面试题.pdf

    `来查看当前数据库的字符集。 #### 11. 如何查看当前数据库版本 使用命令`SELECT VERSION();`来查看当前MySQL数据库版本。 #### 12. 如何查看当前登录的用户。 使用命令`SELECT USER();`来查看当前登录的用户名...

    XMLSPY 2010 企业版

    支持Unicode、多字符集,支持Well-formed和Validated两种类型的XML文档,支持NewsML等多种标准XML文档的所见即所得的编辑,同时提供了强有力的样式表设计。  Altova希望其最新发布的XMLSpy会让XML代码的处理更容易...

    Java面试题集(2017修订版).doc

    - 可以,因为Java的`char`类型占用16位,可以表示Unicode字符集,包括中文汉字。 9. 用最有效率的方法算出2乘以8等于几? - 直接写`2 * 8`是最简单的,Java会快速计算这个基本操作。 10. 冒泡排序实现: - 冒泡...

    Java面试问题集167页.pdf

    Java 面试问题集 Java 是一种广泛使用的编程语言,具有强大、灵活、跨平台等特点。Java 面试是一种常见的编程面试形式,旨在考察候选人的 Java 编程知识和技能。本文档提供了 20 个 Java 面试问题,涵盖了 Java ...

    各种进制的转换计算机基础呀.pdf

    十六进制使用了0-9和A-F的字符集,其中A-F代表十进制中的10-15。十六进制在表示大型二进制数时非常方便,因其可以将很长的二进制数简化为较短的形式。 **二进制转十六进制**:采用“取四合一法”,每四位二进制数...

    字模提取软件 升级版 查看字的内码 可以造字

    总结来说,这款升级版的字模提取软件集字模提取、内码查看和个性化造字于一身,同时还具备批量处理能力,对于设计师、程序员、排版师等专业人士以及对文字艺术有兴趣的普通用户来说,都是一个极具价值的工具。...

    Mysql 数据库面试专题集

    3. 字符串类型(String)。 4. 日期时间类型(Datetime)。 5. 布尔类型(Boolean)。 存储引擎 Mysql 的存储引擎包括: 1. InnoDB。 2. MyISAM。 3. MEMORY。 InnoDB 和 MyISAM 的区别 InnoDB 和 MyISAM 的...

    encoding:编码,解析和填充的实验

    ASCII仅支持英文字符,而Unicode则覆盖了世界上大多数语言的字符,其中UTF-8是目前最广泛使用的编码方式,它能表示Unicode字符集。在Python中,我们可以通过`encode()`函数将字符串转换为字节流,例如`str.encode('...

    易语言源码易语言嵌入汇编十六进制转长整数源码.rar

    易语言源码是由易语言编写的应用程序的原始指令集,包含了程序的所有逻辑和功能。通过阅读和分析源码,开发者可以理解程序的工作原理,进行修改、优化或二次开发。这个压缩包中的源码应该是一个实现了将十六进制数字...

Global site tag (gtag.js) - Google Analytics