Обнаружение недопустимых символов UTF-8 в JavaScript
Я уже опубликовал несколько похожих вопросов и прошу прощения за это, но до сих пор не нашел решения.
У меня есть база данных, где некоторые записи не являются законными UTF-8. Если я знаю, какие записи не являются, я могу преобразовать их в UTF-8. Моя версия JavaScript имеет метод для этого. И эта функция также, кажется, работает:
function utf8_encode(str) {
return unescape( encodeURIComponent( string ) );
}
Однако, если текст уже UTF-8, вышеупомянутая функция сломает уже действительные символы UTF-8. Вы не должны конвертировать UTF-8 в UTF-8.
Итак, моя проблема сводится к следующему: как я могу взять строку в JavaScript и определить, является ли строка допустимой UTF-8 или нет?
Примером такой строки может быть:
Андре Блаво МЮЧЕН
который был введен в ISO-8859-1 и выглядит хорошо, когда браузер рассматривает его как ISO-8859-1, но если браузер вынужден просматривать в UTF-8, похоже, что в строке есть недопустимые символы.
Моя версия JavaScript также имеет тип ByteBuffer(), поэтому я могу при необходимости легко обрабатывать байты в строке по одному байту за раз.
Любой совет был бы очень признателен. Благодарю.
Дуг
Обновление 28 февраля 2014 г.:
Я придумал это, но этого недостаточно. Он ловит много не-UTF-8 символов. Но во многих случаях он считает, что текст действителен, когда это не так. Я застрял. У кого-нибудь есть идеи?
function stringIsValidUtf8 (text) {
if (typeof(text)==="object"){
for (key in text){
text[key]=this.toUTF8(text[key]);
}
}
else if (typeof(text) ==="string"){
var max = text.length;
for (var i=0; i< max; i++){
var c1 = text.charAt(i);
if (c1 >= "\xc0"){
var c2 = i+1>=max? "\x00" : text[i+1];
var c3 = i+2 >= max? "\x00" : text[i+2];
var c4 = i+3 >= max? "\x00" : text[i+3];
if (c1>= "\xc0" & c1 <="\xdf"){
if (c2 >= "\x80" && c2 <= "\xbf"){
i++
}
else{
return false;
}
}
else if (c1 >= "\xe0" & c1 <= "\xef"){
if (c2>= "x80" && c2 <= "\xbf" && c3 >= "\x80" && c3 <="\xbf"){
i=i+2;
}
else{
return false;
}
}
else if (c1>= "\xf0" & c1 <="\xf7"){
if (c2>= "\x80" && c2 <="\xbf" && c3 >= "\x80" && c3 <="\xbf" && c4 >= "\x80" && c4 <= "\xbf"){
i=i+2;
}
else{
return false;
}
}
else{
return false;
}
}
else if ((c1 & "\xc0") === "\x80"){
return false;
}
}
return true;
}
else{
return true;
}
}