无法使用 iconv 在编码之间进行转换
Unable to convert between encodings using iconv
我正在尝试使用 iconv 将德语字符串转换为 UTF-16,但没有成功。这是它的代码:
#include <iconv.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <errno.h>
using namespace std;
const size_t BUF_SIZE=1024;
class IConv {
iconv_t ic_;
public:
IConv(const char* to, const char* from)
: ic_(iconv_open(to,from)) { }
~IConv() { iconv_close(ic_); }
bool convert(char* input, char* output, size_t& out_size) {
size_t inbufsize = strlen(input)+1;
return iconv(ic_, &input, &inbufsize, &output, &out_size);
}
};
int main(void)
{
char str1[BUF_SIZE] = "tägelîch";
char str2[BUF_SIZE] = "something else";
IConv ic("en_US.UTF-8","UTF16LE");
bool ret;
cout << str1 << endl;
size_t outsize = BUF_SIZE; //you will need it
ret = ic.convert(str1, str2, outsize);
if (ret == false) {
cout << "iconv failed: " << errno << endl;
return -1;
}
cout << str2 << endl;
}
输出:
$ ./a.out
tägelîch
something else
如果from编码类型改为ISO-8859-1
,结果是一样的。
另一方面,iconv 实用程序在命令提示符下运行良好:
$ echo "TägelîcH" | iconv -f "ISO-8859-1" -t UTF-16LE
T▒▒gel▒▒cH
iconv --list
表示ISO-8859-1
和UTF-16LE
都支持。我错过了什么?
C++ 是否以任何方式导致此行为?
谢谢!
没有
不是 C++。
你的代码有很多问题。
1)如果我没看错,你把in-code换成out-code;使用 ic("en_US.UTF-8","UTF16LE")
(和 iconv_open(to,from)
),您要求从 "UTF16LE" 转换为 "en_US.UTF-8";如果我理解的很好,你想要的恰恰相反
2) 我不知道你的平台,但我的 Debian iconv
不支持 "en_US.UTF-8" 编码;试试 iconv --list
看看你的平台 iconv
是否支持它
3)你不测试如果iconv_open(to,from)
returniconv_t(-1)
,错误值
4) 你 return bool
从 convert but iconv()
return a size_t
;如果出现错误,iconv()
returns size_t(-1)
转换为 bool,变为 true
(没有错误,如果我理解得很好)
5) 你没有测试传递给convert()
的第三个参数的值;调用函数后应为零(或部分输入流未转换)
6) 当您将 str1
初始化为 "tägelîch" 时,您将其初始化为 ISO-8859-1,而不是 UTF-8
简单地说,如果我没记错的话,你传递的 to-encoding 不在 iconv 支持的编码列表中。 IConv
class 的构造函数用 iconv_t(-1)
(错误值)初始化 cv_
。当您调用 convert()
方法时,iconv()
失败并且 return size_t(-1)
(错误值)被 returned 为 true
(无错误值) convert()
.
以下代码并不完美,但希望能对您有所帮助
#include <iconv.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <errno.h>
using namespace std;
const size_t BUF_SIZE=1024;
class IConv {
iconv_t ic_;
public:
IConv (const char* to, const char* from)
: ic_(iconv_open(to,from)) {
if ( iconv_t(-1) == ic_ )
throw std::runtime_error("error from iconv_open()");
}
~IConv ()
{ if ( iconv_t(-1) != ic_) iconv_close(ic_); }
bool convert (char* input, char* output, size_t& out_size) {
size_t inbufsize = strlen(input)+1;
return
(size_t(-1)
!= iconv(ic_, &input, &inbufsize, &output, &out_size))
&& (0U == inbufsize);
}
};
int main(void)
{
char str1[BUF_SIZE] = "tägelîch";
char str2[BUF_SIZE] = "something else";
IConv ic("UTF16LE", "ISO_8859-1");
bool ret;
size_t outsize = BUF_SIZE;
ret = ic.convert(str1, str2, outsize);
if (ret == false) {
cout << "iconv failed: " << errno << endl;
}
else {
cout << "outsize[" << outsize << "]\n";
cout << "str1[" << str1 << "]\n";
cout << "str2[" << str2 << "]\n";
for ( int i = 0 ; i < (BUF_SIZE - outsize) ; ++i )
if ( str2[i] )
cout << "str2[" << i << "]=[" << int(str2[i]) << "]("
<< str2[i] << ")\n";
}
return ret ? EXIT_SUCCESS : EXIT_FAILURE;
}
p.s.: 对不起我的英语不好
我正在尝试使用 iconv 将德语字符串转换为 UTF-16,但没有成功。这是它的代码:
#include <iconv.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <errno.h>
using namespace std;
const size_t BUF_SIZE=1024;
class IConv {
iconv_t ic_;
public:
IConv(const char* to, const char* from)
: ic_(iconv_open(to,from)) { }
~IConv() { iconv_close(ic_); }
bool convert(char* input, char* output, size_t& out_size) {
size_t inbufsize = strlen(input)+1;
return iconv(ic_, &input, &inbufsize, &output, &out_size);
}
};
int main(void)
{
char str1[BUF_SIZE] = "tägelîch";
char str2[BUF_SIZE] = "something else";
IConv ic("en_US.UTF-8","UTF16LE");
bool ret;
cout << str1 << endl;
size_t outsize = BUF_SIZE; //you will need it
ret = ic.convert(str1, str2, outsize);
if (ret == false) {
cout << "iconv failed: " << errno << endl;
return -1;
}
cout << str2 << endl;
}
输出:
$ ./a.out
tägelîch
something else
如果from编码类型改为ISO-8859-1
,结果是一样的。
另一方面,iconv 实用程序在命令提示符下运行良好:
$ echo "TägelîcH" | iconv -f "ISO-8859-1" -t UTF-16LE
T▒▒gel▒▒cH
iconv --list
表示ISO-8859-1
和UTF-16LE
都支持。我错过了什么?
C++ 是否以任何方式导致此行为?
谢谢!
没有
不是 C++。
你的代码有很多问题。
1)如果我没看错,你把in-code换成out-code;使用 ic("en_US.UTF-8","UTF16LE")
(和 iconv_open(to,from)
),您要求从 "UTF16LE" 转换为 "en_US.UTF-8";如果我理解的很好,你想要的恰恰相反
2) 我不知道你的平台,但我的 Debian iconv
不支持 "en_US.UTF-8" 编码;试试 iconv --list
看看你的平台 iconv
是否支持它
3)你不测试如果iconv_open(to,from)
returniconv_t(-1)
,错误值
4) 你 return bool
从 convert but iconv()
return a size_t
;如果出现错误,iconv()
returns size_t(-1)
转换为 bool,变为 true
(没有错误,如果我理解得很好)
5) 你没有测试传递给convert()
的第三个参数的值;调用函数后应为零(或部分输入流未转换)
6) 当您将 str1
初始化为 "tägelîch" 时,您将其初始化为 ISO-8859-1,而不是 UTF-8
简单地说,如果我没记错的话,你传递的 to-encoding 不在 iconv 支持的编码列表中。 IConv
class 的构造函数用 iconv_t(-1)
(错误值)初始化 cv_
。当您调用 convert()
方法时,iconv()
失败并且 return size_t(-1)
(错误值)被 returned 为 true
(无错误值) convert()
.
以下代码并不完美,但希望能对您有所帮助
#include <iconv.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <errno.h>
using namespace std;
const size_t BUF_SIZE=1024;
class IConv {
iconv_t ic_;
public:
IConv (const char* to, const char* from)
: ic_(iconv_open(to,from)) {
if ( iconv_t(-1) == ic_ )
throw std::runtime_error("error from iconv_open()");
}
~IConv ()
{ if ( iconv_t(-1) != ic_) iconv_close(ic_); }
bool convert (char* input, char* output, size_t& out_size) {
size_t inbufsize = strlen(input)+1;
return
(size_t(-1)
!= iconv(ic_, &input, &inbufsize, &output, &out_size))
&& (0U == inbufsize);
}
};
int main(void)
{
char str1[BUF_SIZE] = "tägelîch";
char str2[BUF_SIZE] = "something else";
IConv ic("UTF16LE", "ISO_8859-1");
bool ret;
size_t outsize = BUF_SIZE;
ret = ic.convert(str1, str2, outsize);
if (ret == false) {
cout << "iconv failed: " << errno << endl;
}
else {
cout << "outsize[" << outsize << "]\n";
cout << "str1[" << str1 << "]\n";
cout << "str2[" << str2 << "]\n";
for ( int i = 0 ; i < (BUF_SIZE - outsize) ; ++i )
if ( str2[i] )
cout << "str2[" << i << "]=[" << int(str2[i]) << "]("
<< str2[i] << ")\n";
}
return ret ? EXIT_SUCCESS : EXIT_FAILURE;
}
p.s.: 对不起我的英语不好