2016-04-13 2 views
1

Я пытаюсь преобразовать строку на немецком языке в UTF-16 с помощью iconv, но напрасно. Вот код для этого:Невозможно преобразовать между кодировками с помощью iconv

#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 

Если от кодирования типа изменяется на 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++ каким-либо образом причиной такого поведения?

Спасибо!

ответ

1

Номер

Не C++.

У вашего кода много проблем.

1) если я не ошибаюсь, вы включаете код с внешним кодом; с 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), что преобразованные в BOOL, становятся true (нет ошибки, если я understan хорошо)

5) Вы не проверить значение третьего аргумента, переданного convert(); она должна быть равна нулю, после вызова функции (или часть входного потока является непрореагировавший)

6) при инициализации str1 на «tägelîch», вы инициализировать его в ISO-8859-1, а не в UTF-8

Вкратце, если я не ошибаюсь, вы передаете кодировку, которая отсутствует в списке кодировок, поддерживаемых iconv. Конструктор вашего класса IConv инициализирует cv_ с iconv_t(-1) (значение ошибки). Когда вы вызываете метод convert(), iconv() сбой и возврат size_t(-1) (значение ошибки), которое возвращается как 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 .: простите за мой плохой английский.

+0

Благодарим за указание на ошибки в коде. Теперь он отлично работает. – Maddy

Смежные вопросы