2013-06-09 19 views
8

Właśnie odkryłem, że Węzeł (testowany: v0.8.23, bieżący git: v0.11.3-pre) ignores any decoding errors w obsłudze bufora, cicho zastępując wszelkie znaki inne niż utf8 za pomocą '\ufffd' (POZIOM WYMIANY ZAMEK) zamiast rzucać wyjątek wejście non-utf8. W konsekwencji, fs.readFile, process.stdin.setEncoding i przyjaciele maskują dużą klasę złych błędów wejściowych.Jak przechwycić błędy dekodowania utf-8 w pliku node.js?

Przykład która nie zawodzi, ale naprawdę powinien:

> notValidUTF8 = new Buffer([ 128 ], 'binary') 
<Buffer 80> 
> decodedAsUTF8 = notValidUTF8.toString('utf8') // no exception thrown here! 
'�' 
> decodedAsUTF8 === '\ufffd' 
true 

'\ufffd' jest całkowicie poprawny znak, który może występować w utf8 prawnej (jak sekwencja ef bf bd), więc to nie jest trywialny monkey- łatka w obsłudze błędów na podstawie tego pojawia się w wyniku.

Kopanie trochę głębiej, wygląda na to, że pochodzi z węzła, który odradza się po strunach v8 i że te z kolei mają powyższe zachowanie, v8 nie ma zewnętrznego świata pełnego zakodowanych danych.

Czy istnieją moduły węzłów lub w inny sposób, które pozwalają mi wychwycić błędy dekodowania utf-8, najlepiej z kontekstem o tym, gdzie wykryto błąd w łańcuchu wejściowym lub buforze?

+0

Chociaż nie jestem pewien, ale masz spojrzał na moduł kodowania. Może to stanowić sposób na obejście problemu. https://npmjs.org/package/encoding –

+0

Ręczne dekodowanie (dobrze, jak w przypadku "nieużywania prymitywów węzłów") powinno być bezpieczne; iconv poprzez "kodowanie" prawdopodobnie jest drogą do osiągnięcia tam, gdzie istnieje taka potrzeba. – ecmanaut

Odpowiedz

6

Mam nadzieję, że rozwiązali problem w tych latach, miałem podobny jeden i ostatecznie rozwiązany tą brzydką sztuczką:

function isValidUTF8(buf){ 
    return Buffer.compare(new Buffer(buf.toString(),'utf8') , buf) === 0; 
    } 

Konwertuje bufor w tę iz powrotem i sprawdza, czy pozostaje taki sam.

Kodowanie "utf8" można pominąć.

Następnie mamy:

> isValidUTF8(new Buffer('this is valid, 指事字 eè we hope','utf8')) 
true 
> isValidUTF8(new Buffer([128])) 
false 
> isValidUTF8(new Buffer('\ufffd')) 
true 

gdzie znak '\ uFFFD' jest właściwie traktowane jako ważnego utf8.

UPDATE: teraz to działa w JXcore też

+0

Dzięki - to rozwiązanie przynajmniej obejmuje wszystkie sytuacje, w których różne formy normalizacji nie powodują pomyłek.(Jak pamiętam, zdecydowałem się na oprzyrządowanie, nad którym pracowałem w tym czasie w Pike, języku o bardzo solidnym rodowodzie Unicode :-) – ecmanaut

0

Jak wspomniano powyżej Josh C „npmjs.org/package/encoding”

Od strony npm „Kodowanie to nakładka dookoła węzłów iconv i iconv-lite konwersji ciągów z jednego do kodowania inne."

Download: $ npm install encoding

Przykład użycia

var result = encoding.convert(new Buffer([ 128 ], 'binary'), "utf8"); 
console.log(result); //<Buffer 80> 

Odwiedź stronę:npm - encoding