Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2716771
  • 博文数量: 416
  • 博客积分: 10220
  • 博客等级: 上将
  • 技术积分: 4193
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-15 09:47
文章分类

全部博文(416)

文章存档

2022年(1)

2021年(1)

2020年(1)

2019年(5)

2018年(7)

2017年(6)

2016年(7)

2015年(11)

2014年(1)

2012年(5)

2011年(7)

2010年(35)

2009年(64)

2008年(48)

2007年(177)

2006年(40)

我的朋友

分类: C/C++

2006-12-19 08:42:35

应该说gb2312跟utf-8的概念应该不是一个层次上的。gb2312跟unicode都是字符的编码方式,而utf8只是unicode的一种表示方式而已。他们的区别主要在iso8859-1定义的字符集之外(用多字节来表示一个字符)。在linux下有一个iconv库可以完成这些编码之间的转换!
下面的代码是gb2312字节流跟跟utf16字节流之间的转换函数。gb2312跟utf8的转换应该差不多!
两个extern函数为转换入口函数,其它都为内部函数。

/*@author:huangh
*@create time:2005/12/16
*/
#include
#include
#include
#include
#include

#define ALIVE() printf("still alive here [%s]:[%d]\n",__FUNCTION__, __LINE__)
/*get the low 8 bits of an unsigned short*/
#define LOWER_SHORT(num) (0x0ff&num)
/*get the high 8 bits of an unsigned short*/
#define HIGH_SHORT(num) ((0xff00&num)>>8)

//#define _BIG_ENDIAN
//#define DEBUG


typedef unsigned int char_16;

static int char16len(char_16 *in_char)
{
    int ret = 0;
    while(in_char[ret])
    {
        ret++;
    }
    return ret;
}
static int gb2312_to_utf16(char *inchar, size_t *in_size, char *outchar, size_t *out_size)
{
    iconv_t cd;
    char **ppinchar = &inchar;
    char **ppoutchar = &outchar;
   
    if ( ( iconv_t )-1 == ( cd = iconv_open( "UCS-2", "GB2312" ) ) )
    {
        perror( "iconv_open() error" );
        return -1;
    }
   
    if ( -1 == iconv( cd, ppinchar, in_size, ppoutchar, out_size ) )
    {
        perror( "iconv() error" );
        goto error;
    }

    {
        int i = 0;
        char *p = outchar;
        while(p[i])
        {
            printf("%2x:", p[i]);
            i++;
        }
    }
    iconv_close(cd);
    return 0;
error:
    iconv_close(cd);
    return -1;
}

static int char_to_char16(char *in, size_t in_size, char_16 out[], size_t out_size)
{
    int i = 0;
    unsigned short high, low;
   
    printf("insize is [%d], out size is [%d]\n", in_size, out_size);  
    if(in_size > 2*out_size)
    {
        return -1;
    }
    ALIVE();
    for(; i    {
#ifdef _BIG_ENDIAN
        high = in[2*i+1]&0xff;
        low  = in[2*i]&0xff;
#else
        high = in[2*i]&0xff;
        low  = in[2*i+1]&0xff;
#endif
        out[i] = (high<<8)|low;
    }
    return 0;
}

static int char16_to_char(char_16 in[], size_t size_in, char *out, size_t size_out)
{
    int i = 0;
    if(size_out < 2*size_in)
    {
        return -1;
    }
    for(; i< size_in; i++)
    {
#ifdef _BIG_ENDIAN
        out[i*2] = LOWER_SHORT(in[i]);
        out[i*2 + 1] = HIGH_SHORT(in[i]);
#else
        out[i*2] = HIGH_SHORT(in[i]);
        out[i*2 + 1] = LOWER_SHORT(in[i]);
#endif
    }
    return 0;
}
static int utf16_to_gb2312(char *inchar, size_t *in_size, char *outchar, size_t *out_size)
{
    iconv_t cd;
    char **ppinchar = &inchar;
    char **ppoutchar = &outchar;
   
    if ( ( iconv_t )-1 == ( cd = iconv_open( "GB2312", "UCS-2") ) )
    {
        perror( "iconv_open() error" );
        return -1;
    }
   
    if ( -1 == iconv( cd, ppinchar, in_size, ppoutchar, out_size ) )
    {
        perror( "iconv() error" );
        goto error;
    }

    iconv_close(cd);
    return 0;
error:
    iconv_close(cd);
    return -1;
}

extern int char_to_utf16(char *in_char, char_16 *out_wchar, size_t out_size)
{
    size_t in_len = strlen(in_char) + 1;
    size_t tmp_len = 2*in_len;
    size_t tmp_len_org;
    char *tmp;
   

    printf("inlen is [%d], out size is [%d]\n", in_len, out_size);  
    if(in_len > 2*out_size)
    {
        return -1;
    }

    if(NULL == (tmp = (char *)malloc(tmp_len)))
    {
        return -1;
    }
    tmp_len_org = tmp_len;

   
    if( 0 != gb2312_to_utf16(in_char, &in_len, tmp, &tmp_len))
    {
        goto error;
    }
    {
        printf("tmp length is [%d]:[%d]\n", tmp_len, in_len);
    }
    if(0 != char_to_char16(tmp, tmp_len_org - tmp_len, out_wchar, out_size))
    {
        goto error;
    }
   
    ALIVE();
    free(tmp);
    return 0;
error:
    free(tmp);
    return -1;
}

extern int utf16_to_char(char_16 *in_char, char *out_char, size_t out_size)
{
    size_t in_size = char16len(in_char) + 1;
    char *tmp;
    size_t in_len ;
    size_t out_len;

#ifdef DEBUG
    int j;
    for(j=0;j    {
        fprintf(stderr, "[%4x]:",in_char[j]);
    }
    fprintf(stderr, "\n");
#endif

    if(NULL == (tmp = (char *)malloc(2*in_size)))
    {
        return -1;
    }
   
    memset(tmp, 0, 2*in_size);

    if(0 != char16_to_char(in_char, in_size, tmp, 2*in_size))
    {
        goto error;
    }
#ifdef DEBUG
    for(j=0; j<2*in_size; j++)
    {
        fprintf(stderr, "[%2x]:",tmp[j]);
    }
    fprintf(stderr, "\n");
#endif
    in_len = in_size*2;
    out_len = out_size;
    if( 0 != (utf16_to_gb2312(tmp, &in_len, out_char, &out_len)))
    {
        goto error;
    }
   
   
    free(tmp);
    return 0;
error:
    free(tmp);
    return -1;
}

1、什么是UTF-8?它与UNICODE是什么关系?
解答:
Unicode的最初目标,是用1个16位的编码来为超过65000个字符提供映射。但这还不够,它不能覆盖全部历史上的文字,也不能解决传输的问题 (implantation head-ache's),尤其在那些基于网络的应用中。已有的软件必须做大量的工作来实现16位的数据。
因此,Unicode用一些基本的保留字符制定了三套编码方式。它们分别是UTF-8,UTF-16和UTF-32。正如名字所示,在UTF-8中,字符是以8位序列来编码的,用一个或几个字节来表示一个字符。这种方式的最大好处,是UTF-8保留了ASCII字符的编码做为它的一部分,例如,在UTF- 8和ASCII中,“A”的编码都是0x41. UTF-16和UTF-32分别是Unicode的16位和32位编码方式。考虑到最初的目的,通常说的Unicode就是指UTF-16。
2、unicode的参考网站
.
3、unicode三种编码之间的转换

4、也可以通过查表的方式转换gb2312码和unicode码。表文件见附件gb2312.txt,文件中有使用说明。


 char buff[1024];
   size_t buff_len = 1024;
   size_t s_len = len;
   iconv_t cd = iconv_open("utf-8", "gbk");
   if (cd != iconv_t(-1))
   {
     char* ptr = &buff[0];
     size_t remain = buff_len;
     size_t d_len = iconv(cd, &s, &s_len, &ptr, &remain);

     //for (size_t i=0; i     //      cout << buff[i];
     //cout << '\n';

     iconv_close(cd);
   }

用它实现在Linux下解决gbk,gb2312<->unicode转换
可用在Clucene上

PortAudio Compile:
./configure --libdir=/c/Program\ Files/Microsoft\ SDKs/Windows/v6.0A/lib \
 --includedir=/c/Program\ Files/Microsoft\ SDKs/Windows/v6.0A/include \
--with-winapi=directx \
--with-dxdir=S:/sdk/DXSDK/9.0
阅读(4449) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~