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

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

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

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

Thx


ОБНОВЛЕНИЕ: 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 с é работает.

Проблема на самом деле на стороне 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 ... так что посмотрим, что произойдет, надеюсь, это сработает.

Ответы [ 4 ]

2 голосов
/ 11 марта 2010

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

Изменен профиль демона, на котором запущен 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)
2 голосов
/ 03 марта 2010

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

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

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

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

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

0 голосов
/ 25 октября 2013

Мне пришлось столкнуться с этой проблемой: латинско-американские специальные символы хранятся как "?" или "¿" в моей базе данных 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.

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

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

0 голосов
/ 09 марта 2010

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

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

...