Работа с eacute и другими специальными символами с использованием Oracle, PHP и Oci8

Привет, Я пытаюсь сохранить имена в базе данных Oracle и вернуть их с помощью PHP и oci8.

Однако, если я вставляю é непосредственно в базу данных Oracle и использую oci8 для его возврата, я просто получаю e

Должен ли я кодировать все специальные символы (включая é ) в html-объекты (т.е.: é ) перед вставкой в ​​базу данных … или я чего-то не хватает?

Спасибо


ОБНОВЛЕНИЕ: 1 марта в 18:40

нашел эту функцию: http://www.php.net/manual/en/function.utf8-decode.php#85034

 function charset_decode_utf_8($string) { if(@!ereg("[\200-\237]",$string) && @!ereg("[\241-\377]",$string)) { return $string; } $string = preg_replace("/([\340-\357])([\200-\277])([\200-\277])/e","'&#'.((ord('\\1')-224)*4096 + (ord('\\2')-128)*64 + (ord('\\3')-128)).';'",$string); $string = preg_replace("/([\300-\337])([\200-\277])/e","'&#'.((ord('\\1')-192)*64+(ord('\\2')-128)).';'",$string); return $string; } 

кажется, работает, хотя и не уверен, что его оптимальное решение


ОБНОВЛЕНИЕ: 8 марта в 15:45

Набор символов Oracle – ISO-8859-1.
в PHP я добавил:

 putenv("NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1"); 

чтобы заставить соединение oci8 использовать этот набор символов. Получение работы с использованием oci8 с PHP теперь работает! (для varchars , но не CLOBs должен был сделать utf8_encode чтобы извлечь его)
Итак, я попытался сохранить данные с PHP на Oracle … и он не работает. Где-то на пути от PHP к Oracle, а ?


ОБНОВЛЕНИЕ: 9 марта в 14:47

Так что все ближе. Добавив переменную NLS_LANG, выполните прямые вставки oci8 с помощью é works.

Проблема на самом деле на стороне PHP. Используя инфраструктуру ExtJs, при отправке формы она кодирует ее с encodeURIComponent .
Таким образом, é отправляется как %C3%A9 а затем перекодируется в é .
Однако это длина теперь 2 (strlen($my_sent_value) = 2) а не 1. И если в PHP я пытаюсь: $ my_sent_value == é = FALSE

Я думаю, что если я могу перекодировать все эти символы в PHP обратно в длину байта размером 1, а затем вставлять их в Oracle, он должен работать.

Еще не повезло


ОБНОВЛЕНИЕ: 10 марта в 11:05

Я продолжаю думать, что я так близок (пока еще далеко).

putenv("NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P9"); работает очень спорадично.

Я создал небольшой скрипт php для тестирования:

 header('Content-Type: text/plain; charset=ISO-8859-1'); putenv("NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P9"); $conn= oci_connect("user", "pass", "DB"); $stmt = oci_parse($conn, "UPDATE temp_tb SET string_field = '|é|'"); oci_execute($stmt, OCI_COMMIT_ON_SUCCESS); 

После запуска этого один раз и входа в базу данных Oracle напрямую я вижу, что для параметра STRING_FIELD установлено значение |¿| , Очевидно, не то, что я ожидал от своего предыдущего опыта.
Однако, если я обновляю эту страницу PHP дважды быстро … это сработало !!!
В Oracle я правильно видел |é| ,

Кажется, что, возможно, переменная окружения неправильно настроена или отправлена ​​во время первого запуска скрипта, но доступна для второго выполнения.

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

Я полагаю, вы знаете об этих фактах:

  • Существует множество разных наборов символов: вам нужно выбрать один и, конечно же, узнать, какой из них вы используете.
  • Oracle отлично умеет хранить текст без объектов HTML ( é ). HTML-объекты используются, ну, HTML. Oracle не является веб-браузером 😉

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

Вы нечетко говорите об ISO-8859-1 и UTF-8. Какую кодировку вы хотите использовать? ISO-8859-1 прост в использовании, но он может хранить только текст на некоторых латинских языках (например, на испанском языке), и ему не хватает общих символов, таких как символ. UTF-8 сложнее использовать, но он может хранить все символы, определенные консорциумом Unicode (включая все, что вам когда-либо понадобится).

После того, как вы приняли решение, вы должны настроить Oracle для хранения данных в такой кодировке и выбрать соответствующий тип столбца. Например, VARCHAR2 отлично подходит для простого ASCII, NVARCHAR2 подходит для UTF-8.

Вот что я, наконец, сделал для решения этой проблемы:

Изменен профиль демона с запущенным PHP:

 NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1 

Так что соединение oci8 использует ISO-8859-1.

Затем в моей конфигурации PHP установите тип содержимого по умолчанию в ISO-8859-1:

 default_charset = "iso-8859-1" 

Когда я вставляю в таблицу Oracle через oci8 из PHP, я делаю:

 utf8_decode($my_sent_value) 

И, получая данные от Oracle, печать переменной должна работать только так:

 echo $my_received_value 

Однако при отправке этих данных по ajax мне пришлось использовать:

 utf8_encode($my_received_value) 

Если вы действительно не можете изменить набор символов, который будет использовать оракул, то как насчет Base64, кодирующего ваши данные, прежде чем хранить его в базе данных. Таким образом, вы можете принимать символы из любого набора символов и хранить их как ISO-8859-1 (потому что Base64 выведет подмножество набора символов ASCII, который точно соответствует ISO-8859-1). Кодировка Base64 увеличит длину строки, в среднем, на 37%

Если ваши данные будут отображаться только как HTML, вы также можете хранить объекты HTML, как вы предполагали, но имейте в ϑ что один объект может содержать до 10 символов на unencoded символ, например θ is ϑ

Мне пришлось столкнуться с этой проблемой: специальные символы LatinAmerican хранятся как «?» или «¿» в моей базе данных Oracle … Я не могу изменить NLS_CHARACTER_SET, потому что мы не являемся владельцами баз данных.

Итак, я нашел обходное решение:

1) Код ASP.NET Создайте функцию, которая преобразует строку в шестнадцатеричные символы:

  public string ConvertirStringAHex(String input) { Encoding encoding = System.Text.Encoding.GetEncoding("ISO-8859-1"); Byte[] stringBytes = encoding.GetBytes(input); StringBuilder sbBytes = new StringBuilder(stringBytes.Length); foreach (byte b in stringBytes) { sbBytes.AppendFormat("{0:X2}", b); } return sbBytes.ToString(); } 

2) Примените функцию выше к переменной, которую вы хотите кодировать, например

  myVariableHex = ConvertirStringZHex( myVariable ); 

В ORACLE используйте следующее:

  PROCEDURE STORE_IN_TABLE( iTEXTO IN VARCHAR2 ) IS BEGIN INSERT INTO myTable( SPECIAL_TEXT ) VALUES ( UTL_RAW.CAST_TO_VARCHAR2(HEXTORAW( iTEXTO )); COMMIT; END; 

Конечно, iTEXTO – это параметр Oracle, который получает значение «myVariableHex» из кода ASP.NET.

Надеюсь, это поможет … если есть что-то, чтобы улучшить PLS, не стесняйтесь публиковать свои комментарии.

Источники: http://www.nullskull.com/faq/834/convert-string-to-hex-and-hex-to-string-in-net.aspx https://forums.oracle.com/thread/44799