2016-04-13 7 views
1

Ich versuche, eine Zeichenfolge in deutscher Sprache in UTF-16 mit iconv zu konvertieren, aber vergeblich. Hier ist der Code für sie:Konnte nicht konvertieren zwischen Codierungen mit 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; 
} 

Ausgang:

$ ./a.out 
tägelîch 
something else 

Wenn der vom Codierungstyp zu ISO-8859-1 geändert wird, das Ergebnis ist das gleiche.

Auf der anderen Seite, iconv Programm arbeitet an der Eingabeaufforderung fein:

$ echo "TägelîcH" | iconv -f "ISO-8859-1" -t UTF-16LE 
T▒▒gel▒▒cH 

iconv --list zeigt, dass sowohl ISO-8859-1 und UTF-16LE unterstützt werden. Was vermisse ich?

Verursacht C++ in irgendeiner Weise dieses Verhalten?

Danke!

Antwort

1

Nr.

Ist nicht C++.

Ihr Code hat eine Menge Probleme.

1) Wenn ich nicht falsch liege, wechseln Sie den Code mit Out-Code; mit ic("en_US.UTF-8","UTF16LE") (und iconv_open(to,from)) werden Sie aufgefordert, von "UTF16LE" zu "en_US.UTF-8" zu konvertieren; Wenn ich das gut verstehe, willst du das Gegenteil.

2) Ich weiß nicht in deiner Plattform, aber mein Debian iconv unterstützt nicht die "en_US.UTF-8" -Encodind; versuchen, mit iconv --list zu sehen, ob iconv in Ihrer Plattform es

3) unterstützen Sie nicht testen, ob iconv_open(to,from) Rückkehr iconv_t(-1), der Fehlerwert

4) Sie kehren bool von convert aber iconv() ein size_t zurückkehren; im Falle eines Fehlers, iconv() kehrt size_t(-1), die in bool umgewandelt werden true (kein Fehler, wenn ich gut under)

5) Sie haben nicht den Wert des dritten Arguments zu convert() Test bestanden; es sollte Null sein, nachdem die Funktion (oder einen Teil des Eingangsstroms ist nicht umgesetzten) rief

6), wenn Sie str1 auf „tägelîch“ initialisieren, können Sie es in ISO-8859-1 zu initialisieren, nicht in UTF-8

Kurz gesagt, wenn ich nicht falsch liege, übergeben Sie eine TO-Codierung, die nicht in der Liste der Codierung von iconv unterstützt wird. Der Konstruktor Ihrer IConv Klasse initialisiert cv_ mit iconv_t(-1) (Fehlerwert). Wenn Sie die convert()-Methode aufrufen, schlägt iconv() fehl und gibt size_t(-1) (Fehlerwert) zurück, die als true (kein Fehlerwert) von convert() zurückgegeben wird.

Der folgende Code ist nicht perfekt, aber ich hoffe, dass es Ihnen

#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 .: sorry für mein schlechtes Englisch helfen kann.

+0

Vielen Dank für die Fehler im Code Hinweis. Es funktioniert jetzt gut. – Maddy