Проверить возможность перекодировки 16бит->8бит

GRIG

Новичок
Проверить возможность перекодировки 16бит->8бит

Привет всем. Подкиньте, пожалуйста, идей на такую тему.
ДАНО: строка, содержащая текст в кодировке UTF-8
ТРЕБУЕТСЯ: определить, можно ли этот текст конвертировать в какую-то конкретную 8-битовую кодировку (например, KOI8-R или LATIN1) без потерь. И при этом не должно возникать никаких ошибочных ситуаций, имеющих заметные внешние проявления. (Это, в частности, накладывает ограничение на возможность применения в данной задаче функции iconv() - она при обнаружении недопустимого символа формирует E_NOTICE в логе).
В принципе я эту задачу сделал. Но сделал способом, который мне самому не нравится. А другие варианты как-то не придумываются.
Заранее спасибо.
 

Вурдалак

Продвинутый новичок
Самое тупое, конечно, iconv() с //IGNORE с проверка длин входящей и получившейся строк. Тогда и Notice не будет.

А вот с latin1 гораздо проще. Достаточно присутствие хотя бы одного байта > 0x7F.
 

GRIG

Новичок
Автор оригинала: mity
Поставьте собаку @iconv() и E_NOTICE в логе не будет
Собаку поставить нетрудно. Вопрос в том как после этого определить - перекодировалась строка полностью или нет.

-~{}~ 31.05.10 11:42:

Автор оригинала: Вурдалак
Самое тупое, конечно, iconv() с //IGNORE с проверка длин входящей и получившейся строк. Тогда и Notice не будет.

А вот с latin1 гораздо проще. Достаточно присутствие хотя бы одного байта > 0x7F.
LATIN1 я привел для примера. Хочется получить решение в общем виде, которое не завязано на особенности конкретной кодировки.
А вот про проверку длин строк - поподробнее: что с чем сравнивать и что брать в качестве признака "можно - нельзя".
 

mity

Новичок
Проверка ошибок реализуется элементарно.
PHP:
//==========================================================================
ini_set('display_errors',1); 
error_reporting(E_ALL &( ~E_DEPRECATED));
//============================================================================
function userErrorHandler($errno,$errmsg,$filename,$linenum,$vars) { 

  if(error_reporting()!=0){
    //Ошибка или предупреждение НЕ замаскированно @
   }else{
     //Ошибка или предупреждение замаскированно @
   }   

$GLOBALS['ErrorCount']++;	 
	 
 } 
//============================================================================ 
 

$old_error_handler=set_error_handler("userErrorHandler"); 
//============================================================================

$GLOBALS['ErrorCount']=0;
$z=iconv("123","UTF-8","UTF-8");
if($GLOBALS['ErrorCount']!=0){
  echo "error<br>";
}

//============================================================================

set_error_handler($old_error_handler); 

//============================================================================
//============================================================================
Можно фильтровать отдельные типы ошибок, и строчки где они появляются
 

GRIG

Новичок
Ну вот примерно так я и сделал. Хотя это все-таки чуть лучше, чем то, что сделал я.
А вот можно ли решить задачу без перехвата обработчиков ошибок и прочего вмешательства в эту подсистему? Вот этот вопрос меня очень интересует.
 

mity

Новичок
Вы никуда не вмешиваетесь, это штатная работа.

Перекодируйте строку в 2-х байтовое unicode представление UCS-2LE.
Создаёте таблицы всех кодировок, ну и проверяете.

Только на php врятли удастся написать быструю реализацию такого механизма.
 

GRIG

Новичок
В моем случае скорость - не главное. Нужны простота и надежность методики.
 

mity

Новичок
Скорость не имеет значение первые 24 часа работы скрипта, затем это начинает напрягать.

iconv по вашему ненадёжен?
 

GRIG

Новичок
Скорость не имеет значения, если обращения к скрипту происходят меньше, чем 1 раз в минуту. (А в моем конкретном случае будет даже реже).
В надежности iconv я не сомневаюсь. А вот перехват обработчиков ошибок меня напрягает - я считаю это дополнительным усложнением системы, и мне кажется, что это усложнение не оправдано, и потому хочу найти способ попроще.
 

phprus

Moderator
Команда форума
Если нужно проверить конвертируемость в какую либо кодировку, то можно перекодировать текст в нее из исходной с применением @ и IGNORE, а потом результат снова перекодировать в исходную кодировку из проверяемой. Если строки совпадут, значит перекодировка без потерь возможна.
 

Вурдалак

Продвинутый новичок
Ещё раз: с //IGNORE не будет никакого Notice, поэтому никакой «собаки» ставить не надо.

-~{}~ 31.05.10 20:52:

mity
Отлавливать ошибки с такой целью — п..ц
 

GRIG

Новичок
Автор оригинала: Вурдалак
Ещё раз: с //IGNORE не будет никакого Notice, поэтому никакой «собаки» ставить не надо.
Notice, разумеется, не будет. Но при этом также не будет никакого признака того, прошел процесс перекодировки полностью или нет. А как раз получение этого признака и является основной целью задачи.
 

SiMM

Новичок
GRIG, а собака-то к Вашему монологу какое имеет отношение?
phprus, есть один забавный момент - BOM неплохо бы для начала удалить ;)
 

phprus

Moderator
Команда форума
SiMM
Да, действительно. Не подумал о BOM и о том, что его надо удалять.
 

GRIG

Новичок
Автор оригинала: SiMM
GRIG, а собака-то к Вашему монологу какое имеет отношение?
Как какое??? "Собака" перед конструкцией языка - указание интерпретатору игнорировать все ошибки, которые могут возникнуть при обработке этой конструкции.
 

dimagolov

Новичок
GRIG, когда до тебя дойдет, что определить корректность перекодировки можно не только по возникающей ошибке, но и по возможности обратной перекодировки в исходный текст?
 

Вурдалак

Продвинутый новичок
Автор оригинала: GRIG
Notice, разумеется, не будет. Но при этом также не будет никакого признака того, прошел процесс перекодировки полностью или нет. А как раз получение этого признака и является основной целью задачи.
— как уже неоднократно сказали есть два варианта:
  • Перекодировка обратно и сравнение с исходной строкой
  • Проверка длины получившейся строки (strlen) и исходной (iconv_strlen)
 

SiMM

Новичок
> "Собака" перед конструкцией языка - указание интерпретатору игнорировать все ошибки, которые могут возникнуть при обработке этой конструкции.
Да нифига подобного - интерпретатор их не игнорирует, игнорировать ошибки и не выводить их пользователю - две большие разницы.
 
Сверху