2012-01-19 30 views
22

Kiedy używam iconv do konwersji z UTF16 na UTF8, wszystko jest w porządku, ale na odwrót nie działa. Mam te pliki:Konwersja UTF8 do UTF16 przy użyciu iconv

a-16.strings: Little-endian UTF-16 Unicode c program text 
a-8.strings:  UTF-8 Unicode c program text, with very long lines 

Tekst wyglądają OK w edytorze. Gdy ten:

iconv -f UTF-8 -t UTF-16LE a-8.strings > b-16.strings 

następnie uzyskać ten wynik:

b-16.strings: data 
a-16.strings: Little-endian UTF-16 Unicode c program text 
a-8.strings:  UTF-8 Unicode c program text, with very long lines 

Narzędzie file nie wykazuje oczekiwany format pliku, a tekst nie wygląda dobrze w edytorze albo. Czy to możliwe, że iconv nie tworzy właściwej BOM? Uruchamiam go na linii poleceń MAC.

Dlaczego b-16 nie ma właściwego formatu UTF-16LE? Czy istnieje inny sposób konwersji utf8 na utf16?

Więcej informacji znajduje się poniżej.

$ iconv -f UTF-8 -t UTF-16LE a-8.strings > b-16le-BAD-fromUTF8.strings 
$ iconv -f UTF-8 -t UTF-16 a-8.strings > b-16be.strings 
$ iconv -f UTF-16 -t UTF-16LE b-16be.strings > b-16le-BAD-fromUTF16BE.strings 

$ file *s 
a-16.strings:     Little-endian UTF-16 Unicode c program text, with very long lines 
a-8.strings:     UTF-8 Unicode c program text, with very long lines 
b-16be.strings:     Big-endian UTF-16 Unicode c program text, with very long lines 
b-16le-BAD-fromUTF16BE.strings: data 
b-16le-BAD-fromUTF8.strings: data 


$ od -c a-16.strings | head 
0000000 377 376 /\0 * \0  \0 \f 001 E \0 S \0 K \0 

$ od -c a-8.strings | head 
0000000 / * * *  Č ** E S K Y  ( J V O 

$ od -c b-16be.strings | head 
0000000 376 377 \0 /\0 * \0 * \0 * \0  001 \f \0 E 

$ od -c b-16le-BAD-fromUTF16BE.strings | head         
0000000 /\0 * \0 * \0 * \0  \0 \f 001 E \0 S \0 

$ od -c b-16le-BAD-fromUTF8.strings | head 
0000000 /\0 * \0 * \0 * \0  \0 \f 001 E \0 S \0 

Oczywistym jest, że brakuje specyfikacji materiałowej, gdy przeprowadzam konwersję do UTF-16LE. Każda pomoc w tej sprawie?

+0

co, jeśli zamiast tego użyłeś 'iconv -f UTF-8-t UTF-16LE a-8.strings -o b-16. Stringi'? Wątpię, że to naprawi, ale warto spróbować. – cha0site

+0

Moja wersja iconv nie obsługuje parametru -o (MacOS). Jak już powiedziałeś, prawdopodobnie to by nie pomogło. Dzięki za spróbuj. –

+0

Twoje dane wyjściowe pokazują 'iconv -f UTF-8-t UTF-16 a-8.stringów (uruchamianych w systemie little-endian) generujących big-endian UTF-16 z LM. Czy możesz to potwierdzić? Czy polecenie 'iconv' w MacOS działa inaczej niż w Linuksie? 'echo cześć | iconv -f ascii -t UTF-16 | od -x' –

Odpowiedz

31

UTF-16LE mówi iconv do generowania małego-endian UTF-16 bez BOM (znak zamówienia bajtów). Wygląda na to, że od czasu, gdy podałeś LE, zestawienie komponentów nie jest konieczne.

prosi o wygenerowanie tekstu UTF-16 (w kolejności bajtów lokalnej maszyny) z a BOM.

Jeśli jesteś na maszynie Little-Endian, nie widzę sposobu, aby powiedzieć iconv, aby wygenerować big-endian UTF-16 z LM, ale może po prostu czegoś mi brakuje.

Uważam, że polecenie file nie rozpoznaje tekstu w formacie UTF-16 bez LM, a Twój edytor również nie. Ale jeśli uruchomisz iconv -f UTF-16LE -t UTF_8 b-16 strings, powinieneś uzyskać poprawną wersję oryginalnego pliku w formacie UTF-8.

Spróbuj uruchomić pliki od -c, aby zobaczyć ich aktualną zawartość.

UPDATE:

Wygląda na to, że jesteś na big-endian maszyny (x86 jest little-endian) i próbujesz wygenerować mało endian UTF-16 plik z BOM . Czy to jest poprawne? O ile mogę powiedzieć, iconv nie zrobi tego bezpośrednio. Ale to powinno działać:

(printf "\xff\xfe" ; iconv -f utf-8 -t utf-16le UTF-8-FILE) > UTF-16-FILE 

Zachowanie printfpotędze zależy od ustawień regionalnych; Mam LANG=en_US.UTF-8.

(Czy ktoś może zaproponować bardziej eleganckie rozwiązanie?)

Innym obejście, jeśli znasz endianness wyjścia produkowanego przez -t utf-16:

iconv -f utf-8 -t utf-16 UTF-8-FILE | dd conv=swab 2>/dev/null 
+0

Dziękuję Keithowi za pomoc. Zmieniłem oryginalne pytanie z większą ilością wyników na podstawie Twojej pomocy. Czy wiesz, jak to naprawić? Co się stanie, jeśli ręcznie wstawię BOM? –

+0

Zobacz zaktualizowaną odpowiedź. –

+0

Jestem również na komputerze z procesorem Intela, ale z systemem MacOS. Nie mniej jednak ręczne dodawanie zestawienia komponentów, jakie zaproponowałeś, działa doskonale. Wielkie dzięki! –

0

To może nie być eleganckie rozwiązanie, ale znalazłem ręczną sposób, aby zapewnić prawidłową konwersję do mojego problemu, który Uważam, że jest podobny do tematu tego wątku.

Problem: Dostałem plik danych tekstowych z użytkownikiem i miałem zamiar przetwarzać go na Linux (konkretnie, Ubuntu), używając skrypt (atomizacja, podział, etc.). Nazwijmy plik myfile.txt. Pierwszym wskazaniem, że coś mi się nie podobało, było to, że tokenizacja nie działała. Więc nie byłem zaskoczony, kiedy wpadłem polecenia file na myfile.txt i uzyskałem następujący

$ file myfile.txt 

myfile.txt: Little-endian UTF-16 Unicode text, with very long lines, with CRLF line terminators 

Jeśli plik był zgodny, tutaj jest to, co powinno być rozmowa:

$ file myfile.txt 

myfile.txt: ASCII text, with very long lines 

Rozwiązanie: Aby dokonać zgodnego pliku danych, poniżej znajdują się 3 ręczne kroki, które znalazłem po kilku próbach i błędach.

  1. najpierw przekształcić Big Endian jednocześnie kodowania poprzez vi (lub vim). vi myfile.txt. W vi do :set fileencoding=UTF-16BE następnie wypisz plik. Być może będziesz musiał wymusić to przy pomocy :!wq.

  2. vi myfile.txt (która powinna znajdować się teraz w utf-16BE). W vi do :set fileencoding=ASCII następnie wypisz plik. Ponownie, możesz wymusić zapis za pomocą !wq.

  3. Wykonaj konwerter dos2unix: d2u myfile.txt. Jeśli teraz uruchomić file myfile.txt powinieneś teraz zobaczyć wyjście lub coś bardziej znane i zapewnienie jak:

    myfile.txt: ASCII text, with very long lines 
    

to wszystko. Właśnie to zadziałało, a następnie mogłem uruchomić skrypt powłoki bash przetwarzania myfile.txt. Stwierdziłem, że nie mogę pominąć kroku 2. Oznacza to, że w tym przypadku nie mogę przejść bezpośrednio do kroku 3. Mam nadzieję, że informacje te są przydatne; miejmy nadzieję, że ktoś może zautomatyzować to prawdopodobnie poprzez sed lub tym podobne. Twoje zdrowie.

3

Najpierw skonwertuję na UTF-16, który będzie poprzedzał znak kolejności bajtów, w razie potrzeby as Keith Thompson mentions. Następnie, ponieważ UTF-16 nie definiuje endianness, musimy użyć file, aby ustalić, czy jest to UTF-16BE lub UTF-16LE. Wreszcie możemy przekonwertować na UTF-16LE.

iconv -f utf-8 -t utf-16 UTF-8-FILE > UTF-16-UNKNOWN-ENDIANNESS-FILE 
FILE_ENCODING="$(file --brief --mime-encoding UTF-16-UNKNOWN-ENDIANNESS-FILE)" 
iconv -f "$FILE_ENCODING" -t UTF-16LE UTF-16-UNKNOWN-ENDIANNESS-FILE > UTF-16-FILE 
Powiązane problemy