2014-01-18 2 views
0

Мы пытаемся сравнить такое же имя файла, один устанавливается оператором =, а другой возвращается, получив файл с сервера Nodejs после закачано, как следующий блок кода:nodejs сравнить Unicode имена файлов

var name = "tên_đẹp.WAV"; 

// uploaded_file is the file (tên_đẹp) returned by calling an ajax function 
// to get the uploaded file in uploaded_folder of a Nodejs server 
ajaxUploadFile(name).done(function(e, uploaded_file) { 

    if(name == uploaded_file.name) { 
     return uploaded_file; // This line is never reached 
    else { 
     console.log(escape(name));    // t%EAn_%u0111%u1EB9p.WAV 
     console.log(escape(uploaded_file.name)); // te%u0302n_%u0111e%u0323p.WAV 
    } 
} 

Как вы можете видеть, результат 2 команд управления отличается. Я не знаю, почему они используют разные форматы unicode и как я могу заставить их использовать одну и ту же кодировку Unicode или любое решение, которое было бы высоко оценено? Спасибо.

ответ

3

Вопрос заключается в том, что "e\u0302" и "\u00EA" оба визуально идентичны. Одним из них является конкретный символ U+00EA (LATIN SMALL LETTER E WITH CIRCUMFLEX), а другой - e с комбинирующим символом U+0302 (КОМБИНИРОВАННЫЙ ЦИРКУМФЛЕКСНЫЙ АКЦЕНТ). Сначала вы должны нормализовать каждую строку до стандартной формы, чтобы сравнить их.

require('unorm'); 

var name = "tên_đẹp.WAV"; 

// uploaded_file is the file (tên_đẹp) returned by calling an ajax function 
// to get the uploaded file in uploaded_folder of a Nodejs server 
ajaxUploadFile(name).done(function(e, uploaded_file) { 

    if(name.normalize() == uploaded_file.name.normalize()) { 
     return uploaded_file; // This line is never reached 
    else { 
     console.log(escape(name));    // t%EAn_%u0111%u1EB9p.WAV 
     console.log(escape(uploaded_file.name)); // te%u0302n_%u0111e%u0323p.WAV 
    } 
} 

Обратите внимание, что я загрузил unorm модуль, который polyfills в методе .normalize() вызывается на струнах. Этот метод является частью ECMA6, а в будущих версиях узла вам не нужно будет загружать unorm.

Невозможно сказать, что представляет собой различия там, это мог быть ваш текстовый редактор или ваш браузер.

1

Юникодными символами в файле uploaded_file.name являются акценты. %u0302 - это диакритическая метка. КОМБИНИРОВАННЫЙ ЦИРКУМФЛЕКСНЫЙ АКЦЕНТ, %u0323 - это диакритическая отметка «КОМБИНИРОВАННАЯ ДОТ НИЖЕ».

С другой стороны, %EA (ê) и %u1EB9 (ẹ) являются эквивалентными символами с интегрированными акцентами.

Это что-то обрабатывается Юникод-эквивалентность (см. Википедию). Последовательность e%u0302 называется эквивалентом canonicaly до %EA, и аналогично для другой пары.

Для правильной обработки сравнения в node.js, вы должны нормализовать строки в канонической форме (NFC или NFD). Это может быть достигнуто с unorm:

var unorm = require('unorm'); 
var s1 = 'êẹ'; 
var s2 = 'e\u0302e\u0323'; 
console.log(s1 == s2); // false 
console.log(unorm.nfc(s1) == unorm.nfc(s2)); // true 
console.log(unorm.nfd(s1) == unorm.nfd(s2)); // true 

Выбор между NFC (в составе) и по СФО (разложенном) не имеет значения в данном случае.

Важно: Обратите внимание, что canonicalization может иногда вводить неочевидные уязвимости, связанные с использованием, особенно с именами файлов, поскольку ОС, вероятно, по-прежнему будет воспринимать их как разные. Например. см. эту историю spotify: Creative usernames and Spotify account hijacking.

1

%EA == ê

e%u0302 == e + ^

Эти две Юникода последовательности, которые выглядят одинаково, но напечатал по-разному. Если вам нужно их сравнить, сначала вам нужно будет нормализовать юникод.

Смежные вопросы