Windows 1251 для php

Заметки Лёвика

web программирование, администрирование и всякая всячина, которая может оказаться полезной

PHP iconv — кодировка из utf-8 windows-1251

При помощи функции php iconv (строго говоря, это не совсем функция PHP, она использует стороннюю библиотеку (есть iconv.dll и php_iconv.dll или iconv.so), которой может не быть на хостинге) легко преобразовать кодировку (например, из windows-1251 в utf-8 и наоборот:

$s = iconv( «cp1251″,»UTF-8», $s);
$s = iconv(«UTF-8», «windows-1251», $s);

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

Про преобразование UFT-8 сущностей я уже писал ранее , однако иногда требуется наоборот перевести текст из cp1251 в utf-8 — например.

Если не работает iconv

function iconv ($in_charset, $out_charset, $str) string — для преобразования из Windows в UTF-8 выполняем один из вызовов
iconv( «cp1251″,»UTF-8», $s);
iconv( «windows-1251″,»UTF-8», $s);
выдаёт пустую строку (если в $s нет английских символов — они в любой кодировке отображаются одинаково) на некоторых хостингах можно попробовать использовать функцию mb_convert_encoding — у неё другой порядок аргументов!
function mb_convert_encoding ($str, $to_encoding, $from_encoding = null) string

Т.е. чтобы преобразовать текст из кодировки windows-1251 в UTF-8 следует выполнить:
mb_convert_encoding($s,»UTF-8″,»windows-1251″);

iconv array для массива

В некоторых ситуациях преобразовать одномерный или многомерный массив из одной кодировки в другую (например, из utf8 в windows-1251) с сохранением ключей массива. Для решения, можно использовать несколько способов.
// если не требуется сохранять предыдущий массив, для экономии
// передаем его по ссылке, происходит замена внутри
function utf8to1251(&$text) <
$text = iconv(«utf-8», «windows-1251», $text); //without return
>
array_walk_recursive($array, «utf8to1251»);

Или, если требуется оставить исходный массив без изменений — можно воспользоваться:
$newArray = array_map(create_function(‘$v’, ‘return iconv(«utf-8», «windows-1251», $v);’), $oldArray);

Метки: iconv

Опубликовано Пятница, Октябрь 21, 2011 в 15:02 в следующих категориях: Без рубрики. Вы можете подписаться на комментарии к этому сообщению через RSS 2.0. Вы можете оставить комментарий. Пинг отключен.

Автор будет признателен, если Вы поделитесь ссылкой на статью, которая Вам помогла:
BB-код (для вставки на форум)

html-код (для вставки в ЖЖ, WP, blogger и на страницы сайта)

ссылка (для отправки по почте)

Комментарии (3) к записи “PHP iconv — кодировка из utf-8 windows-1251”

Как быть с запросом select к базе mssql не понимает кирилицу
“select
[Название]
,[номер]
, [Removed]
from imdb.dbo. Оконечное оборудование “;

Следует привести столбцы (или всю базу данных сразу) к соответствующему сравнению (кодировке)
ALTER DATABASE COLLATE Cyrillic_General_CI_AS

Или использовать Nvarchar

declare @test TABLE
(
Col1 varchar(40),
Col2 varchar(40),
Col3 nvarchar(40),
Col4 nvarchar(40)
)
INSERT INTO @test VALUES
(‘иытание’,N’иытание’,’иытание’,N’иытание’)
SELECT * FROM @test

В старом скрипте на php 5.3 работает
function conv($text) <
return iconv(’UTF-8′, ‘WINDOWS-1251′, $text);
>

Если изменяю версию php 5.6 то не перекодируется. Не подскажете?

Windows-1251 file inside UTF-8 site?

Hello everyone Masters Of Web Delevopment 🙂 I have a piece of PHP script that fetches last 10 played songs from my winamp. This script is inside file (lets call it «lastplayed.php») which is included in my site with php include function inside a «div». My site is on UTF-8 encoding. The problem is that some songs titles are in Windows-1251 encoding. And in my site they displays like «������». Is there any known way to tell to this div with included «lastplayed.php» in it, to be with windows-1251 encoding? Or any other suggestions?

P.S: The file with fetching script a.k.a. «lastplayed.php», is converted to UTF-8. But if it is ANCII it’s the same result. I try to put and meta tag with windows-1251 between head tag but nothing happens again.

P.P.S: Script that fetches the Winamp’s data (lastplayed.php):

And the calling script outside the lastplayed.php:

2 Answers 2

If all of your source data is in windows-1251, you can use something like:

and put that converted data in your HTML stream.

Читайте также:  Jabra windows 10 drivers

Since I’m only looking at docs, I’m not 100% sure that the source encoding alias is correct; you may want to try CP1251 if Windows-1251 doesn’t work.

If your source data isn’t reliably in 1251, you’ll have to come up with a heuristic to guess, and use the same conversion method. mb_detect_encoding may help you.

You cannot change the encoding of just part of an HTML document, but you can certainly convert everything to UTF-8 easily enough.

The newer ID3 implementations have an encoding marker in their text frames:

Is it possible that your content is in UTF16?

Based on the code you’ve posted, it’s not clear how $trackArr is defined, as it’s not referenced elsewhere. It looks like you have several problems.

«auto» expands to a list of encodings that do not include Windows-1251, so I’m not sure why you’ve used it. You really should use «Windows-1251». I have tried using «Windows-1251,utf-16» on a mac with PHP installed, but autodetect fails to find a suitable encoding against a relatively short string, so it looks like you’re going to have to be the one to guess.

But that code doesn’t look like it has any reason to exist anyway, as you overwrite the values with your iteration:

In each iteration, the variable $title_utf8 is assigned to the current track. What you probably want is something more like:

mb_convert_encoding takes a string as the first argument, not an array or object, so you need to apply this encoding on each string that is not utf-8.

iconv

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

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

Описание

Преобразует набор символов строки string из кодировки from_encoding в to_encoding .

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

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

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

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

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

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

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

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

Примеры

Пример #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 39 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.

[UPDATE 15-JUN-2012]
Here’s a workaround.

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??

Читайте также:  Mac os window mockup

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 ;

If you want to convert to a Unicode encoding without the byte order mark (BOM), add the endianness to the encoding, e.g. instead of «UTF-16» which will add a BOM to the start of the string, use «UTF-16BE» which will convert the string without adding a BOM.

( ‘CP1252’ , ‘UTF-16’ , $text ); // with BOM
iconv ( ‘CP1252’ , ‘UTF-16BE’ , $text ); // without BOM

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.

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’ );

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» );
?>

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 );
>
?>

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

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.

Читайте также:  Rapi dll windows 10

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 ;
>
>
>

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.

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.

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

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.

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 ] );

Оцените статью