Php latin1 general ci

Кодирование SQL_Latin1_General_CP1_CI_AS в UTF-8

Я создаю XML-файл с PHP, используя DomDocument, и мне нужно обрабатывать азиатские символы. Я извлекаю данные с сервера MSSQL2008 с помощью драйвера pdo_mssql и применяю utf8_encode () к значениям атрибутов XML. Все работает отлично, пока нет специальных символов.

Сервер – это MS SQL Server 2008 SP3

Сборка базы данных, таблицы и столбца – это все SQL_Latin1_General_CP1_CI_AS

$pdo = new PDO("mssql:host=MyServer,1433;dbname=MyDatabase", user123, password123); 

Мой запрос является базовым SELECT.

Я знаю, что хранение специальных символов в столбцах SQL_Latin1_General_CP1_CI_AS невелик, но в идеале было бы неплохо заставить его работать, не меняя его, потому что другие не-PHP-программы уже используют этот столбец, и он отлично работает. В SQL Server Management Studio я правильно вижу азиатские символы.

Учитывая все вышеперечисленные детали, как мне обрабатывать данные?

Я нашел, как его решить, поэтому, надеюсь, это будет полезно кому-то.

Во-первых, SQL_Latin1_General_CP1_CI_AS – странное сочетание CP-1252 и UTF-8. Основными персонажами являются CP-1252, поэтому я все-таки должен был сделать UTF-8, и все сработало. Асимвольные и другие символы UTF-8 закодированы на 2 байта, и драйвер php pdo_mssql, кажется, ненавидит переменные длины символов, поэтому он, похоже, делает CAST для varchar (вместо nvarchar), а затем все 2 байтовых символа становятся вопросительными знаками (‘ ? ‘).

Я исправил его, выставив его в двоичный файл, а затем перестроил текст с помощью php:

SELECT CAST(MY_COLUMN AS VARBINARY(MAX)) FROM MY_TABLE; 
//Binary to hexadecimal $hex = bin2hex($bin); //And then from hex to string $str = ""; for ($i=0;$i //And then from UCS-2LE/SQL_Latin1_General_CP1_CI_AS (that's the column format in the DB) to UTF-8 $str = iconv('UCS-2LE', 'UTF-8', $str); 

Я знаю, что этот пост старый, но единственное, что работает для меня, это iconv («CP850», «UTF-8 // TRANSLIT», $ var); У меня были те же проблемы с SQL_Latin1_General_CP1_CI_AI, возможно, он работает и для SQL_Latin1_General_CP1_CI_AS.

header("Content-Type: text/html; charset=utf-8"); $dbhost = "hostname"; $db = "database"; $query = "SELECT * FROM Estado ORDER BY Nome"; $conn = new PDO( "sqlsrv:server=$dbhost ; Database = $db", "", "" ); $stmt = $conn->prepare( $query, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED, PDO::SQLSRV_ENCODING_SYSTEM) ); $stmt->execute(); while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ) < // CP1252 == code page Latin1 print iconv("CP1252", "ISO-8859-1", "$row[Nome] 
"); >

По умолчанию PDO использует PDO::SQLSRV_ENCODING_UTF8 для отправки / получения данных.

Если ваш текущий результат равен LATIN1 , попробовали ли вы специфицировать PDO::SQLSRV_ENCODING_SYSTEM чтобы PDO знал, что вы хотите использовать текущую системную кодировку вместо UTF-8 ?

Вы даже можете использовать PDO::SQLSRV_ENCODING_BINARY который возвращает данные в двоичной форме (при передаче данных не происходит кодирования или перевода). Таким образом, вы можете обрабатывать кодировку символов на вашей стороне.

Спасибо @SGr за ответ.
Я нашел лучший способ сделать это:

SELECT CAST(CAST(MY_COLUMN AS VARBINARY(MAX)) AS VARCHAR(MAX)) as MY_COLUMN FROM MY_TABLE;
а также попробуйте:
SELECT CAST(MY_COLUMN AS VARBINARY(MAX)) as MY_COLUMN FROM MY_TABLE;

И в PHP вы должны просто преобразовать его в UTF-8:

$string = iconv(‘UCS-2LE’, ‘UTF-8’, $row[‘MY_COLUMN’]);

Для меня ни одно из вышеперечисленных не было прямым решением, хотя я использовал некоторые части вышеперечисленных решений. Это работало для меня с вьетнамским алфавитом. Если вы столкнулись с этим сообщением, и ни одно из вышеперечисленных действий для вас не поможет, попробуйте:

 $req = "SELECT CAST(MY_COLUMN as VARBINARY(MAX)) as MY_COLUMN FROM MY_TABLE"; $stmt = $conn->prepare($req); $stmt->execute(); while ($row = $stmt->fetch(PDO::FETCH_ASSOC))

И небольшой бонус – мне пришлось json_encode эти данные и был (duh) получать html-код вместо специальных символов. для исправления просто используйте html_entity_decode () для строк перед отправкой с помощью json_encode.

Источник

mysqli_set_charset

Задаёт набор символов, который будет использоваться при обмене данными с сервером баз данных.

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

Только для процедурного стиля: объект mysqli , полученный с помощью mysqli_connect() или mysqli_init() .

Набор символов, который необходимо установить.

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

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

Ошибки

Если уведомления об ошибках mysqli включены ( MYSQLI_REPORT_ERROR ) и запрошенная операция не удалась, выдаётся предупреждение. Если, кроме того, установлен режим MYSQLI_REPORT_STRICT , вместо этого будет выброшено исключение mysqli_sql_exception .

Примеры

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

mysqli_report ( MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT );
$mysqli = new mysqli ( «localhost» , «my_user» , «my_password» , «test» );

printf ( «Начальный набор символов: %s\n» , $mysqli -> character_set_name ());

/* изменение набора символов на utf8mb4 */
$mysqli -> set_charset ( «utf8mb4» );

printf ( «Текущий набор символов: %s\n» , $mysqli -> character_set_name ());

mysqli_report ( MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT );
$link = mysqli_connect ( ‘localhost’ , ‘my_user’ , ‘my_password’ , ‘test’ );

printf ( «Начальный набор символов: %s\n» , mysqli_character_set_name ( $link ));

/* изменение набора символов на utf8mb4 */
mysqli_set_charset ( $link , «utf8mb4» );

printf ( «Текущий набор символов: %s\n» , mysqli_character_set_name ( $link ));

Результат выполнения данных примеров:

Начальный набор символов: latin1 Текущий набор символов: utf8mb4

Примечания

Замечание:

Чтобы использовать эту функцию на Windows платформах, вам потребуется клиентская библиотека MySQL версии 4.1.11 или выше (для MySQL 5.0 соответственно 5.0.6 или выше).

Замечание:

Это предпочтительный способ задания набора символов. Использование для этих целей функции mysqli_query() (например SET NAMES utf8 ) не рекомендуется. Дополнительно смотрите Наборы символов в MySQL.

Смотрите также

  • mysqli_character_set_name() — Возвращает текущую кодировку, установленную для соединения с БД
  • mysqli_real_escape_string() — Экранирует специальные символы в строке для использования в SQL-выражении, используя текущий набор символов соединения
  • Концепции кодировок MySQL
  • » Список поддерживаемых MySQL наборов символов

User Contributed Notes 5 notes

Setting the charset (it’s really the encoding) like this after setting up your connection:
$connection->set_charset(«utf8mb4»)

FAILS to set the proper collation for the connection:

character_set_client: utf8mb4
character_set_connection: utf8mb4
character_set_database: utf8mb4
character_set_filesystem: binary
character_set_results: utf8mb4
character_set_server: utf8mb4
character_set_system: utf8
collation_connection: utf8mb4_general_ci collation_database: utf8mb4_unicode_ci
collation_server: utf8mb4_unicode_ci

If you use SET NAMES, that works:
$connection->query(«SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci»);

character_set_client: utf8mb4
character_set_connection: utf8mb4
character_set_database: utf8mb4
character_set_filesystem: binary
character_set_results: utf8mb4
character_set_server: utf8mb4
character_set_system: utf8
collation_connection: utf8mb4_unicode_ci collation_database: utf8mb4_unicode_ci
collation_server: utf8mb4_unicode_ci

Please note, that I set the following variables on the server:

Set the following to be: utf8mb4_unicode_ci

character-set-client-handshake = FALSE or 0
skip-character-set-client-handshake = TRUE or 1

So in my case, I had tried changing the collation from utf8mb4_unicode_ci for mysql and had to change it to uft8_general_ci.

mysqli_set_charset( $con, ‘utf8’);

right before I did the SELECT command.

This is my code for reading from db :

$con = mysqli_connect($DB_SERVER, $DB_USER_READER, $DB_PASS_READER, $DB_NAME, $DB_PORT);//this is the unique connection for the selection

mysqli_set_charset( $con, ‘utf8’);

$slct_stmnt = «SELECT «.$SELECT_WHAT.» FROM «.$WHICH_TBL.» WHERE «.$ON_WHAT_CONDITION;

$slct_query = mysqli_query($con, $slct_stmnt);

if ($slct_query==true) //Do your stuff here . . .
>

And it worked like a charm. All the best. The above code can work with reading chineese, russian or arabic or any international language from the database’s table column holding such data.

Although the documentation says that using that function is preferred than using SET NAMES, it is not sufficient in case you use a collation different from the default one:

// That will reset collation_connection to latin1_swedish_ci
// (the default collation for latin1):
$mysqli -> set_charset ( ‘latin1’ );

// You have to execute the following statement *after* mysqli::set_charset()
// in order to get the desired value for collation_connection:
$mysqli -> query ( «SET NAMES latin1 COLLATE latin1_german1_ci» );

To align both the character set (e.g., utf8mb4) AND the collation sequence with the schema (database) settings:

$mysqli = new mysqli ( DB_HOST , DB_USER , DB_PASSWORD , DB_SCHEMA , DB_PORT );
if ( 0 !== $mysqli -> connect_errno )
throw new \ Exception ( $mysqli -> connect_error , $mysqli -> connect_errno );

if ( TRUE !== $mysqli -> set_charset ( ‘utf8mb4’ ) )
throw new \ Exception ( $mysql -> error , $mysqli -> errno );

if ( TRUE !== $mysqli -> query ( ‘SET collation_connection = @@collation_database;’ ) )
throw new \ Exception ( $mysql -> error , $mysqli -> errno );
?>

To confirm:

echo ‘character_set_name: ‘ , $mysqli -> character_set_name (), ‘
‘ , PHP_EOL ;
foreach( $mysqli -> query ( «SHOW VARIABLES LIKE ‘%_connection’;» )-> fetch_all () as $setting )
echo $setting [ 0 ], ‘: ‘ , $setting [ 1 ], ‘
‘ , PHP_EOL ;
?>

will output something like:
character_set_name: utf8mb4
character_set_connection: utf8mb4
collation_connection: utf8mb4_unicode_520_ci

Note that using utf8mb4 with this function may cause this function to return false, depending on the MySQL client library compiled into PHP. If the client library is older than the introduction of utf8mb4, then PHP’s call of the libraries ‘mysql_set_character_set’ will return an error because it won’t recognise that character set.

The only way you will know there’s an error is by checking the return value, because PHP warnings are not emitted by this function.
mysqli_error will return something like:
«Can’t initialize character set utf8mb4 (path: /usr/share/mysql/charsets/)»
(I don’t think the directory has anything to do with it; I think the utf8mb4 vs utf8 distinction is handled internally)

A workaround is to recall with utf8, then do a ‘SET NAMES’ query with utf8mb4.

If your MySQL server is configured to use utf8 by default, then you may not notice any of this until you get obscure bugs. It seems it will still save into the database correctly in terms of bytes. However, you may get «Data too long for column» errors if you are truncating strings to fit fields, because from MySQL’s point of view during the length check every 4-byte character will actually be multiple individual characters. This caused me hours of debugging.

Источник

Читайте также:  Java нет java control panel
Оцените статью