您好,登錄后才能下訂單哦!
場景說明
將UTF-8的編碼轉換成GBK編碼,使用Notepad++創建一個UTF-8(無BOM)的編碼文件,文件內容簡單為風雨在途,保存文件名稱為utf8.txt,轉換之后存儲文件名稱為gbk.txt.
iconv -f UTF8 -t GBK <utf8.txt> gbk.txt
#include <iconv.h>
size_t iconv(iconv_t cd,
char **inbuf, size_t*inbytesleft,
char **outbuf, size_t*outbytesleft);
參數說明:經過iconv函數之后,*outbuf當前指向轉換之后的字符串的最后位置,*inuf當前指向被轉換字符串的最后位置,所以為了得到正確的轉換字符串的指針位置,需要進行如下的調整:
*outbuf = *outbuf - iconv函數的返回值.或者定義指針指向當前的字符串緩存區,就不會修改字符串的緩沖區指針了
int UTF8fileToGBKfile()
{
int ret;
int read_fd;
int write_fd;
//1打開文件,讀取utf-8文件
read_fd=open("utf8.txt",O_RDONLY|O_CREAT);
write_fd=open("gbk.txt", O_WRONLY|O_CREAT);
char utfBuffer[256] = {0};
size_t inLen = read(read_fd, utfBuffer,256);
//2獲取字符集轉換的文件句柄,這里是從utf-8轉換為gbk
errno = 0;
iconv_t cd = iconv_open("gbk","utf-8");
char* errMsg = NULL;
if (errno !=0)
{
errMsg = strerror(errno);
cout<<errno<<endl;
cout<<errMsg<<endl;
return -1;
}
//3準備轉換前的字符串,避免修改原字符串
char* szSrc = (char*)malloc(inLen);
memset(szSrc, 0, inLen);
memcpy(szSrc, utfBuffer, inLen);
//4準備轉換后的字符串存儲空間
size_t outLen = 256;
char* szDest = (char*)malloc(outLen);
memset(szDest, 0, outLen);
//4開始轉換
errno = 0;
char* pszDest = szDest;
char* pszSrc = szDest;
errno = 0;
ret = iconv(cd, &pszSrc, &inLen,&pszDest , &outLen);
if (errno !=0)
{
errMsg = strerror(errno);
cout<<errno<<endl;
cout<<errMsg<<endl;
return -2;
}
iconv_close(cd);
//5寫入文件,outlen是剩下多少空間沒有使用
ret = write(write_fd, szDest, 256-outLen);
close(read_fd);
close(write_fd);
free(szDest);
free(szSrc);
return 0;
}
下載libiconv-1.14.tar.gz,解壓,執行./configure --prefix=/opt/iconv;make;make install
生成文件:
charset.alias libcharset.so libiconv.la libiconv.so.2.5.1
libcharset.a libcharset.so.1 libiconv.so preloadable_libiconv.so
libcharset.la libcharset.so.1.0.0 libiconv.so.2
實際鏈接到庫的時候,指定庫目錄,在/etc/ld.so.conf文件之后追加一行/opt/iconv/lib.采用ldconfig命令的時候,出錯:
libcharset.so.1 不是符號鏈接
libiconv.so.2 不是符號鏈接
原因是:刪除這兩個文件,然后使用ldconfig命令,生成該符號鏈接。
[root@jack lib]# ll
總用量 3560
-rw-r--r--. 1 root root 212 9月 13 10:22 charset.alias
-rw-r--r--. 1 root root 27868 9月 13 10:22 libcharset.a
-rw-r--r--. 1 root root 936 9月 13 10:22 libcharset.la
-rw-r--r--. 1 root root 277609月 13 10:22 libcharset.so
lrwxrwxrwx. 1 root root 19 9月 13 11:10libcharset.so.1->libcharset.so.1.0.0
-rw-r--r--. 1 root root 27760 9月 13 10:22 libcharset.so.1.0.0
-rw-r--r--. 1 root root 912 9月 13 10:22 libiconv.la
-rw-r--r--. 1 root root 1186436 9月 13 10:22 libiconv.so
lrwxrwxrwx. 1 root root 17 9月 13 11:10 libiconv.so.2 ->libiconv.so.2.5.1
-rw-r--r--. 1 root root 1186436 9月 13 10:22 libiconv.so.2.5.1
-rw-r--r--. 1 root root 1168119 9月 13 10:22 preloadable_libiconv.so
調用該動態庫的編譯命令如下:
g++ test.cpp -I/opt/iconv/include//opt/iconv/lib/libcharset.a/opt/iconv/lib/libiconv.so libsqlite3.a-lpthread -ldl -g -o main
./configure--prefix=/opt/iconvCFLAGS="-g -O0"
生成動態庫鏈接符號錯誤解決
[root@jack lib]# ldconfig
ldconfig: /opt/iconv/lib/libiconv.so.2 不是符號連接
ldconfig: /opt/iconv/lib/libcharset.so.1 不是符號連接
[root@jack lib]# rm -rflibiconv.so.2libcharset.so.1
[root@jack lib]# ldconfig
主要是將UTF-8編碼的字符串在轉換成GBK編碼,詳細的轉換規則UTF-8轉Unicode,
然后Unicode編碼通過查表,映射到GBK編碼上
loop_unicode.h:273
執行函數
incount=cd->ifuncs.xxx_mbtowc(cd,&wc,inptr,inleft);
跳轉到./utf8.h:30
核心轉換函數:static size_t unicode_loop_convert (iconv_t icd,
const char* * inbuf, size_t *inbytesleft,char* *outbuf,size_t*outbytesleft)
at./loop_unicode.h:284
284 incount = cd->ifuncs.xxx_mbtowc(cd,&wc,inptr,inleft);
at./loop_unicode.h:362
362 outcount = cd->ofuncs.xxx_wctomb(cd,outptr,wc,outleft);
該函數進行Unicode轉換成GBK
進行的是查表進行轉換,在調試的過程中,可以通過附件,提前知道轉換的字符編碼,然后查看iconv庫是否轉換有問題
UTF-8轉Unicode編碼的函數:
static int
utf8_mbtowc (conv_t conv, ucs4_t*pwc,constunsigned char *s, int n)
iconv函數中傳遞進去的outptr會指向轉換字符串的末尾,所以需要進行指針的前移,outptr-返回值
就是指向最開始轉換的字符串
iconv_open函數跳轉到lib/iconv.c 218 行,里面調用了
#include "iconv_open1.h"
47-60行
141-152行
for (cp = fromcode, bp = buf, count = MAX_WORD_LENGTH+10+1; ; cp++,bp++){
unsigned char c = * (unsigned char *) cp;
if (c >= 0x80)
goto invalid;
if (c >= 'a' && c <= 'z')
c -= 'a'-'A';
*bp = c;
if (c == '\0')
break;
if (--count == 0)
goto invalid;
}
這里進行了大小寫轉換,所有的字體編碼類型,轉換成大寫字母,gbk轉換成GBK.小寫字母轉換成大寫字母是減去26
目前遇到一個相當大的問題:
ap= aliases_lookup(buf,bp-buf);
if(ap == NULL) {
ap = aliases2_lookup(buf);
if (ap == NULL)
goto invalid;
}
這幾行函數沒能夠單步調試所以并不清楚返回值進行了什么操作
#include "iconv_open2.h"
設置執行的回調函數,以及初始化標志位,具體的沒有看出什么
使用庫提供的automake,順利生成libiconv.so文件,目前嘗試單獨編譯,出現如下的問題
使用指令如下:
g++libiconv-1.14/libcharset/lib/localcharset.clibiconv-1.14/lib/iconv.clibiconv-1.14/lib/relocatable.c libsqlite3.a -lpthread -ldl -Ilibiconv-1.14/-I libiconv-1.14/include/-I libiconv-1.14/lib-Ilibiconv-1.14/libcharset/include/ -fPIC -shared -o libiconv.so
libiconv-1.14/libcharset/lib/localcharset.c:77:25:錯誤:configmake.h:沒有那個文件或目錄
libiconv-1.14/libcharset/lib/localcharset.c:Infunction‘const char* get_charset_aliases()’:
libiconv-1.14/libcharset/lib/localcharset.c:135:錯誤:‘LIBDIR’在此作用域中尚未聲明
查找資料顯示在windows下無需該文件,因此注釋該頭文件的包含
問題剩下LIBDIR的定義問題
查找所有的引用LIBDIR ,localcharset.c函數
static const char*get_charset_aliases(void)會通過dir =relocate (LIBDIR);
獲取該值,查看該函數的內容:
const char *cp;
cp=charset_aliases;
/* Pointer to the contentsofthecharset.alias file, if it has already been
read, else NULL. Its format is:
ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0'CANONICAL_n '\0''\0' */
static const char *volatilecharset_aliases;
說明指向這個charset.alias文件,查看該文件:
該文件的目錄如下:
libiconv-1.14/libcharset/lib
內容如下:
# This file contains a table ofcharacterencodingaliases,
# suitable for operating system'linux-gnu'.
# It was automatically generatedfromconfig.charset.
# Packages using this file:
ISO_646.IRV:1983 ASCII
說明該文件是由同一級目錄下的config.charset腳本生成的
跟蹤:
linux* | *-gnu*)
#With glibc-2.1 or newer, we don't need any canonicalization,
#because glibc has iconv and both glibc and libiconv support all
#GNU canonical names directly. Therefore, the Makefile does not
#need to install the alias file at all.
#The following applies only to glibc-2.0.x and older libcs.
echo "ISO_646.IRV:1983 ASCII"
翻譯:glibc-2.1以后的版本都不需要任何的標準化文件,因為自帶的緣故,該文件只是被之前的版本引用
因此在localcharset.c 定義LIBDIR指向的目錄:
#defineLIBDIR"/work/libiconv-1.14/libcharset/lib"
[root@jack work]# g++libiconv-1.14/libcharset/lib/localcharset.clibiconv-1.14/lib/relocatable.c libiconv-1.14/lib/iconv.c test.cpp -I libiconv-1.14/ -Ilibiconv-1.14/lib/-Ilibiconv-1.14/include -Ilibiconv-1.14/libcharset/include/ -I libiconv-1.14/srclib/ libsqlite3.a -lpthread -ldl -o testmain
/tmp/cc1ENLex.o: Infunction`libiconv_open':
iconv.c:(.text+0x18206):undefinedreferenceto `aliases_lookup(char const*, unsigned int)'
iconv.c:(.text+0x18391):undefinedreferenceto `aliases_lookup(char const*, unsigned int)'
/tmp/cc1ENLex.o:Infunction`libiconv_open_into':
iconv.c:(.text+0x187d0): undefinedreferenceto`aliases_lookup(char const*, unsigned int)'
iconv.c:(.text+0x1895b):undefinedreferenceto `aliases_lookup(char const*, unsigned int)'
/tmp/cc1ENLex.o: Infunction`iconv_canonicalize':
iconv.c:(.text+0x190a9):undefinedreferenceto `aliases_lookup(char const*, unsigned int)'
collect2: ld 返回 1
該函數的定義就在lib/aliases.h文件當中定義的,不清楚為什么無法找到,
然后手動將該定義拷貝到lib/iconv.c文件,還是出現同樣子的問題
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。