2010-10-30 6 views
18

Można by sądzić, że będzie to łatwo dostępne, ale ciężko jest znaleźć prostą funkcję biblioteki, która konwertuje ciąg znaków C lub C++ z ISO -8859-1 kodowanie do UTF-8. Czytam dane w 8-bitowym kodowaniu ISO-8859-1, ale trzeba je przekonwertować na ciąg znaków UTF-8, aby można go było użyć w bazie danych SQLite, a także w aplikacji na Androida.Konwertuj ciągi znaków ISO-8859-1 na kodowanie UTF-8 w języku C/C++

Znalazłem jeden produkt komercyjny, ale obecnie jest to poza moim budżetem.

+3

Jest nic prostego w tym. Możesz użyć biblioteki ICU z otwartym źródłem. –

+3

Jeśli musisz to zrobić, najprostszym kodem jest wstępne wygenerowanie tabeli ze 128 (lub podobnymi) znakami UTF-8 odpowiadającymi 8859-1 znakom z ustawionym górnym bitem. Pozostałe 128 znaków 8859-1 jest niezmodyfikowanych. W ten sposób twój kod wcale nie musi rozumieć kodu Unicode. Uważaj także na różnicę między ISO-8859-1 i Windows CP-1252. Ten ostatni ma dodatkowe znaki, w których 8859-1 ma przerwy (nieużywane punkty kodowe).O ile nie powinieneś potwierdzać, że twoje wejście jest w rzeczywistości ISO-8859-1, nie ma sensu nie akceptować CP-1252, ponieważ * zobaczysz *, że jest on nieprawidłowo oznakowany. –

+0

@Steve: ponieważ UTF-8 ma zmienną długość (w tym przypadku 1 lub 2 bajty na znak), tablica odnośników nie jest tak łatwa w użyciu. Zobacz moją odpowiedź, która powinna być równie szybka i znacznie prostsza. –

Odpowiedz

31

Jeśli kodowanie źródła będzie zawsze być ISO-8859-1, to jest trywialne. Oto pętla:

unsigned char *in, *out; 
while (*in) 
    if (*in<128) *out++=*in++; 
    else *out++=0xc2+(*in>0xbf), *out++=(*in++&0x3f)+0x80; 

Dla bezpieczeństwa należy się upewnić, że bufor wyjściowy jest dwukrotnie większa od bufora wejściowego, albo zawierać limit rozmiaru i sprawdzić go w stan pętli.

+1

Wow. To jest bardzo pomocne! Nie oczekiwałam jeszcze - kolejny algorytm wyszukiwania tabeli. Teraz dla ANSEL-to-UTF-8 ... – gordonwd

+8

To z pewnością odpowiada na pytanie. Ale, jak powiedziałem w komentarzu powyżej, ludzie * wyślą Ci CP-1252 z błędem oznaczonym jako ISO-8859-1. Serwery sieciowe są przykładem, że potknąłem się o to, że przekonałem mnie o problemie, ale także redaktorów tekstów, którzy twierdzą, że zapisują jako "Latin-1", gdy nie są. To, że "jeśli twoje kodowanie źródłowe zawsze będzie ISO-8859-1" jest dość duże "jeśli", i może być ciężko wytropić i wyeliminować niewłaściwego odpowiedzialnego. –

+0

@Steve: Możesz dodać błąd "else if (* in <192) goto;" case to error-out przy napotkaniu dowolnych kodów sterujących ISO-8859-1 (które są prawdopodobnie źle kodowanymi znakami Windows-1252, a niepoprawne znaki tak czy inaczej). –

3

Standard C++ 03 nie zapewnia funkcji do bezpośredniej konwersji między określonymi zestawami znaków.

W zależności od systemu operacyjnego, można użyć ikony iconv() w systemie Linux, MultiByteToWideChar() & Co. w systemie Windows. Biblioteką, która zapewnia dużą obsługę konwersji łańcuchów jest biblioteka ICU, która jest open source.

+0

> ** "** Standard C++ nie zapewnia funkcji do bezpośredniej konwersji między zestawami znaków. –

0

ISO-8859-1 na UTF-8 to nic innego jak algorytm kodowania, ponieważ ISO-8859-1 jest podzbiorem kodu Unicode. Masz już punkty kodu Unicode. Sprawdź Wikipedia pod kątem algorytmu.

Aspekty C++ - integrując to z technologią iostreams - są znacznie trudniejsze.

Proponuję, abyś chodził po tej górze zamiast próbować ją przewiercić lub wspiąć się na nią, czyli zaimplementować prosty ciąg do konwertora strun.

Cheers & HTH.,

+0

Algorytm nie jest całkowicie banalny, zwłaszcza gdy początkujący do średnio zaawansowanych programów kodujących C często używają' char * ', gdzie' unsigned char * 'jest potrzebny. Bardziej znaczące nietrywialności są w definicji UTF-8, w szczególności, że musisz odrzucić zastępcze wartości kodowe i wartości spoza zakresu. Na szczęście te nie pojawią się w enkoderze, który potrzebuje tylko obsługi wejścia ISO-8859-1, ale jeśli napiszesz taki ograniczony koder, prawdopodobnie ktoś go w końcu nadużyje dla większego zakresu wejściowego później bez dodawania żadnych kontroli. –

+0

@ MichałLeon: Unicode nie jest kodowaniem. Istnieje wiele różnych kodowań Unicode, w tym UTF-8 i UTF-16. Pierwsze 256 punktów kodowych Unicode jest takie samo jak Latin 1 (a.k.a. ISO-8859-1). Uwaga: nacisk nie sprawia, że ​​mniej kłócisz się z banalnym faktem. Następnym razem zamiast krzyczeć i zignorować, rozważ po prostu sprawdzanie faktów lub po prostu zapytaj o coś, czego nie rozumiesz. –

+0

@Martin: Blok punktów kodu Unicode od 128 do 255 jest nazywany ["Dodatkiem Latin-1" Unicode] (https://en.wikipedia.org/wiki/Latin-1_Supplement_ (Unicode_block)), ponieważ jest to tak samo jak Latin-1. Unicode jest bezpośrednim rozszerzeniem Latin-1. Wasze komentarze to absurdalne bzdury, rodzaj techno-bełkotu, który może wpłynąć na osoby nietechniczne i wskazuje na trolling. Zakładam, że jesteś trollingiem. –

2

Ludzie z Unicode mają kilka tabel, które mogą pomóc w przypadku Windows 1252 zamiast prawdziwego ISO-8859-1. Ostatecznym wydaje się być this one, który odwzorowuje każdy punkt kodowy w CP1252 na punkt kodowy w kodzie Unicode. Kodowanie Unicode jako UTF-8 jest prostym ćwiczeniem.

Nie będzie trudno przetworzyć bezpośrednio tabelę i utworzyć tabelę odnośników w czasie kompilacji.

7

do C++ Używam tego:

std::string iso_8859_1_to_utf8(std::string &str) 
{ 
    string strOut; 
    for (std::string::iterator it = str.begin(); it != str.end(); ++it) 
    { 
     uint8_t ch = *it; 
     if (ch < 0x80) { 
      strOut.push_back(ch); 
     } 
     else { 
      strOut.push_back(0xc0 | ch >> 6); 
      strOut.push_back(0x80 | (ch & 0x3f)); 
     } 
    } 
    return strOut; 
} 
Powiązane problemy