无法使用iconv在编码之间转换

Unable to convert between encodings using iconv

本文关键字:编码 之间 转换 iconv      更新时间:2023-10-16

我试图使用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

2表示同时支持CCD_ 3和CCD_。我错过了什么?

C++是否以任何方式导致了这种行为?

谢谢!

否。

不是C++。

您的代码有很多问题。

1) 如果我没有错的话,你可以把代码换成out代码;对于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)是否返回iconv_t(-1),即错误值

4) 转换返回bool,但iconv()返回size_t;在出现错误的情况下,iconv()返回size_t(-1),该CCD_16在布尔中转换为true(如果我理解得很好,则没有错误)

5) 您不测试传递给convert()的第三个参数的值;在调用函数(或者部分输入流未转换)之后,它应该为零

6) 当您将str1初始化为"tägelîch"时,您可以用ISO-8859-1进行初始化,而不是用UTF-8 进行初始化

简单地说,如果我没有错的话,您可以将一个传递给不在iconv支持的编码列表中的编码。iconv --list0类的构造函数使用iconv_t(-1)(错误值)初始化cv_。调用convert()方法时,iconv()失败并返回size_t(-1)(错误值),convert()将其返回为true(无错误值)。

以下代码并不完美,但我希望它能帮助你

#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;
}

抱歉我英语不好。