2017-03-30 61 views
6

Mam aplikację, która pozwala użytkownikom utrzymywać ciągi w bazie danych, a te łańcuchy mogą zawierać emotikony. Mam problem jest emotikonów takich jak będą przechowywane w MySQL jako 😊Kodowanie Node.js ISO8859-1 do UTF-8

Kiedy odzyskać ten ciąg przy użyciu klienta PHP MySQL i uczynić go w przeglądarce internetowej, że czyni dobrze prawdopodobnie dlatego, że Content-Type jest ustawione na UTF -8. Kiedy próbuję odczytać ciąg w pliku node.js, wracam do tego, co uważam za kod ISO8859-1 kodujący literał 😊. Zestaw znaków na stole ustawiony jest na latin1 i stąd uzyskuję ISO8859-1.

Jaki jest właściwy sposób kodowania ciągu w pliku node.js, aby można było zobaczyć emoji, a nie kodowanie ustawione przez MySQL, gdy I console.log ciąg znaków?

+3

Jak o po prostu ustalenie kolumna charset zamiast? – zerkms

+0

@zerkms Niestety obecnie nie ma takiej opcji, najlepiej, gdybym mógł rozwiązać to na kliencie. Rozumiem, że twoja sugestia jest idealnym rozwiązaniem. – randombits

+0

Wygląda na to, że musisz przekonwertować punkty kodowe Unicode na odpowiednie znaki charytatywne iso8859-1. Następnie użyj bufora tablicowego do złożenia łańcucha utf z surowych bajtów. Ten ostatni można znaleźć http://stackoverflow.com/a/11058858/251311 i dla pierwszego spróbować https://github.com/ashtuchkin/iconv-lite Alternatywnie do iconv-lite można po prostu ręcznie utworzyć tabelę konwersji , ponieważ jest malutki – zerkms

Odpowiedz

2

Znalazłem bardzo brudny sposób przekonwertować go z powrotem:

const isoToUtfTable = { 
 
     'ð': 0xf0, 
 
     'Ÿ': 0x9f, 
 
     '˜': 0x98, 
 
     'Š': 0x8a 
 
    }; 
 
    
 
    function convertISO8859ToUtf8(s) { 
 
     const buf = new Uint8Array([...s].map(c => isoToUtfTable[c])); 
 
     return String.fromCharCode(...buf) 
 
    } 
 
    
 
    function decode_utf8(s) { 
 
     return decodeURIComponent(escape(s)); 
 
    } 
 
    
 
    console.log(decode_utf8(convertISO8859ToUtf8('😊')))

Teraz wystarczy wypełnić tabelę isoToUtfTable (to mała, patrz https://en.wikipedia.org/wiki/ISO/IEC_8859-1).

+0

Musi być lepszy sposób niż ręczne wypełnienie tabeli odnośników. Jeśli jest to najlepsza odpowiedź, zaznaczę ją jako taką, ale zamierzam poczekać, aby sprawdzić, czy istnieje bardziej niezawodna metoda. – randombits

+0

@Randombits możesz wziąć https://github.com/ashtuchkin/iconv-lite lub dowolną inną bibliotekę, aby je przekonwertować. Jest to po prostu sposób na zrobienie tego bez powodowania zależności. – zerkms

+0

Próbowałem uruchomić go do pracy z iconv-lite, nie mam nic przeciwko dodawaniu zależności - ale nie mogę tego przywrócić do UTF-8. Po prostu wyświetla literały łańcuchowe znajdujące się w bazie danych. – randombits

3

Nie potrzebujesz i nie należy konwertować kodowania. Po prostu użyj właściwych protokołów. Jeśli wyślesz stronę HTML w UTF-8, przeglądarka wyśle ​​dane z powrotem do twojego serwera w UTF-8.

Następnie chcesz przechowywać dane w bazie danych, która jest w latin1, która nie będzie działać wcale. Konwertuj bazę danych również na UTF-8. Obejmuje to bazę danych, tabele i ewentualnie same kolumny. Upewnij się również, że twój klient bazy danych jest skonfigurowany do połączenia w UTF-8, ponieważ sam klient musi zadeklarować swoje kodowanie.

Gdy masz cały strumień danych w UTF-8, wszystko będzie działać bezbłędnie.

Server -> GET HTML -> POST -> Server -> SQL Client -> Database -> Table -> Kolumna

+1

Jeśli przeczytasz komentarze w oryginalnym poście, zobaczysz, że zmiana bazy danych na UTF-8 nie jest obecnie dostępna. – randombits

+3

Widzę to, ale pewnego dnia będzie to opcja, ponieważ używanie brudnych sztuczek do konwersji kodowania jest tylko bramą do otwarcia piekła. Zespół OP powinien o tym niezwłocznie porozmawiać i podjąć odpowiednią decyzję. –

12

😊 jest Mojibake dla . Interpretując ten pierwszy jako łaciński1, otrzymujesz hex F09F988A, który jest heksem UTF-8 dla tego emotikonu.

(Uwaga:. UTF-8 poza MySQL jest równoważna utf8mb4 wewnątrz MySQL)

W MySQL, trzeba mieć tabeli/kolumny zadeklarowanej z CHARACTER SET utf8mb4. Musisz również stwierdzić, że dane przechowywane/pobierane są kodowane utf8mb4. Uwaga: utf8 nie wystarczy.

Wykonaj , aby sprawdzić, czy otrzymujesz ten heks dla tego emotikonu. Jeśli tak jest w przypadku i, kolumna jest obecnie latin1, a następnie częścią poprawki jest ostrożna konwersja kolumny na utf8mb4. Oznacza to, że masz CHARACTER SET latin1, ale masz w sobie bajty UTF-8; spowoduje to pozostawienie bajtów podczas ustawiania zestawu znaków. Zakładając, że kolumna jest już VARCHAR(111) CHARACTER SET latin1 NOT NULL, a następnie zrobić to 2-stopniową ALTER:

ALTER TABLE tbl MODIFY COLUMN col VARBINARY(111) NOT NULL; 
ALTER TABLE tbl MODIFY COLUMN col VARCHAR(111) CHARACTER SET utf8mb4 NOT NULL; 

Praktycznie każdy inny mechanizm konwersji uczyni gorszy bałagan.

chodzi o ustanowienie połączenia poprawnie, to idzie coś takiego dla node.js:

var connection = mysql.createConnection({ ... , charset : 'utf8mb4'}); 
+0

do tego terminu jest dedykowany, dzięki :-) – zerkms

+0

Jeśli kolumna jest CHAR (vs VARCHAR) robi żadnej z tych zmian? Wyobrażam sobie, że odpowiedź brzmi nie, ale kiedy konwertuję wszystkie bajty Mojibake, zamień je w literalne znaki zapytania "? – randombits

+0

Zobacz ponownie link - znaki zapytania są spowodowane przez coś innego. Sprawdź listę "najlepszych praktyk". 'CHAR' ma tendencję do marnowania miejsca, chyba że łańcuchy mają stałą długość. –

1

Może spróbuj spojrzeć na node-iconv.

const iconv = new Iconv('ISO-8859-2', 'UTF-8'); 
const buffer = iconv.convert(something); 
console.log(buffer); 
console.log(buffer.toString('UTF8')); 
2

Zaleca się używać iconv(prosty ISO-8859-1 na UTF-8 konwersji)

Od tego gist

var iconv = require('iconv'); 

function toUTF8(body) { 
    // convert from iso-8859-1 to utf-8 
    var ic = new iconv.Iconv('iso-8859-1', 'utf-8'); 
    var buf = ic.convert(body); 
    return buf.toString('utf-8'); 
} 

tutaj jeśli przechodzą coś w ISO -8859-1, zwróci kod UTF-8.

np

toUTF8("😊"); 

powróci

+1

Czy próbowałeś tego? Otrzymuję komunikat "à ŸË". – randombits