linux 宽字符与多字节字符之间的转换
短信中文编码的问题
字符集之:短信中文编码的问题收藏SMS是由Esti 所制定的一个规范(GSM 03.40 和GSM 03.38)。
有两种方式来发送和接收SMS消息:文本模式或者PDU(protocol description unit)模式。
文本模式只能发送普通的ASCII字符,而要发送图片、铃声、其它编码的字符(如中文)就必须采用PDU模式。
PDU模式中,可以采用三种编码方式来编码要发送的内容,分别是7-bit编码、8-bit编码、16-bit编码。
7-bit编码用于发送普通的ASCII字符;8-bit编码通常用于发送数据消息,比如图片和铃声等;而16-bit编码用于发送Unicode字符。
在这三种编码方式下,可以发送的最大字符数分别是160、140、70。
若要发送中文(或日文等),必须采用PDU模式的Unicode编码方式。
我最近参与了一个在linux下收发短信的项目。
其中,需要实现中文的发送和接收。
由于原来没有中文编码、Unicode编码的经验,所以查了一些资料,也在一些论坛上提了一些问题。
现在把它整理出来,希望对以后再做类似项目的朋友有个帮助。
我写的比较简单,关于PDU 的规范,可以看这里:/sustain/SMS_PDU-mode.p df ,或者去wavecom的网站上找找看。
1、GB2312 编码到Unicode 编码的转换在Redhat 7.3系统上,默认是用GB2312编码保存中文字符的(对于中英文混合的文本也是如此)。
所以首先需要把GB2312 编码的字符串转换到Unicode编码的字符串。
G B2312编码是一种多字节编码方式,对于中文,用2个字节表示,对于英文,用1个字节表示,就是英文的ascii码。
(注:我没有仔细看过GB2312编码的规范,以上理解是实际开发中得出来的,不能保证正确性)。
Unicode编码是双字节编码方式,对所有字符,都采用2个字节编码。
在linux平台上,GB2312编码到Unicode编码的转换,可以有三种实现方式(或者更多):1)、用mbstowcs () 函数。
超星阅读器安全评测报告
测试报告题目:超星阅读器pdg2.dll ActiveX栈溢出0day漏洞报告报告类型:漏洞分析报告提交人:张东辉[shineast]报告人背景:西安交通大学智能网络与网络安全教育部重点实验室,看雪软件安全评测中心联系方式:/shineastdh报告创建日期:2008年8月4日最后修改日期:2008年8月4日测试目标名称:超星阅读器测试目标信息:从超星的网站(/downland_index.asp)下载最新版的超星阅读器,版本4.0,更新日期是2007年5月11日,文件大小为6.8MB。
测试环境和配置:INTEL CPU,内存1G,Windows XP安全评测类别得分:(最大值2)项目:漏洞的利用:危险等级2 (漏洞会被攻击者利用威胁软件使用者个人信息安全)分析和测试工具:OLLYDBG 1.10测试周期:1天主要存在的安全性问题:该软件注册的pdg2.dll控件存在多处缓冲区溢出漏洞。
简短摘要:本报告详细分析存在于pdg2.dll ActiveX中的多处安全漏洞,并给出了对应的技术解决方案,希望能够引超星公司的重视,并尽快修复。
报告正文内容:尊敬的超星公司:您好!我是西安交通大学智能网络与网络安全教育部重点实验室的研究员,经过我们的对贵公司产品——超星阅读器的安全测试,发现该软件注册的pdg2.dll控件存在多处缓冲区溢出漏洞。
这给使用超星的广大用户带来极大的安全隐患。
本报告将详细分析存在于pdg2.dll ActiveX中的多处安全漏洞,希望能够引起贵公司的重视,并尽快修复。
漏洞分析从超星的网站(/downland_index.asp)下载最新版的超星阅读器,版本4.0,更新日期是2007年5月11日,文件大小为6.8MB。
下载后安装之,用COM Explorer 可以看到超星在你的系统上注册的几个ActiveX控件。
其中有一个是,pdg2.dll:该控件CLSID是{7F5E27CE-4A5C-11D3-9232-0000B48A05B2};文件路径在C:\WINDOWS\system32\pdg2.dll;并且可以看出这个dll确实是最新4.0版的。
linux宽字符与多字节字符之间的转换
linux宽字符与多字节字符之间的转换linux 宽字符与多字节字符之间的转换2008-07-17 09:411237人阅读评论(0)收藏举报最近再调linux下证书验证问题,由于要对客户端发送过来的证书在服务器上与根证书进行认证,所以在读取证书、验证证书时设计到了编码转换问题。
在windows下,使用MultiByteT oWideChar和WideCharT oMultiByte没有问题,但在linux下,不存在这两个函数,于是我们想到了用wcstombs和mbstowcs两个函数,但经试验,不能得到正确的结果,后来,经分析,得到,在windows下wchar_t为2字节,而在linux wchar_t为4字节,我们提取的证书编码为2字节的宽字符,所以不能正确地进行转换。
不得不,只能使用libiconv 进行转换。
iconv函数族的头文件是iconv.h。
#includeiconv函数族有三个函数,原型如下:(1) iconv_t iconv_open(const char *tocode, const char *fromcode);此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。
(2) size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t*outbytesleft);此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft 用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。
(3) int iconv_close(iconv_t cd);此函数用于关闭转换句柄,释放资源。
经过测试,使用这转换函数需要注意的有以下几点:1、宽字节存在big-endian和little-endian之分,那使用宽字符编码时使用的编码名字也不一样,例如我们用的UCS-2编码,那有“UCS-2”和“UCS-2-INTERNAL”之分;2、iconv中的两个长度在运行完函数后,分别为分配缓存剩余字节的大小;3、而两个指针分别指向转换后字符串的尾部,所以在进行转换之前,应该保留缓存的原始指针,在转换后,用这两个指针减去原始指针,那就是已转换的字节长度和转换后的字节长度。
MultiByteToWideChar和WideCharToMultiByte用法详解
MultiByteToWideChar和WideCharToMultiByte用法详解注意:这两个函数是由Windows提供的转换函数,不具有通用性C语言提供的转换函数为mbstowcs()/wcstombs()一、函数简单介绍涉及到的头文件:函数所在头文件:windows.h#include <windows.h>wchar_t类型所需头文件:wchar.h#include <wchar.h>( 1 ) MultiByteToWideChar()函数功能:该函数映射一个字符串到一个宽字符(unicode)的字符串。
由该函数映射的字符串没必要是多字节字符组。
函数原型:int MultiByteToWideChar(UINT CodePage,DWORD dwFlags,LPCSTR lpMultiByteStr,int cchMultiByte,LPWSTR lpWideCharStr,int cchWideChar);参数:1> CodePage:指定执行转换的多字节字符所使用的字符集这个参数可以为系统已安装或有效的任何字符集所给定的值。
你也可以指定其为下面的任意一值:2> dwFlags:一组位标记,用以指出是否未转换成预作或宽字符(若组合形式存在),是否使用象形文字替代控制字符,以及如何处理无效字符。
你可以指定下面是标记常量的组合,含义如下:MB_PRECOMPOSED:通常使用预作字符——就是说,由一个基本字符和一个非空字符组成的字符只有一个单一的字符值。
这是缺省的转换选择。
不能与MB_COMPOSITE值一起使用。
MB_COMPOSITE:通常使用组合字符——就是说,由一个基本字符和一个非空字符组成的字符分别有不同的字符值。
不能与MB_PRECOMPOSED值一起使用。
MB_ERR_INVALID_CHARS:如果函数遇到无效的输入字符,它将运行失败,且GetLastErro返回ERROR_NO_UNICODE_TRANSLATION 值。
浅析Solaris 移植到linux 的大小字节序问题
浅析Solaris移植到linux的大小字节序问题市场部/林铮一. 前言随着 Linux 操作系统的逐渐普及,很多公司都在考虑如何将已有的Solaris应用程序和开发环境移植到 Linux上。
本文对C/C++语言从solaris(32bit)移植到linux(32bit)环境上的过程中,可能遇到的大小字节序的问题和解决方案进行说明。
当有2个字节以上的数值存入计算机内存或是文档的时候,又或是进行数据转送的时候,我们要考虑先把哪个位置的字节存入内存地址的高位?或是要先转送哪个位置的数据?像这样的次序考虑,就称为endian或者是byte order(字节序)。
Little endian(小端):按照最低字节在地址最低位,最高字节在地址最高位的顺序排列。
Big endian(大端):按照最高字节在地址最低位,最低字节在地址最高位的顺序排列。
字节序是根据CPU的构造来来决定的。
一般来说,Solaris 是大端,而Linux则是小端。
比如,要将这个为0x12345678的32bit(4字节)的16进制常量,其按照不同的字节序存入内存时,其排列如下:Big endian(Solaris):内容 12345678地址 0 1 2 3 Little endian(Linux):内容 78563412地址 0 1 2 3 二. 大小字节序对移植的影响字节序的移植性问题的话,只对short, int, long, float, double, pointer等多字节的类型有影响,而对单字节(char 型等),或是字符串是没有影响的。
例如:int size;char data[7];把十进制数10,和字符串"012345"分别赋值到size和data,在字节序不同的机器中,对size和data进行二进制转送,结果如下:像这样的字节序的不同,当在字节序不同的机器(OS)间进行二进制数据文档共享的时候,或是通过网络进行通信的时候,就会产生问题。
char与wchar_t之间的转换
char*与wchar_t*之间的转换1.问题描述char字符与wchar_t字符由于编码不同,所以在char*和wchar_t之间使用强制类型转换达不到正确转换字符串的目的。
考察如下程序。
#include<iostream>usingnamespace std;int main(){wchar_t* str=L"ABC我们";char* s=(char*)str;cout<<s<<endl;}输出结果出错:只输出A。
经过强制类型转换,s指向了宽字符编码字符串,字符串数据没有发生任何变化,只是用多字节字符字符编码重新对它进行解释,自然输出的结果是错误的。
2.char*与wchar_t*之间相互转换要想将宽字符编码字符串转换成多字节编码字符串(或者反过来),必须先读懂原来的字符串,然后再重新对它进行编码。
只有这样才能到达转换的目的。
由于宽字符可以表示多国语言的文字,因此,下文的讨论限于中文的宽字符串与多字节字符串之间的相互转换。
在不同的才做系统上,有一些特殊的库函数可以用来进行字符编码之间的转换。
在VC++中,其中关键的几个函数是setlocale()、wcstombs_s()和mbstowcs_s()。
2.1关键函数简介(1)setlocale()功能:配置地域化信息头文件:#include <locale.h>函数原型:char *setlocale (int category, const char * locale);函数参数:category表示对本地化的某项内容进行设置,可取如下值:LC_ALL 包括下面的全部选项都要;LC_COLLATE 配置字符串比较;C_CTYPE 配置字符类别及转换,例如全变大写strtoupper();LC_MONETARY 配置金融货币;LC_NUMERIC 配置小数点后的位数;LC_TIME 配置时间日期格式,与strftime() 合用。
多字节与宽字节stringwstring互转
多字节与宽字节stringwstring互转多字节字符集(MBCS,Multi-Byte Chactacter Set):指⽤多个字节来表⽰⼀个字符的字符编码集合。
⼀般英⽂字母⽤1Byte,汉语等⽤2Byte来表⽰。
兼容ASCII 127。
在最初的时候,Internet上只有⼀种字符集——ANSI的ASCII字符集,它使⽤7 bits来表⽰⼀个字符,总共表⽰128个字符,其中包括了英⽂字母、数字、标点符号等常⽤字符。
为了扩充,以⽤于显⽰本国的语⾔,不同的国家和地区制定了不同的标准,由此产⽣了 GB2312, BIG5, JIS 等各⾃的编码标准。
这些使⽤ 2个来代表⼀个字符的各种汉字延伸编码⽅式,称为 ANSI 编码,⼜称为"MBCS(Muilti-Bytes Charecter Set,多字节字符集)"。
不同 ANSI 编码之间互不兼容,当信息在国际间交流时,⽆法将属于两种语⾔的⽂字,存储在同⼀段 ANSI 编码的⽂本中。
⼀个很⼤的缺点是,同⼀个编码值,在不同的编码体系⾥代表着不同的字。
这样就容易造成混乱。
导致了unicode码的诞⽣。
宽字节字符集:⼀般指Unicode编码的字符集,Unicode称为统⼀码或万国码,统⼀了不同国家的字符编码。
Unicode通常⽤两个字节表⽰⼀个字符,原有的英⽂编码从单字节变成双字节,只需要把⾼字节全部填为0就可以。
为了统⼀所有⽂字的编码,Unicode应运⽽⽣。
Unicode把所有语⾔都统⼀到⼀套编码⾥,这样就不会再有乱码问题了。
Unicode固然统⼀了编码⽅式,但是它的效率不⾼,⽐如UCS-4(Unicode的标准之⼀)规定⽤4个字节存储⼀个符号,那么每个英⽂字母前都必然有三个字节是0,这对存储和传输来说都很耗资源。
为了提⾼Unicode的编码效率,于是就出现了UTF-8编码。
UTF-8可以根据不同的符号⾃动选择编码的长短。
⽐如英⽂字母可以只⽤1个字节就够了。
GCC编译时头文件路径问题
GCC_EXEC_PREFIX 的默认设置为 prefix /lib/gcc-lib/ ,这里的 prefix 是安装编译程序时 configure 脚本指定的名字。该前缀也用于定位标准连接程序文件,包含进来作为可执行程序的一部分。 如果使用 -B 命令行TH 。
方法一:在配置文件/etc/ld.so.conf中指定动态库搜索路径。
可以通过编辑配置文件/etc/ld.so.conf来指定动态库的搜索路径,该文件中每行为一个动态库搜索路径。每次编辑完该文件后,都必须运行命令ldconfig使修改后的配置生效。我们通过例1来说明该方法。
例1:
我们通过以下命令用源程序pos_conf.c(见程序1)来创建动态库 libpos.so,详细创建过程请参考文[1]。
网友回复:你引用的是内核下的头文件.
不在/usr/include下.
在: /usr/src/kernels/2.6.18-8.el5-x86_64/include/linux/module.h 下面... 中间的版本号是不一样的...你选你的就行了..
网友回复:请问楼上为什么是在/usr/src/kernels/2.6.18-8.el5-x86_64/include/linux/module.h呢?我查了一下环境变量,没有看到关于头文件的环境变量。gcc是如何知道头文件的位置的?
} 程序1: pos_conf.c
linux中将字符串转换为数组的方法-定义说明解析
linux中将字符串转换为数组的方法-概述说明以及解释1.引言1.1 概述概述部分应该对文章主题进行简要的介绍和概括。
对于这篇文章,我们可以概述如下:在Linux系统中,经常会遇到需要将字符串转换为数组的情况。
无论是在Shell脚本编程还是在命令行操作中,对字符串进行拆分并存储到数组中是一项常见的任务。
本文将介绍三种常用的方法来实现这一目标。
方法一是使用split函数进行字符串分割,该函数能够根据指定的分隔符将字符串拆分成多个子字符串,并将其存储到数组中。
这种方法简单直接,适合处理简单的字符串拆分需求。
方法二是使用正则表达式进行字符串匹配,通过正则表达式的特性,我们可以定义更复杂的拆分规则。
这种方法更加灵活,适用于处理表达式较为复杂的字符串拆分情况。
方法三是使用循环遍历字符串进行字符拆分,通过遍历字符串中的每个字符并判断其是否为分隔符,将字符串按照指定规则进行拆分并存储到数组中。
这种方法相对较为繁琐,但在某些情况下可以提供更高的灵活性。
本文将详细介绍上述三种方法的具体实现步骤,并对它们的优缺点进行分析。
最后,我们将讨论这些方法的应用场景,以帮助读者根据实际需求选择合适的方法。
通过本文的学习,读者将能够掌握在Linux中将字符串转换为数组的方法,为其后续的开发和操作提供更多的可能性。
1.2 文章结构文章将分为以下几个部分:1. 引言:对Linux中将字符串转换为数组的方法进行概述,并介绍本文的目的和总结。
2. 正文:详细介绍了三种方法将字符串转换为数组的步骤和具体实现。
2.1 方法一:使用split函数进行字符串分割。
这一部分将介绍split 函数的使用方法,并提供示例代码演示如何将字符串根据指定的分隔符进行分割,并将结果存储到数组中。
2.2 方法二:使用正则表达式进行字符串匹配。
这一部分将解释如何使用正则表达式来匹配字符串,并提取其中的内容,并通过示例代码展示如何将匹配到的结果存储到数组中。
2.3 方法三:使用循环遍历字符串进行字符拆分。
高低字节序转换(htonl、ntohl、htons、ntohs函数)
高低字节序转换(htonl、ntohl、htons、ntohs函数)Part 1: htons函数具体解释在Linux和Windows网络编程时需要用到htons和htonl函数,用来将主机字节顺序转换为网络字节顺序。
在Intel机器下,执行以下程序int main()...{printf("%d /n",htons(16));return 0;}得到的结果是4096,初一看感觉很怪。
解释如下,数字16的16进制表示为0x0010,数字4096的16进制表示为0x1000。
由于Intel机器是小尾端,存储数字16时实际顺序为1000,存储4096时实际顺序为0010。
因此在发送网络包时为了报文中数据为0010,需要经过htons进行字节转换。
如果用IBM 等大尾端机器,则没有这种字节顺序转换,但为了程序的可移植性,也最好用这个函数。
另外用注意,数字所占位数小于或等于一个字节(8 bits)时,不要用htons转换。
这是因为对于主机来说,大小尾端的最小单位为字节(byte)。
Part 2: 大小端模式不同的CPU有不同的字节序类型这些字节序是指整数在内存中保存的顺序这个叫做主机序最常见的有两种1. Little endian:将低序字节存储在起始地址2. Big endian:将高序字节存储在起始地址LE little-endian最符合人的思维的字节序地址低位存储值的低位地址高位存储值的高位怎么讲是最符合人的思维的字节序,是因为从人的第一观感来说低位值小,就应该放在内存地址小的地方,也即内存地址低位反之,高位值就应该放在内存地址大的地方,也即内存地址高位BE big-endian最直观的字节序地址低位存储值的高位地址高位存储值的低位为什么说直观,不要考虑对应关系只需要把内存地址从左到右按照由低到高的顺序写出把值按照通常的高位到低位的顺序写出两者对照,一个字节一个字节的填充进去例子:在内存中双字0x01020304(DWORD)的存储方式内存地址4000 4001 4002 4003LE 04 03 02 01BE 01 02 03 04例子:如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为big-endian little-endian0x0000 0x12 0xcd0x0001 0x23 0xab0x0002 0xab 0x340x0003 0xcd 0x12x86系列CPU都是little-endian的字节序.网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。
linux 二进制比较命令
linux 二进制比较命令Linux二进制比较命令在Linux系统中,二进制比较命令是一种用于对比两个二进制文件的工具。
它可以帮助我们快速准确地判断两个文件是否相同,以及找出差异之处。
本文将介绍常用的二进制比较命令,并详细说明其使用方法和注意事项。
1. cmp命令cmp命令是Linux系统中最基本的二进制比较命令之一。
它可以逐字节地比较两个文件,并在找到不同字节时输出其位置和差异值。
使用cmp命令的基本语法如下:cmp [选项] 文件1 文件2其中,选项可以是以下之一:- b:以字节为单位进行比较(默认为块)。
- l:以长整型为单位进行比较。
- s:不输出任何错误信息。
例如,要比较文件file1和file2:cmp file1 file2cmp命令将输出不同字节的位置和差异值,如果两个文件完全相同,则不会输出任何信息。
2. diff命令diff命令是另一个常用的二进制比较命令,它可以逐行比较两个文件的内容,并输出不同之处。
使用diff命令的基本语法如下:diff [选项] 文件1 文件2其中,选项可以是以下之一:- b:忽略空白字符的差异。
- c:输出上下文格式的差异结果。
- q:仅显示有无差异,不显示具体内容。
例如,要比较文件file1和file2:diff file1 file2diff命令将输出不同行的具体内容,以及差异所在的行号。
3. od命令od命令是Linux系统中用于显示文件内容的命令,它可以将文件内容以不同的进制形式显示出来。
在二进制比较中,od命令可以将文件内容转换为十六进制形式,以便于观察和比较。
使用od命令的基本语法如下:od [选项] 文件其中,选项可以是以下之一:- x:以十六进制形式显示文件内容。
- c:以字符形式显示文件内容。
例如,要将文件file以十六进制形式显示出来:od -x fileod命令将输出文件内容的十六进制表示,并且每个字节都有对应的位置信息。
4. md5sum命令md5sum命令是Linux系统中用于计算文件MD5值的命令,它可以将文件内容转换为一个唯一的128位哈希值。
字符串和bytes形式的转换
字符串和bytes形式的转换⽬录1.bytes类型转化成str的2种⽅式:第⼀种:data = b'hello world'data = str(data,encoding='utf-8')print(data,type(data))>>>>>>>>>>>>>>>>>>>>>>>>hello world <class 'str'>第⼆种:data = b'hello world's1= data.decode('utf-8')print(s1,type(s1))>>>>>>>>>>>>>>>>>>>>>>>>>>hello world <class 'str'>2.字符串类型转化成bytes的2种⽅式第⼀种⽅式:data = 'hello world'data = bytes(data,encoding='utf-8')print(data,type(data))>>>>>>>>>>>>>>>>>>>>>>>>b'hello world' <class 'bytes'>第⼆种⽅式:data = 'hello world'data= data.encode('utf-8')print(data,type(data))>>>>>>>>>>>>>>>>>>>>>>>>>>b'hello world' <class 'bytes'>。
c语言 url转换宽字符处理
C语言中URL转换宽字符处理C语言作为一种通用的编程语言,具有较高的灵活性和通用性,可以处理各种复杂的编程任务。
在网络编程中,URL的处理是一个常见的需求,而在C语言中处理URL时,可能需要考虑到宽字符的处理。
本文将从C语言中URL的转换和宽字符处理两个方面展开讨论。
一、URL的转换1. URL编码URL编码是指将URL中的特殊字符转换成特定的编码形式,以便于在网络传输过程中不产生歧义。
在C语言中,可以使用urlencode函数来进行URL编码,该函数的定义如下:```cchar *urlencode(const char *src);```该函数接受一个源字符串作为参数,返回一个经过URL编码后的字符串。
对于字符串"hello world",经过urlencode函数编码后的结果为"hello20world"。
2. URL解码URL解码是指将URL中的编码形式的字符还原成原始的特殊字符。
在C语言中,可以使用urldecode函数来进行URL解码,该函数的定义如下:```cchar *urldecode(const char *src);```该函数接受一个经过URL编码后的字符串作为参数,返回一个解码后的字符串。
对于字符串"hello20world",经过urldecode函数解码后的结果为"hello world"。
二、宽字符处理1. 宽字符与多字节字符在C语言中,字符可以分为宽字符和多字节字符两种类型。
宽字符是指每个字符占用多个字节的字符,而多字节字符是指每个字符占用一个字节的字符。
在处理URL时,需要考虑到URL中可能包含非ASCII 字符,而非ASCII字符通常是宽字符。
2. 宽字符转换在C语言中,可以使用mbstowcs函数将多字节字符转换成宽字符,该函数的定义如下:```csize_t mbstowcs(wchar_t *dest, const char *src, size_t n);```该函数接受一个多字节字符作为参数,返回一个宽字符序列。
16位有符号数转两字节算法
16位有符号数转两字节算法
“16位有符号数转两字节算法”这句话的意思是,将一个16位有符号数转换为一个两字节(16位)的数值表示的算法。
16位有符号数转两字节算法通常涉及以下步骤:
1.确定源和目标数据类型的长度。
在这种情况下,源数据类型是一个16位有
符号整数,目标数据类型是两字节(16位)的整数。
2.检查源数据是否能够适应目标数据类型的范围。
由于目标数据类型是16位,
因此需要确保源数据不会超出该范围。
3.如果源数据在目标数据类型的范围内,则可以直接进行转换。
否则,需要
进行溢出处理或截断。
4.使用位操作和移位来执行转换。
将源数据的每个字节复制到目标数据的相
应位置。
5.处理符号扩展。
如果源数据是有符号的,需要在转换过程中保留符号信息。
通常使用最高位(符号位)来表示符号。
6.返回转换后的结果。
总结来说,“16位有符号数转两字节算法”是指将一个16位有符号整数转换为一个两字节(16位)整数的算法。
这个算法涉及到确定数据类型的长度、检查溢出情况、执行转换操作以及处理符号扩展等步骤。
Linux下实现UTF-8和GB2312互相转换的方法
Linux下实现UTF-8和GB2312互相转换的⽅法实例如下:#include<iconv.h> #include <stdio.h>#include<iconv.h>using namespace std;int utf8togb2312(const char *sourcebuf,size_t sourcelen,char *destbuf,size_t destlen) {iconv_t cd;if( (cd = iconv_open("gb2312","utf-8")) ==0 )return -1;memset(destbuf,0,destlen);const char **source = &sourcebuf;char **dest = &destbuf;if(-1 == iconv(cd,source,&sourcelen,dest,&destlen))return -1;iconv_close(cd);return 0;}int gb2312toutf8(const char *sourcebuf,size_t sourcelen,char *destbuf,size_t destlen) {iconv_t cd; if( (cd = iconv_open("utf-8","gb2312")) ==0 )return -1; memset(destbuf,0,destlen);const char **source = &sourcebuf;char **dest = &destbuf;if(-1 == iconv(cd,source,&sourcelen,dest,&destlen))return -1;iconv_close(cd);return 0;}int main() {char line[80];char dest_gb2312[200];char dest_utf8[200];int ret ;FILE *fp = fopen("love.txt","r");if(fp == NULL){printf("oh my dear,open fail...\n");return 1;}memset(line,0,80);if( NULL == fgets(line,80,fp)){printf("oh fgets fail...\n");return 2;}printf( "----- :%s\n",line );ret = gb2312toutf8(line,strlen(line),dest_gb2312,200);// ret = gb2312toutf8(dest_gb2312,strlen(dest_gb2312),dest_utf8,80);printf( "ret=%d\n\n\n",ret);printf( "gb2312:%s\n",line );printf( " utf-8:%s\n\n\n\n\n\n", dest_gb2312 );ret = utf8togb2312(dest_gb2312,strlen(dest_gb2312),dest_utf8,200);printf( "ret=%d\n\n\n ",ret);printf( " utf-8:%s\n ",dest_gb2312);printf( "gb2312:%s\n ",dest_utf8);return 0;}以上就是⼩编为⼤家带来的Linux下实现UTF-8和GB2312互相转换的⽅法全部内容了,希望⼤家多多⽀持~。
linux中Bit、Byte、KB、MB、GB、TB之间的换算
linux中Bit、Byte、KB、MB、GB、TB之间的换算
换算
1 Byte = 8 Bits(即 1B=8b)
1 KB = 1024 Bytes
1 MB = 1024 KB
1 GB = 1024 MB
1 TB = 1024 GB
基本概念
Bit意为“位”或“⽐特”,是计算机运算的基础,属于⼆进制的范畴;
Byte意为“字节”,是计算机⽂件⼤⼩的基本计算单位;
这两者应⽤的场合不同。
通常⽤bit来作数据传输的单位,因为物理层,数据链路层的传输对于⽤户是透明的,⽽这种通信传输是基于⼆进制的传输。
在应⽤层通常是⽤byte来作单位,表⽰⽂件的⼤⼩,在⽤户看来就是可见的数据⼤⼩。
⽐如⼀个字符就是1byte,如果是汉字,则是2byte
实际应⽤
字节是内存的基本单位,也是编址单位,例如,某计算机的内存是4GB,指的就是该计算机的内存中共有4×1024×1024×1024个字节。
常用的宽字符函数
常用的宽字符函数_tcsrchr从末尾开始查找常用的宽字符函数由于Windows NT/2000/XP采用的是Unicode字符编码,字符都是双字节的。
所以在MFC编程中,一般需要使用双字节的字符类型wchar_t和对应的字符串及其指针类型LPCWSTR和LPCTSTR,并在常数字符串前添加了L转换符,串长计算函数不能用strlen而改用wcslen,串格式打印函数也不能用sprintf,而是改用swprintf。
wchar_t类型,在标准C++中为内置的数据类型和关键字;在C99标准中则为typedef类型,其等价的数据类型与具体的实现有关,在Win32和VC中定义为:typedef unsigned short wchar_t;下面是若干常用的宽字符函数(包含在ISO C99 / ISO C++的标准库中):#includesize_t wcslen(const wchar_t *s);int wprintf(const wchar_t * restrict format, ...);int wscanf(const wchar_t * restrict format, ...);int swprintf(wchar_t * restrict s, size_t n, const wchar_t * restrict format, ...);int swscanf(const wchar_t * restrict s, const wchar_t * restrict format, ...);long int wcstol(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base);float wcstof(const wchar_t * restrict nptr, wchar_t ** restrict endptr);double wcstod(const wchar_t * restrict nptr, wchar_t ** restrict endptr);#includeerrno_t _itow_s( int value, wchar_t *buffer, size_t sizeInCharacters, int radix );errno_t _ultow_s( unsigned long value, wchar_t *str, size_t sizeOfstr, int radix );多字节-multibyte宽字符-widechar非英语系的大部分语言,存在无法用有限的ascii字符表达的问题。
宽字符——精选推荐
宽字符1.关于字符编码1)ASCII1】ASCII 码使⽤指定的 7 位或 8 位⼆进制数组合来表⽰ 128 或 256 种可能的字符。
2】标准 ASCII 码使⽤ 7 位⼆进制数来表⽰所有的⼤写和⼩写字母,数字 0 到 9、标点符号,以及在美式英语中使⽤的特殊控制字符。
3】扩展 ASCII 码允许将每个字符的第 8 位⽤于确定附加的 128 个特殊符号字符、外来语字母和图形符号。
标志ascii表的部分:拓展ascii表:2)gb2312标准的ascii占⼀个字节8位,且最⾼位为0;拓展ascii表8位,最⾼位为1;如果要表是中⽂字符,ascii不够⽤,因为⽆法表⽰数量庞⼤的汉字;为了解决这⼀问题,中国的专家使⽤gb2312;gb2312⽤两个字节表⽰⼀个汉字;为了不⾄于⽆法区分标准ascii表,两个字符的最⾼位都是1;gb2312编码中去掉了拓展ascii表,也就是使⽤gb2312编码时不要拓展ascii表了;gb2312编码规则:计算机发明之处及后⾯很长⼀段时间,只⽤应⽤于美国及西⽅⼀些发达国家,ASCII能够很好满⾜⽤户的需求。
但是当天朝也有了计算机之后,为了显⽰中⽂,必须设计⼀套编码规则⽤于将汉字转换为计算机可以接受的数字系统的数。
天朝专家把那些127号之后的奇异符号们(即EASCII)取消掉,规定:⼀个⼩于127的字符的意义与原来相同,但两个⼤于127的字符连在⼀起时,就表⽰⼀个汉字,前⾯的⼀个字节(他称之为⾼字节)从0xA1⽤到 0xF7,后⾯⼀个字节(低字节)从0xA1到0xFE,这样我们就可以组合出⼤约7000多个简体汉字了。
在这些编码⾥,还把数学符号、罗马希腊的字母、⽇⽂的假名们都编进去了,连在ASCII⾥本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全⾓"字符,⽽原来在127号以下的那些就叫"半⾓"字符了。
部分gb2312表:如图:保存在内存中的字符2.宽字符使⽤ascii可能出现的问题1】乱码对于中⽂来说,编码⽅式为gb2312,将2个拓展ascii字符合成1个汉字;但其它编码⽅式也使⽤同样的⽅式,例如⽇⽂、韩⽂之类的;也就是说,同样的两个字节,在使⽤不同的编码⽅式时表⽰的是不同的字符;因此可能出现乱码;乱码的本质就是多个符号对应同⼀个⼆进制数据;2】字符个数的计算问题例如:hello世界该字符串有7个字符;实际计算出来的是9个字符;因为⼀个汉字占了2个字符,5+2x2=9;为了解决这⼀问题,联合国的某⼀组织推出了宽字符Unicode;Unicode每⼀个字符都⽤2个字节来表⽰;Unicode只有⼀个字符集,将所有国家的常⽤符号都记录在这个字符集中;ps:字符集本质上就是⼀张表,⽤来记录某个符号对应某个⼆进制数;Unicode记录的只是所有国家常⽤符号,⽆法解决所有问题;因为2个字节最多记录65536个符号,不可能将所有符号完全包括;因为Unicode只有⼀张表,使⽤Unicode不会出现⼀个⼆进制数对应多个符号的问题,从⽽解决了乱码;例如常⽤的utf-8就是在Unicode的基础上扩展⽽来的字符集;3.c语⾔中的宽字符1)宽字符的使⽤"中"字的编码:ASCII:d6 d0 //拓展的ascii也就是gb2312UNICODE:4e 2d观察内存中的值,为什么会出现这种情况?char x = '中'; //内存中只会保存d0,因为char只能存⼀个字节,⽽中⽂字符占2个字节,只保存⼀半;wchar_t x1 = '中'; //内存中为 d6 d0,也就是对应gb2312表的d0d6,windows中是反着存的;wchar_t宽度是2个字节,⾜够存中⽂字符;如何告诉编译器我们要使⽤的是Unicode的那张表呢?wchar_t x1 = L'中'; //内存中是4e2d,字符前⾯加L告诉编译器查Unicode表;2)宽字符串的使⽤char x[] = "中国";//d6 d0 b9 fa 00 使⽤拓展ASCII编码表以00(\0)结尾wchar_t x1[] = L"中国";//2d 4e fd 56 00 00 使⽤UNICODE编码表以00 00(\0\0)结尾3)在控制台中输出宽字符char x[] = "中国";wchar_t x1[] = L"中国";printf("%s\n",x); //使⽤控制台默认的编码wprintf(L"%s\n",x1); //默认使⽤英⽂,可能⽆法正常输出中⽂告诉编译器,使⽤控制台默认的编码格式1】包含头⽂件 #include <locale.h>2】 setlocale(LC_ALL,""); //使⽤控制台默认的编码,第⼆个参数为""将区操作系统的语⾔区,也就是中⽂语⾔区4)取宽字符串长度需要引⼊头⽂件:#include"string.h"char x[] = "中A国";wchar_t x1[] = L"中A国";strlen(x); //取得多字节字符串中字符长度,不包含 00 ;结果是5,中⽂占2字节,英⽂占1字节,不算结尾符00wcslen(x1); //取得多字节字符串中字符长度,不包含 00 00 ;结果是3,unicode中英⽂都占2字节,将2字节当做1个字符,不包含结尾的0000,也就是3个字符返回3 5)字符串复制strcpy(a,b)->将字符串b复制到字符串a处,会将b的结束标记00也复制过去->本质上就是封装后的memcpy(),只不过是会⾃动判断遇到字符串结束符00后结束复制,⽽不需要指定复制的字节数;char x[] = "china";char x1[] = "123";strcpy(x,x1); //结果是x处的字符串变成了"123"wchar_t y[] = L"中国";wchar_t y1[] = L"好";wcscpy(y,y1);ascii和宽字符关键字和常⽤字符串操作函数的对应:4.Win32的API中的宽字符1)什么是Win32 API?有哪些?在哪⾥?主要是存放在 C:\WINDOWS\system32 下⾯所有的dll2)⾮常重要的⼏个DLLKernel32.dll:最核⼼的功能模块,⽐如管理内存、进程和线程相关的函数等.User32.dll:是Windows⽤户界⾯相关应⽤程序接⼝,如创建窗⼝和发送消息等.GDI32.dll:全称是Graphical Device Interface(图形设备接⼝),包含⽤于画图和显⽰⽂本的函数⽐如要显⽰⼀个程序窗⼝,就调⽤了其中的函数来画这个窗⼝这些dll并不提供内核函数,只是⼀个壳,通过这⾥dll提供的函数来调⽤真正的内核函数;3)Win32 API中的宽字符和多字节字符Windows是使⽤C语⾔开发的,Win32 API同时⽀持宽字符与多字节字符.为了加强可读性,Windows的API中定义了很多类型的宏,在vc6中可以按F12跟进去看到底是什么类型;(1) 字符类型 (2) 字符串指针char CHAR PSTR(LPSTR) 指向多字节字符串wchar_t WCHAR PWSTR(LPWSTR) 指向宽字符串宏 TCHAR 宏 PTSTR(LPTSTR)字符数组赋值CHAR cha[] = "中国";WCHAR chw[] = L"中国";TCHAR cht[] = TEXT("中国");为字符串指针赋值:PSTR pszChar = "china"; //多字节字符PWSTR pszWChar = L"china"; //宽字符PTSTR pszTChar = TEXT("china"); //如果项⽬是ASCII的相当于"china" UNICODE 相当于L"china"windows底层处理字符串都是⽤宽字符;但为了兼容也会提供多字节字符的函数;实际上,多字节字符的函数是将多字节字符转为宽字节字符来实现的;TCHAR是根据环境类型来决定的,如果环境是宽字节那么TCHAR就是查UNICODE表;如果环境是多字节字符,那么TCHAR就是查ASCII 表;这样有个问题,⽆法确定该怎么给TCHAR类型的变量赋值,也就是到底要不要在字符串前⾯加L;为了解决这个问题,通常会⽤TEXT("字符串")函数来给TCHAR类型赋值;使⽤windows的api时最好⽤宏类型TCHAR;4)各种版本的MessageBoxMessageBoxA(0,"内容多字节","标题",MB_OK);MessageBoxW(0,L"内容宽字节",L"标题",MB_OK);MessageBox(0,TEXT("根据项⽬字符集决定"),TEXT("标题"),MB_OK);Windows提供的API 凡是需要传递字符串参数的函数,都会提供两个版本和⼀个宏.WIN32 API只提供了MessageBoxA和MessageBoxW;MessageBox实际上是⼀个宏,会根据当前项⽬的编码格式来决定到底是MessageBoxA还是MessageBoxW;4.Win32的⼊⼝函数win32控制台程序的⼊⼝函数是main;win32程序的⼊⼝函数时WinMain;控制台程序和win32程序本质上没什么区别,只是引⼊的头⽂件和⼊⼝函数不⼀样⽽已;WinMain:int CALLBACK WinMain(_In_ HINSTANCE hInstance,_In_ HINSTANCE hPrevInstance,_In_ LPSTR lpCmdLine,_In_ int nCmdShow){return0;}windows API所有函数的调⽤约定都是__stdcall;参数从右⾄左⼊栈,函数⾃⾝⽤ret x平衡堆栈;5.win32程序调试1)win32控制台输出win32程序中不能使⽤printf;为了调试需要定义⼀个函数能在控制台输出;.hvoid __cdecl OutputDebugStringF(const char *format, ...);#ifdef _DEBUG#define DbgPrintf OutputDebugStringF //如果是debug版的程序定义该函数,如果发布成release版则不定义;也就是为了正式版发布是不⽤删除调试信息;#else#define DbgPrintf#endif.cppvoid __cdecl OutputDebugStringF(const char *format, ...){va_list vlArgs;char *strBuffer = (char*)GlobalAlloc(GPTR, 4096);va_start(vlArgs, format);_vsnprintf(strBuffer, 4096 - 1, format, vlArgs);va_end(vlArgs);strcat(strBuffer, "\n");OutputDebugStringA(strBuffer);GlobalFree(strBuffer);return;}2)GetLastError的使⽤该函数会返回⼀个DWORD类型的错误代码;通过错误代码可以知道到底哪⾥出错;将该函数放到可能出问题的函数下⾯即可;例如:TCHAR szContent[] = TEXT("内容");TCHAR szTitle[] = TEXT("标题");MessageBox((HWND)0,szContent,szTitle,MB_OK); DWORD errorCode = GetLastError();。
WideCharToMultiByte[宽字符转多字节字符串]详解
WideCharToMultiByte函数功能:该函数映射一个unicode字符串到一个多字节字符串。
(---Unicode转ANSI(GB2312))函数原型:int WideCharToMultiByte(UINT CodePage,DWORD dwFlags,LPWSTR lpWideCharStr,int cchWideChar,LPCSTR lpMultiByteStr,int cchMultiByte,LPCSTR lpDefaultChar,PBOOL pfUsedDefaultChar);参数:CodePage:指定执行转换的代码页,这个参数可以为系统已安装或有效的任何代码页所给定的值。
你也可以指定其为下面的任意一值: (我想最常用的应该是CP_ACP和CP_UTF8了,前者将宽字符转dwFlags:指定如何处理没有转换的字符,但不设此参数函数会运行的更快一些,我都是把它一个不占空间的字符(如欧洲国家及汉语拼音的音标)组成,每一个都有不同的字符值。
预制字符有一个用于表示基字符和不占空间字符的合成体的单一的字符值。
当指定WC_COMPOSITECHECK选项时,也可以使用上表列出的最后3个选项来定制预制字符的转换规则。
这些选项决定了函数在遇到宽字符串的合成字符没有对应的预制字符时的行为,他们与WC_COMPOSITECHECK一起使用,如果都没有指定,函数默认WC_SEPCHARS。
对于下列代码页,dwFlags必须为0,否则函数返回错误码ERROR_INVALID_FLAGS。
50220 50221 50222 50225 50227 50229 52936 54936 57002到57011 65000(UTF7) 42(Symbol)对于UTF8,dwFlags必须为0或WC_ERR_INVALID_CHARS,否则函数都将失败返回并设置错误码ERROR_INVALID_FLAGS,你可以调用GetLastError获得。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
linux 宽字符与多字节字符之间的转换
2008-07-17 09:411237人阅读评论(0)收藏举报最近再调linux下证书验证问题,由于要对客户端发送过来的证书在服务器上与根证书进行认证,所以在读取证书、验证证书时设计到了编码转换问题。
在windows下,使用MultiByteToWideChar和WideCharT oMultiByte没有问题,但在linux下,不存在这两个函数,于是我们想到了用wcstombs和mbstowcs两个函数,但经试验,不能得到正确的结果,后来,经分析,得到,在windows下wchar_t为2字节,而在linux wchar_t为4字节,我们提取的证书编码为2字节的宽字符,所以不能正确地进行转换。
不得不,只能使用libiconv 进行转换。
iconv函数族的头文件是iconv.h。
#include <iconv.h>
iconv函数族有三个函数,原型如下:
(1) iconv_t iconv_open(const char *tocode, const char *fromcode);
此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。
(2) size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t
*outbytesleft);
此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。
(3) int iconv_close(iconv_t cd);
此函数用于关闭转换句柄,释放资源。
经过测试,使用这转换函数需要注意的有以下几点:
1、宽字节存在big-endian和little-endian之分,那使用宽字符编码时使用的编码名字也不一样,例如我们用的UCS-2编码,那有“UCS-2”和“UCS-2-INTERNAL”之分;
2、iconv中的两个长度在运行完函数后,分别为分配缓存剩余字节的大小;
3、而两个指针分别指向转换后字符串的尾部,所以在进行转换之前,应该保留缓存的原始指针,在转换后,用这两个指针减去原始指针,那就是已转换的字节长度和转换后的字节长度。
下面是我测试的代码,程序写的不怎么考究,呵呵!
#include <iconv.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <locale.h>
#define BUFLEN 200
char outBuf[BUFLEN];
//char inBuf[BUFLEN]="CN";
char inBuf[BUFLEN]="/x43/x00/x4e/x00/x00/x00";
//char inBuf[BUFLEN]="/x7a/x7a/x51/x9b/x00/x00";
int main(){
char *pIn = inBuf;
char *pOut = outBuf;
iconv_t cd;
int inLen = 4, outLen = BUFLEN;
int retSize = 0;
cd = iconv_open("UTF-8","UCS-2-INTERNAL");
// cd = iconv_open("UCS-2-INTERNAL","UTF-8");
if ((iconv_t)-1 == cd){
printf("Donot support this convert../n");
return -1;
}
if ((size_t)-1 == (retSize= iconv(cd, &pIn, (size_t *)&inLen, &pOut,(size_t
*)&outLen))){
if (E2BIG == errno)
printf(" E2BIG errno %d/n", errno);
if (EILSEQ == errno)
printf("EILSEQ errno %d/n", errno);
if (EINVAL == errno)
printf("EINVAL errno %d/n", errno);
printf("convert WCHAR to multi error/n");
return -1;
}
if (outLen > 0){
printf("/n/n outBuf:");
int i = 0;
for (i = 0; i < 200; i++){
printf("%02x ", outBuf[i]);
}
printf("/n/n inBuf:");
for (i = 0; i < 200; i++){
printf("%02x ", inBuf[i]);
}
printf("/n/n");
}
printf("out buf: %s outLen: %d retSize: %d inLen: %d/n", pOut, outLen, retSize, inLen);
printf("pInbuf: %s/n", pIn);
iconv_close(cd);
return 0;
}。