Что такое код iconv


ЗАПИСКИ АДМИНИСТРАТОРА FREEBSD

FreeBSD, iconv и юникод UTF-8

При разработке натолкнулся на проблему.

Код PHP: iconv(‘cp1251’, ‘utf8’, ‘Тестовая строка’);

постоянно возвращает значение FALSE.

Такое впечатление, что функция iconv не понимает, что от нее хотят.

Проблема в том, что iconv во FreeBSD не знает кодировки «utf8», а знает «UTF-8».

Следите за регистром, и все будет работать.

Таким образом, предыдущий код надо записывать так:

iconv(‘cp1251’, ‘UTF-8’, ‘Тестовая строка’);

iconv encoding conversion problem

I am having trouble converting strings from utf8 to gb2312. My convert function is below

This is an example of how I used it:

edit: I most of the time get a E2BIG error.

2 Answers 2

outleft should be the size of the output buffer (e.g. 1000 bytes), not the size of the incoming string.

When converting, the string length usually changes in the process and you cannot know how long it is going to be until afterwards. E2BIG means that the output buffer wasn’t large enough, in which case you need to give it more output buffer space (notice that it has already converted some of the data and adjusted the four variables passed to it accordingly).

As others have noted, E2BIG means that the output buffer wasn’t large enough for the conversion and you were using the wrong value for outleft.

But I’ve also noticed some other possible problems with your function. Namely, with the way your function works, your caller has no way of knowing how many bytes are in the output string. Your convert() function neither nul-terminates the output buffer nor does it have a means of telling its caller the number of bytes it wrote to outptr.

If you want to deal with nul-terminates strings (and it appears that’s what you want to do since your input string is nul-terminated), you might find the following approach to be much better:

iconv — Преобразование строки в требуемую кодировку

(PHP 4 >= 4.0.5, PHP 5, PHP 7)

iconv — Преобразование строки в требуемую кодировку

Описание

Преобразует набор символов строки str из кодировки in_charset в out_charset .

Список параметров

Кодировка входной строки.

Требуемая на выходе кодировка.

Если добавить к out_charset строку //TRANSLIT, включается режим транслитерации. Это значит, что в случае, если символ не может быть представлен в требуемой кодировке, он будет заменен на один или несколько нескольких наиболее близких по внешнему виду символов. Если добавить строку //IGNORE, то символы, которые не могут быть представлены в требуемой кодировке, будут удалены. В случае отсутствия вышеуказанных параметров при наличии некорректных символов строка str будет обрезана до первого такого символа, и будет сгенерирована ошибка уровня E_NOTICE .

Строка, которую необходимо преобразовать.

Возвращаемые значения

Возвращает преобразованную строку или FALSE в случае возникновения ошибки.

Примеры

Пример #1 Пример использования iconv()

= «This is the Euro symbol ‘€’.» ;

echo ‘Original : ‘ , $text , PHP_EOL ;
echo ‘TRANSLIT : ‘ , iconv ( «UTF-8» , «ISO-8859-1//TRANSLIT» , $text ), PHP_EOL ;
echo ‘IGNORE : ‘ , iconv ( «UTF-8» , «ISO-8859-1//IGNORE» , $text ), PHP_EOL ;
echo ‘Plain : ‘ , iconv ( «UTF-8» , «ISO-8859-1» , $text ), PHP_EOL ;

Результатом выполнения данного примера будет что-то подобное:

Что такое кодировка файла

В двух словах, кодировка — это числовой код, который присвоен каждому символу/букве. Числовой код фиксируется в специальных кодовых таблицах, в разных таблицах одному и тому же символу присвоены разные числовые коды.
При выводе символа на экран производиться операция — декодирование. Декодирование преобразует код символа в его изображение.

Отбросим, по сути не нужную нам теорию, и займемся практикой.
Главное правило, всегда, во всех своих файлах, устанавливайте одинаковую кодировку, чтобы не было никаких конфликтов, и текст отображался адекватно.
В Notepad ++ это выглядит так:

UTF-8 — я всегда ставлю ее, это самая распространенная кодировка, используйте ее, и у Вас будет меньше проблем с кодировкой сайта.

Стоп! А что значит UTF-8 без BOM? При установке кодировки на UTF-8 в начале файла создаются невидимые нам символы, в некоторых скриптах эти символы могут вызвать ошибки. В этом и есть основная разница между UTF-8 и UTF-8 без BOM, поэтому мы выбираем ее.

Идем дальше. Теперь во все наши HTML коды мы будем добавлять специальный Meta-тэг, который будет сообщать браузеру какая кодировка установлена на сайте. Выглядит он так:

В некоторых ситуациях, кодировку необходимо указать и в PHP — скриптах, делается это с помощью кода:

Смена кодировки строки в PHP. Функция iconv()

Иногда, бывают ситуации когда необходимо принудительно сменить кодировку строки. В PHP за это отвечает функция iconv(). Приведу пример ее использования:

В данном случае функция iconv() преобразует строку из кодировки Windows-1251 в кодировку UTF-8.

Внимательно следите чтобы во всех файлах была одинаковая кодировка.

iconv

(PHP 4 >= 4.0.5, PHP 5, PHP 7)

iconv — Преобразование строки в требуемую кодировку

Описание

Преобразует набор символов строки str из кодировки in_charset в out_charset .

Список параметров

Кодировка входной строки.

Требуемая на выходе кодировка.

Если добавить к out_charset строку //TRANSLIT, включается режим транслитерации. Это значит, что в случае, если символ не может быть представлен в требуемой кодировке, он будет заменен на один или несколько наиболее близких по внешнему виду символов. Если добавить строку //IGNORE, то символы, которые не могут быть представлены в требуемой кодировке, будут удалены. В случае отсутствия вышеуказанных параметров будет сгенерирована ошибка уровня E_NOTICE , а функция вернет FALSE .

Как будет работат //TRANSLIT и будет ли вообще, зависит от системной реализации iconv() ( ICONV_IMPL ). Известны некоторые реализации, которые просто игнорируют //TRANSLIT, так что конвертация для символов некорректных для out_charset скорее всего закончится ошибкой.

Строка, которую необходимо преобразовать.

Возвращаемые значения

Возвращает преобразованную строку или FALSE в случае возникновения ошибки.

Список изменений

Версия Описание
5.4.0 Начиная с этой версии, функция возвращает FALSE на некорректных символах, только если в выходной кодировке не указан //IGNORE. До этого функция возвращала часть строки.

Примеры

Пример #1 Пример использования iconv()

= «Это символ евро — ‘€’.» ;

echo ‘Исходная строка : ‘ , $text , PHP_EOL ;
echo ‘С добавлением TRANSLIT : ‘ , iconv ( «UTF-8» , «ISO-8859-1//TRANSLIT» , $text ), PHP_EOL ;
echo ‘С добавлением IGNORE : ‘ , iconv ( «UTF-8» , «ISO-8859-1//IGNORE» , $text ), PHP_EOL ;
echo ‘Обычное преобразование : ‘ , iconv ( «UTF-8» , «ISO-8859-1» , $text ), PHP_EOL ;

Результатом выполнения данного примера будет что-то подобное:

User Contributed Notes 38 notes

The «//ignore» option doesn’t work with recent versions of the iconv library. So if you’re having trouble with that option, you aren’t alone.

That means you can’t currently use this function to filter invalid characters. Instead it silently fails and returns an empty string (or you’ll get a notice but only if you have E_NOTICE enabled).

This has been a known bug with a known solution for at least since 2009 years but no one seems to be willing to fix it (PHP must pass the -c option to iconv). It’s still broken as of the latest release 5.4.3.

ini_set(‘mbstring.substitute_character’, «none»);
$text= mb_convert_encoding($text, ‘UTF-8’, ‘UTF-8’);

That will strip invalid characters from UTF-8 strings (so that you can insert it into a database, etc.). Instead of «none» you can also use the value 32 if you want it to insert spaces in place of the invalid characters.

Please note that iconv(‘UTF-8’, ‘ASCII//TRANSLIT’, . ) doesn’t work properly when locale category LC_CTYPE is set to C or POSIX. You must choose another locale otherwise all non-ASCII characters will be replaced with question marks. This is at least true with glibc 2.5.

Example:
( LC_CTYPE , ‘POSIX’ );
echo iconv ( ‘UTF-8’ , ‘ASCII//TRANSLIT’ , «Žluťoučký kůň\n» );
// ?lu?ou?k? k??

setlocale ( LC_CTYPE , ‘cs_CZ’ );
echo iconv ( ‘UTF-8’ , ‘ASCII//TRANSLIT’ , «Žluťoučký kůň\n» );
// Zlutoucky kun
?>

Interestingly, setting different target locales results in different, yet appropriate, transliterations. For example:

//some German
$utf8_sentence = ‘Weiß, Goldmann, Göbel, Weiss, Göthe, Goethe und Götz’ ;

//UK
setlocale ( LC_ALL , ‘en_GB’ );

//transliterate
$trans_sentence = iconv ( ‘UTF-8’ , ‘ASCII//TRANSLIT’ , $utf8_sentence );

//gives [Weiss, Goldmann, Gobel, Weiss, Gothe, Goethe und Gotz]
//which is our original string flattened into 7-bit ASCII as
//an English speaker would do it (ie. simply remove the umlauts)
echo $trans_sentence . PHP_EOL ;

//Germany
setlocale ( LC_ALL , ‘de_DE’ );

$trans_sentence = iconv ( ‘UTF-8’ , ‘ASCII//TRANSLIT’ , $utf8_sentence );

//gives [Weiss, Goldmann, Goebel, Weiss, Goethe, Goethe und Goetz]
//which is exactly how a German would transliterate those
//umlauted characters if forced to use 7-bit ASCII!
//(because really ä = ae, ö = oe and ü = ue)
echo $trans_sentence . PHP_EOL ;

to test different combinations of convertions between charsets (when we don’t know the source charset and what is the convenient destination charset) this is an example :

= array( «UTF-8» , «ASCII» , «Windows-1252» , «ISO-8859-15» , «ISO-8859-1» , «ISO-8859-6» , «CP1256» );
$chain = «» ;
foreach ( $tab as $i )
<
foreach ( $tab as $j )
<
$chain .= » $i$j » . iconv ( $i , $j , » $my_string » );
>
>

echo $chain ;
?>

then after displaying, you use the $i$j that shows good displaying.
NB: you can add other charsets to $tab to test other cases.

If you are getting question-marks in your iconv output when transliterating, be sure to ‘setlocale’ to something your system supports.

Some PHP CMS’s will default setlocale to ‘C’, this can be a problem.

use the «locale» command to find out a list..

( LC_CTYPE , ‘en_AU.utf8’ );
$str = iconv ( ‘UTF-8’ , ‘ASCII//TRANSLIT’ , «Côte d’Ivoire» );
?>

Like many other people, I have encountered massive problems when using iconv() to convert between encodings (from UTF-8 to ISO-8859-15 in my case), especially on large strings.

The main problem here is that when your string contains illegal UTF-8 characters, there is no really straight forward way to handle those. iconv() simply (and silently!) terminates the string when encountering the problematic characters (also if using //IGNORE), returning a clipped string. The

= html_entity_decode ( htmlentities ( $oldstring , ENT_QUOTES , ‘UTF-8’ ), ENT_QUOTES , ‘ISO-8859-15’ );

?>

workaround suggested here and elsewhere will also break when encountering illegal characters, at least dropping a useful note («htmlentities(): Invalid multibyte sequence in argument in. «)

I have found a lot of hints, suggestions and alternative methods (it’s scary and in my opinion no good sign how many ways PHP natively provides to convert the encoding of strings), but none of them really worked, except for this one:

= mb_convert_encoding ( $oldstring , ‘ISO-8859-15’ , ‘UTF-8’ );

There may be situations when a new version of a web site, all in UTF-8, has to display some old data remaining in the database with ISO-8859-1 accents. The problem is iconv(«ISO-8859-1», «UTF-8», $string) should not be applied if $string is already UTF-8 encoded.

I use this function that does’nt need any extension :

function convert_utf8( $string ) <
if ( strlen(utf8_decode($string)) == strlen($string) ) <
// $string is not UTF-8
return iconv(«ISO-8859-1», «UTF-8», $string);
> else <
// already UTF-8
return $string;
>
>

I have not tested it extensively, hope it may help.

For those who have troubles in displaying UCS-2 data on browser, here’s a simple function that convert ucs2 to html unicode entities :

function ucs2html ( $str ) <
$str = trim ( $str ); // if you are reading from file
$len = strlen ( $str );
$html = » ;
for( $i = 0 ; $i $len ; $i += 2 )
$html .= ‘&#’ . hexdec ( dechex ( ord ( $str [ $i + 1 ])).
sprintf ( «%02s» , dechex ( ord ( $str [ $i ])))). ‘;’ ;
return( $html );
>
?>

In my case, I had to change:
( LC_CTYPE , ‘cs_CZ’ );
?>
to
( LC_CTYPE , ‘cs_CZ.UTF-8’ );
?>
Otherwise it returns question marks.

When I asked my linux for locale (by locale command) it returns «cs_CZ.UTF-8», so there is maybe correlation between it.

iconv (GNU libc) 2.6.1
glibc 2.3.6

Here is how to convert UCS-2 numbers to UTF-8 numbers in hex:

function ucs2toutf8 ( $str )
<
for ( $i = 0 ; $i strlen ( $str ); $i += 4 )
<
$substring1 = $str [ $i ]. $str [ $i + 1 ];
$substring2 = $str [ $i + 2 ]. $str [ $i + 3 ];

if ( $substring1 == «00» )
<
$byte1 = «» ;
$byte2 = $substring2 ;
>
else
<
$substring = $substring1 . $substring2 ;
$byte1 = dechex ( 192 +( hexdec ( $substring )/ 64 ));
$byte2 = dechex ( 128 +( hexdec ( $substring )% 64 ));
>
$utf8 .= $byte1 . $byte2 ;
>
return $utf8 ;
>

echo strtoupper ( ucs2toutf8 ( «06450631062D0020» ));

?>

Input:
06450631062D
Output:
D985D8B1D8AD

I have used iconv to convert from cp1251 into UTF-8. I spent a day to investigate why a string with Russian capital ‘Р’ (sounds similar to ‘r’) at the end cannot be inserted into a database.

The problem is not in iconv. But ‘Р’ in cp1251 is chr(208) and ‘Р’ in UTF-8 is chr(208).chr(106). chr(106) is one of the space symbol which match ‘\s’ in regex. So, it can be taken by a greedy ‘+’ or ‘*’ operator. In that case, you loose ‘Р’ in your string.

For example, ‘ГР ‘ (Russian, UTF-8). Function preg_match. Regex is ‘(.+?)[\s]*’. Then ‘(.+?)’ matches ‘Г’.chr(208) and ‘[\s]*’ matches chr(106).’ ‘.

Although, it is not a bug of iconv, but it looks like it very much. That’s why I put this comment here.

Here is how to convert UTF-8 numbers to UCS-2 numbers in hex:

function utf8toucs2 ( $str )
<
for ( $i = 0 ; $i strlen ( $str ); $i += 2 )
<
$substring1 = $str [ $i ]. $str [ $i + 1 ];
$substring2 = $str [ $i + 2 ]. $str [ $i + 3 ];

if ( hexdec ( $substring1 ) 127 )
$results = «00» . $str [ $i ]. $str [ $i + 1 ];
else
<
$results = dechex (( hexdec ( $substring1 )- 192 )* 64 + ( hexdec ( $substring2 )- 128 ));
if ( $results 1000 ) $results = «0» . $results ;
$i += 2 ;
>
$ucs2 .= $results ;
>
return $ucs2 ;
>

echo strtoupper ( utf8toucs2 ( «D985D8B1D8AD» )). «\n» ;
echo strtoupper ( utf8toucs2 ( «456725» )). «\n» ;

I just found out today that the Windows and *NIX versions of PHP use different iconv libraries and are not very consistent with each other.

Here is a repost of my earlier code that now works on more systems. It converts as much as possible and replaces the rest with question marks:

if (! function_exists ( ‘utf8_to_ascii’ )) <
setlocale ( LC_CTYPE , ‘en_AU.utf8’ );
if (@ iconv ( «UTF-8» , «ASCII//IGNORE//TRANSLIT» , ‘é’ ) === false ) <
// PHP is probably using the glibc library (*NIX)
function utf8_to_ascii ( $text ) <
return iconv ( «UTF-8» , «ASCII//TRANSLIT» , $text );
>
>
else <
// PHP is probably using the libiconv library (Windows)
function utf8_to_ascii ( $text ) <
if ( is_string ( $text )) <
// Includes combinations of characters that present as a single glyph
$text = preg_replace_callback ( ‘/\X/u’ , __FUNCTION__ , $text );
>
elseif ( is_array ( $text ) && count ( $text ) == 1 && is_string ( $text [ 0 ])) <
// IGNORE characters that can’t be TRANSLITerated to ASCII
$text = iconv ( «UTF-8» , «ASCII//IGNORE//TRANSLIT» , $text [ 0 ]);
// The documentation says that iconv() returns false on failure but it returns »
if ( $text === » || ! is_string ( $text )) <
$text = ‘?’ ;
>
elseif ( preg_match ( ‘/\w/’ , $text )) < // If the text contains any letters.
$text = preg_replace ( ‘/\W+/’ , » , $text ); // . then remove all non-letters
>
>
else < // $text was not a string
$text = » ;
>
return $text ;
>
>
>

Didn’t know its a feature or not but its works for me (PHP 5.0.4)

test it to convert from windows-1251 (stored in DB) to UTF-8 (which i use for web pages).
BTW i convert each array i fetch from DB with array_walk_recursive.

Here is an example how to convert windows-1251 (windows) or cp1251(Linux/Unix) encoded string to UTF-8 encoding.

function cp1251_utf8 ( $sInput )
<
$sOutput = «» ;

for ( $i = 0 ; $i strlen ( $sInput ); $i ++ )
<
$iAscii = ord ( $sInput [ $i ] );

Be aware that iconv in PHP uses system implementations of locales and languages, what works under linux, normally doesn’t in windows.

Also, you may notice that recent versions of linux (debian, ubuntu, centos, etc) the //TRANSLIT option doesn’t work. since most distros doesn’t include the intl packages (example: php5-intl and icuxx (where xx is a number) in debian) by default. And this because the intl package conflicts with another package needed for international DNS resolution.

Problem is that configuration is dependent of the sysadmin of the machine where you’re hosted, so iconv is pretty much useless by default, depending on what configuration is used by your distro or the machine’s admin.

iconv with //IGNORE works as expected: it will skip the character if this one does not exist in the $out_charset encoding.

If a character is missing from the $in_charset encoding (eg byte \x81 from CP1252 encoding), then iconv will return an error, whether with //IGNORE or not.

For transcoding values in an Excel generated CSV the following seems to work:

= iconv ( ‘Windows-1252’ , ‘UTF-8//TRANSLIT’ , $value );
?>

Note an important difference between iconv() and mb_convert_encoding() — if you’re working with strings, as opposed to files, you most likely want mb_convert_encoding() and not iconv(), because iconv() will add a byte-order marker to the beginning of (for example) a UTF-32 string when converting from e.g. ISO-8859-1, which can throw off all your subsequent calculations and operations on the resulting string.

In other words, iconv() appears to be intended for use when converting the contents of files — whereas mb_convert_encoding() is intended for use when juggling strings internally, e.g. strings that aren’t being read/written to/from files, but exchanged with some other media.

‘» to the output.
This function will strip out these extra characters:
( LC_ALL , ‘en_US.UTF8’ );
function clearUTF ( $s )
<
$r = » ;
$s1 = @ iconv ( ‘UTF-8’ , ‘ASCII//TRANSLIT’ , $s );
$j = 0 ;
for ( $i = 0 ; $i strlen ( $s1 ); $i ++) <
$ch1 = $s1 [ $i ];
$ch2 = @ mb_substr ( $s , $j ++, 1 , ‘UTF-8’ );
if ( strstr ( ‘`^

function detectUTF8($string)
<
return preg_match(‘%(?:
[\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
|\xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
|[\xE1-\xEC\xEE\xEF][\x80-\xBF] <2># straight 3-byte
|\xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
|\xF0[\x90-\xBF][\x80-\xBF] <2># planes 1-3
|[\xF1-\xF3][\x80-\xBF] <3># planes 4-15
|\xF4[\x80-\x8F][\x80-\xBF] <2># plane 16
)+%xs’, $string);
>

function cp1251_utf8( $sInput )
<
$sOutput = «»;

Перевод кодировки текстовых файлов (через консольную утилиту win_iconv)

Dragokas

Very kind Developer

Конвертирование текстовых файлов с одной кодировки в другую с помощью win_iconv

win_iconv
Автор: Yukihiro Nakadaira
Версия: 0.0.6 (от 22.11.2012)
Это утилита с открытым исходным кодом: code.google

Входная кодировка задаётся ключом -f, а выходная — ключом -t. Любая из этих кодировок по умолчанию равна локали системы. Все входные файлы читаются по очереди, если не задан параметр входного файла, то используется стандартный ввод, а конвертируемый текст выводится на стандартный вывод.

Когда задана опция -c, символы, которые не могут быть преобразованы просто выбрасываются. В противном случае при появлении подобной ошибки программа аварийно завершается.

Когда задана опция -s, сообщения об ошибках не выводятся.

Файл UTFtext.txt будет преобразован из кодировки UTF-16LE в OEM-866 и результат записан в файл DOStext.txt.

Ключ -l выводит список доступных кодировок.

Сила кодируется из US-ASCII в UTF-8 (iconv)

Я пытаюсь перекодировать кучу файлов из US-ASCII в UTF-8.

Для этого я использую iconv:

Thing — мои исходные файлы, кодированные US-ASCII, что делает невозможным преобразование. По-видимому, это происходит потому, что ASCII является подмножеством UTF-8.

Нет необходимости, чтобы текстовый файл появлялся иначе, пока не-ascii вводятся символы

True. Если я введу в файл не-ASCII-символ и сохраню его, скажем, с Eclipse, кодировка файла (charset) переключается на UTF-8.

В моем случае я хотел бы заставить iconv перекодировать файлы на UTF-8 в любом случае. Есть ли в нем символы, отличные от ASCII, или нет.

Примечание. Причина в том, что мой PHP-код (файлы, отличные от ASCII. ) имеет дело с некоторой строкой, отличной от ASCII, что приводит к тому, что строки не могут быть хорошо интерпретированы (французский):

Il à © tait une fois. l’homme sà © rie animà © e mythique d’Albert

Barillà © (Procidis), 1ère

ИЗМЕНИТЬ

  • US-ASCII — — подмножество UTF-8 (см. ответ Ned ниже)
  • Значение US-ASCII файлов действительно закодировано в UTF-8
  • Моя проблема возникла где-то в другом месте

ASCII — это подмножество UTF-8, поэтому все файлы ASCII уже закодированы в кодировке UTF-8. Байты в файле ASCII и байты, которые должны быть получены из «кодирования его в UTF-8», будут точно такими же байтами. Между ними нет никакой разницы, поэтому ничего не нужно делать.

Похоже, ваша проблема в том, что файлы на самом деле не ASCII. Вам нужно определить, какую кодировку они используют, и перекодировать их должным образом.

Короткий ответ

  • file только догадывается о кодировке файла и может быть неправильным.
  • вы можете использовать hexdump для просмотра байтов текста без 7-бит-ascii и сравнения с кодовыми таблицами для общих кодировок (7-бит-ascii, iso-8859- *, utf-8), чтобы решить что такое кодировка.
  • iconv будет использовать любую кодировку ввода/вывода, которую вы укажете вне зависимости от содержимого файла. Если вы укажете неправильную кодировку ввода, выход будет искажен.
  • даже после запуска iconv , file может не сообщать о каких-либо изменениях из-за ограниченного способа, с помощью которого file пытается угадать кодировку. Для конкретного примера см. Мой длинный ответ.

Длинный ответ

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

Во-первых, термин ASCII перегружен, и это приводит к путанице (включая меня).

7-разрядный ASCII включает только 128 символов (00-7F или 0-127 в десятичной форме). 7-разрядный ASCII также упоминается как US-ASCII.

Кодировка UTF-8 использует ту же кодировку, что и 7-разрядный ASCII для первых 128 символов. Таким образом, текстовый файл, содержащий только символы из этого диапазона из первых 128 символов, будет идентичным на уровне байта, независимо от того, закодирован ли он UTF-8 или 7-разрядный ASCII.

Термин расширенный ascii (или высокий ascii) относится к восьмибитным или большему кодированию символов, которые включают стандартные семибитные символы ASCII, плюс дополнительные символы.

ISO-8859-1 (он же «ISO Latin 1» ) — это специальный 8-разрядный стандарт расширения ASCII, который охватывает большинство символов для Западной Европы. Существуют и другие стандарты ИСО для восточноевропейских языков и кириллических языков. ISO-8859-1 включает такие символы, как Ö, é, ñ и ß для немецкого и испанского языков. «Расширение» означает, что ISO-8859-1 включает 7-битный стандарт ASCII и добавляет к нему символы с использованием 8-го бита. Таким образом, для первых 128 символов он эквивалентен на байтовом уровне кодированным файлам ASCII и UTF-8. Однако, когда вы начинаете разбираться с символами за пределами первых 128, вы больше не эквивалентны UTF-8 на уровне байтов, и вы должны сделать преобразование, если вы хотите, чтобы ваш файл расширенного ascii был кодирован UTF-8.

Один урок, который я узнал сегодня, заключается в том, что мы не можем доверять file , чтобы всегда давать правильную интерпретацию кодировки символа файла.

Команда сообщает только, как выглядит файл, а не то, что он (в случае, когда файл просматривает содержимое). Легко обмануть программу, поместив магическое число в файл, содержимое которого не соответствует ему. Таким образом, команда не используется в качестве инструмента безопасности, кроме как в определенных ситуациях.

file ищет магические числа в файле, которые намекают на тип, но это может быть неправильно, без гарантии правильности. file также пытается угадать кодировку символов, просматривая байты в файле. В основном file имеет серию тестов, которые помогают угадать тип файла и кодировку.

Мой файл представляет собой большой файл CSV. file сообщает этот файл как us-ascii закодированный, WRONG.

В моем файле есть umlauts (т.е. ). Первый не-7-бит-ascii не отображается до более чем 100k строк в файл. Я подозреваю, что именно поэтому file не понимает, что кодировка файла не является US-ASCII.

(Я нахожусь на Mac, поэтому использую PCRE grep . С gnu grep вы можете использовать опцию -P .)

Я не вкопался в исходный код file , и man-страница подробно не обсуждает обнаружение текстового кодирования, но я предполагаю, что file не смотрит весь файл перед угадыванием кодирование.

Независимо от моего кодирования файлов, эти символы не-7-бит-ASCII ломаются. Мой немецкий CSV файл ; — разделен и извлечение одного столбца не работает.

Обратите внимание на ошибку cut и мой файл «tmp» имеет только 102320 строк с первым специальным символом в строке 102321.

Посмотрим, как кодируются эти символы, отличные от ASCII. Я сбрасываю первый не-7-бит-ascii в hexdump , делаю небольшое форматирование, удаляю новые строки ( 0a ) и занимаю только первые несколько.

Другой способ. Я знаю, что первый не-7-бит-ASCII char находится в позиции 85 в строке 102321. Я беру эту строку и говорю hexdump , чтобы взять два байта, начиная с позиции 85. Вы можете увидеть специальный (не-7 -bit-ASCII), представленный символом «.», а следующий байт — «M». так что это однобайтовая кодировка символов.

В обоих случаях мы видим, что специальный символ представлен d6 . Поскольку этот символ является. который является немецким письмом, я предполагаю, что ISO-8859-1 должен включать это. Конечно, вы можете видеть, что «d6» соответствует (https://en.wikipedia.org/wiki/ISO/IEC_8859-1#Codepage_layout).

Важный вопрос. как я узнаю, что этот символ. не будучи уверенным в кодировке файла? Ответ — это контекст. Я открыл файл, прочитал текст и затем определил, каким персонажем он должен быть. Если я открою его в vim , он отобразится как. потому что vim делает лучшую работу по угадыванию кодировки символов (в данном случае), чем file .

Итак, мой файл выглядит как ISO-8859-1. Теоретически я должен проверить остальные символы без 7-битного ASCII, чтобы убедиться, что ISO-8859-1 подходит. Ничто не заставляет программу использовать только одну кодировку при записи файла в диск (кроме хороших манер).

Я пропущу проверку и перейду к шагу преобразования.

Хм. file все еще говорит мне, что этот файл является US-ASCII даже после преобразования. Повторите проверку с помощью hexdump .

Определенно изменение. Обратите внимание, что у нас есть два байта не-7-бит-ASCII (представлен справа.), А шестнадцатеричный код для двух байтов теперь c3 96 . Если мы посмотрим, похоже, у нас теперь есть UTF-8 (c3 96 — это правильная кодировка Ö в UTF-8) http://www.utf8-chartable.de/

Но file все еще сообщает наш файл как us-ascii ? Ну, я думаю, что это возвращается к вопросу о file не глядя на весь файл и тот факт, что первые не-7-бит-ASCII-символы не встречаются до глубокого в файле.

Я использую sed , чтобы вставить файл. в начале файла и посмотреть, что произойдет.

Прохладный, у нас есть умляут. Обратите внимание на кодировку, но это c3 96 (utf-8). Хм.

Еще раз проверьте наши другие умлауты в том же файле:

ISO-8859-1. К сожалению! Просто идет, чтобы показать, как легко заставить кодировки прикручиваться.

Попробуйте преобразовать наш новый тестовый файл с помощью umlaut спереди и посмотреть, что произойдет.

К сожалению. Этот первый умлаут, который был UTF-8, был интерпретирован как ISO-8859-1, поскольку это то, что мы сказали iconv . Второй умлаут правильно преобразован из d6 в c3 96 .

Я попробую еще раз, на этот раз я буду использовать vim для ввода Ö вместо sed . vim , казалось, лучше определял кодировку (как «latin1», а также ISO-8859-1), поэтому, возможно, он введет новый. с последовательной кодировкой.

Выглядит хорошо. Похож на ISO-8859-1 для новых и старых умляутов.

Boom! Мораль истории. Не доверяйте file , чтобы всегда угадать свое право кодирования. Легко смешивать кодировки в одном файле. Если вы сомневаетесь, посмотрите на шестнадцатеричный.

Взлом (также подверженный сбою), который будет учитывать это конкретное ограничение file при работе с большими файлами, — это сократить файл, чтобы убедиться, что специальные символы появляются в начале файла, поэтому file более вероятно чтобы найти их.

Update

Christos Zoulas обновил file , чтобы количество байтов выглядело как настраиваемое. Один день поворота вокруг запроса функции, удивительный!

Функция была выпущена в file версии 5.26.

Глядя на большой файл, прежде чем делать предположение о кодировании, требуется время. Однако неплохо иметь возможность для конкретных случаев использования, когда лучшее предположение может перевесить дополнительное время /io.

Используйте следующий параметр:

. должен сделать трюк, если вы хотите заставить file посмотреть весь файл перед тем, как сделать предположение. Конечно, это работает, только если у вас file 5.26 или новее.

Я еще не создал/не тестировал последние версии. Большинство моих машин в настоящее время имеют file 5.04 (2010). надеюсь, что когда-нибудь эта версия сделает это с восходящего потока.

Функции iconv

Введение

Это расширение предоставляет интерфейс к библиотеке преобразования кодировок iconv. Набор поддерживаемых кодировок зависит от реализации iconv в вашей системе. На некоторых платформах iconv может работать ненормально, в таких случаях рекомендуется установить библиотеку » GNU libiconv.

Начиная с PHP 5.0.0, это в расширение добавлены некоторые вспомогательные функции, помогающие при написании сценариев, работающих с несколькими языками.

Требования

Операционные системы, отвечающие стандартам POSIX, поставляются с C-библиотеками, предоставляющими функциональность iconv. Иначе, вам придётся установить библиотеку » libiconv от GNU.

Установка

Чтобы расширение было доступно, нужно указать ключ —with-iconv[=DIR] при запуске сценария конфигурирования.

Note: Примечание для пользователей Windows® Чтобы расширение было доступно, поместите библиотеку с именем iconv.dll или iconv-1.3.dll (для версий до 4.2.1), которая входит в поставку PHP для Windows®, в одну из её системных папок. Этот модуль является частью PHP начиная с версии 5, так что библиотеки iconv.dll и php_iconv.dll более не нужны.

Настройка во время выполнения

Поведение этих функций зависит от установок в php.ini .

Конфигурационные параметры, касающиеся Iconv

Параметр Значение по умолчанию Переменная окружения
iconv.input_encoding ICONV_INPUT_ENCODING PHP_INI_ALL
iconv.output_encoding ICONV_OUTPUT_ENCODING PHP_INI_ALL
iconv.internal_encoding ICONV_INTERNAL_ENCODING PHP_INI_ALL

Для подробностей о константах PHP_INI_* см. ini_set().

Note: На данный момент iconv.input_encoding никак не используется.

Типы ресурсов

Данное расширение не определяет никакие типы ресурсов.

Предопределенные константы

Начиная с PHP 4.3.0 возможно узнать во время выполнения, какая реализация iconv используется расширением.

Константы iconv
Имя Тип Описание
ICONV_IMPL string Реализация
ICONV_VERSION string Версия реализации

Note: Используйте эти константы для написания сценариев, независимых от реализации.

iconv — Преобразование строки в требуемую кодировку

(PHP 4 >= 4.0.5, PHP 5, PHP 7)

iconv — Преобразование строки в требуемую кодировку

Описание

Преобразует набор символов строки str из кодировки in_charset в out_charset .

Список параметров

Кодировка входной строки.

Требуемая на выходе кодировка.

Если добавить к out_charset строку //TRANSLIT, включается режим транслитерации. Это значит, что в случае, если символ не может быть представлен в требуемой кодировке, он будет заменен на один или несколько нескольких наиболее близких по внешнему виду символов. Если добавить строку //IGNORE, то символы, которые не могут быть представлены в требуемой кодировке, будут удалены. В случае отсутствия вышеуказанных параметров при наличии некорректных символов строка str будет обрезана до первого такого символа, и будет сгенерирована ошибка уровня E_NOTICE .

Строка, которую необходимо преобразовать.

Возвращаемые значения

Возвращает преобразованную строку или FALSE в случае возникновения ошибки.

Примеры

Пример #1 Пример использования iconv()

= «This is the Euro symbol ‘€’.» ;

echo ‘Original : ‘ , $text , PHP_EOL ;
echo ‘TRANSLIT : ‘ , iconv ( «UTF-8» , «ISO-8859-1//TRANSLIT» , $text ), PHP_EOL ;
echo ‘IGNORE : ‘ , iconv ( «UTF-8» , «ISO-8859-1//IGNORE» , $text ), PHP_EOL ;
echo ‘Plain : ‘ , iconv ( «UTF-8» , «ISO-8859-1» , $text ), PHP_EOL ;

Результатом выполнения данного примера будет что-то подобное:

PHP iconv: корректная кодировка строк

Использование PHP дает однозначно работающее решение. Если что-то где-то не отображается, нет синтаксических или семантических ошибок, то проблема будет лежать в используемой кодировке символов. Возможны другие коллизии, но нарушения правил кодирования информации — самые частые.

Общее правило представления информации

Всегда имеет значение кодировка файла, в котором содержится скрипт PHP. Если нет проблем с отображением исходного текста в среде разработки или обычном текстовом редакторе, а в браузере ничего прочитать нельзя — не следует обращаться сразу к функции PHP iconv. Нужно просто поправить строчки:

  • «META charset=»UTF-8″» или charset=»windows-1251″;
  • «META HTTP-EQUIV=»Content-Language» CONTENT=»en,ru»».

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

Код PHP — это обработка текстовой информации. Часто программист забывает, что один символ — это далеко не всегда один байт. Если сайт посвящен математическим расчетам, а кириллица применяется при выводе результатов, возможны коллизии. Это решается применением функции iconv() в PHP-коде страницы.

Если в процессе обработки информации используется база данных, то информация может просто «пропасть». В реальность все есть и все работает, просто нужно произвести надлежащие преобразования.

Приведенные примеры показывают, как просто произвести преобразование строк из одной кодировки в другую посредством функции PHP iconv(). Не суть важно, в каком регистре записывать стандартные обозначения кодировок, но смысл использования функции должен быть корректен.

Прежде чем производить преобразование, нужно знать:

  • из какой кодировки;
  • в какую кодировку.

В последнем примере показано, как iconv используется для визуализации исполнения внешней команды dir, исполненной в Windows 10. Результаты работы команды возвращены обратно в место вызова, где PHP iconv() трансформировала их из CP866 в UTF-8, и они корректно отобразились в браузере.

Во всех этих случаях функция предоставила возможность получить информацию в читабельном виде.

Работа с базой данных

При работе с базой данных может случиться так, что PHP iconv не работает. Программист тратит драгоценные часы рабочего времени, но результаты запроса просто не отображаются или помещаются в базу данных в нечитабельном виде.

Проблема решается просто. Если запрос исполняется без ошибок, значит, виновато несоответствие кодировки базы данных и кода страницы. Обычно этого достаточно, если нет, нужно проверить кодировку HTML-страницы, PHP-кода и базы данных. Проблема будет решена.

Характерная черта: кодировок много, условия для исполнения работы многогранны, но если один раз все проверить и обеспечить совместимость, то результат будет абсолютно читабельным, а работа веб-ресурса — безукоризненна.

Илон Маск рекомендует:  Что такое код is_subclass_of
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL