التعامل مع EACUTE والشخصيات الخاصة الأخرى باستخدام Oracle و PHP و OCI8

StackOverflow https://stackoverflow.com/questions/2357680

سؤال

مرحبًا ، أحاول تخزين الأسماء في قاعدة بيانات 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 المباشر مع é يعمل.

المشكلة هي في الواقع على جانب PHP. باستخدام ExtJS Framework ، عند إرسال نموذج ، فإنه يشفره باستخدامه encodeURIComponent.
لذا é يتم إرسالها على النحو %C3%A9 ثم إعادة ترميزها é.
ومع ذلك ، فإن الطول الآن 2 (strlen($my_sent_value) = 2) وليس 1. وإذا كنت في php أحاول: $ my_sent_value == é = خاطئة

أعتقد أنه إذا كنت قادرًا على إعادة ترميز كل هذه الشخصيات في 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 هذه مرتين بسرعة .... لقد نجحت !!!
في أوراكل رأيت بشكل صحيح |é|.

يبدو أنه ربما لا يتم تعيين متغير البيئة بشكل صحيح أو إرساله في الوقت المناسب للتنفيذ الأول للنص ، ولكنه متاح للتنفيذ الثاني.

تجربتي التالية هي تصدير المتغير إلى بيئة PHP ، ومع ذلك ، أحتاج إلى إعادة تعيين Apache لذلك ... لذلك سنرى ما يحدث ، ونأمل أن يعمل.

هل كانت مفيدة؟

المحلول 2

هذا ما انتهى بي الأمر أخيرًا لحل هذه المشكلة:

عدل ملف تعريف الخفي الذي يدير PHP ليكون:

NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1

بحيث يستخدم اتصال OCI8 ISO-8859-1.

ثم في تكوين PHP الخاص بي ، قم بتعيين نوع المحتوى الافتراضي إلى ISO-8859-1:

default_charset = "iso-8859-1"

عندما أقوم بإدخال جدول أوراكل عبر OCI8 من PHP ، أفعل:

utf8_decode($my_sent_value)

وعند تلقي البيانات من Oracle ، يجب أن تعمل طباعة المتغير فقط على النحو التالي:

echo $my_received_value

ومع ذلك ، عند إرسال تلك البيانات عبر أياكس ، اضطررت إلى استخدام:

utf8_encode($my_received_value)

نصائح أخرى

أفترض أنك على دراية بهذه الحقائق:

  • هناك العديد من مجموعات الأحرف المختلفة: عليك اختيار واحدة ، وبطبيعة الحال ، تعرف أي شخص تستخدمه.
  • Oracle قادر تمامًا على تخزين النص بدون كيانات HTML (é). يتم استخدام كيانات HTML في ، حسنا ، HTML. أوراكل ليس متصفح ويب ؛-)

يجب أن تعرف أيضًا أن كيانات HTML لا ترتبط بـ Charset معين ؛ على العكس من ذلك ، يتم استخدامها لتمثيل الأحرف في سياق مستقل عن Charset.

أنت تتحدث بشكل غير واضح عن ISO-8859-1 و UTF-8. ما هو charset تريد استخدامه؟ ISO-8859-1 سهل الاستخدام ، لكن لا يمكنه تخزين النص إلا في بعض اللغات اللاتينية (مثل الإسبانية) ويفتقر إلى بعض العربات الشائعة مثل رمز €. يعد استخدام UTF-8 أكثر صعوبة في استخدامه ، لكن يمكنه تخزين جميع الأحرف المحددة بواسطة Consortium Unicode (والتي تشمل كل ما تحتاجه على الإطلاق).

بمجرد اتخاذ القرار ، يجب عليك تكوين Oracle للاحتفاظ بالبيانات في مثل هذا Charset واختيار نوع العمود المناسب. على سبيل المثال ، varchar2 على ما يرام بالنسبة إلى ASCII العادي ، NVARCHAR2 مفيد لـ UTF-8.

إذا لم تتمكن حقًا من تغيير مجموعة الأحرف التي ستستخدمها Oracle ، فماذا عن ترميز BASE64 لترميز بياناتك قبل تخزينها في قاعدة البيانات. وبهذه الطريقة ، يمكنك قبول الشخصيات من أي مجموعة أحرف وتخزينها كـ ISO-8859-1 (لأن BASE64 ستخرج مجموعة فرعية من مجموعة أحرف ASCII والتي تعرّف تمامًا إلى ISO-8859-1). سيؤدي ترميز BASE64 إلى زيادة طول السلسلة بنسبة 37 ٪ في المتوسط

إذا لم يتم عرض بياناتك إلا على أنها HTML ، فيمكنك أيضًا تخزين كيانات HTML كما اقترحت ، ولكن كن على علم بأن كيان واحد يمكن أن يصل إلى 10 أحرف لكل حرف غير مشفر على سبيل المثال ϑ

اضطررت إلى مواجهة هذه المشكلة: يتم تخزين الشخصيات الخاصة الأمريكية اللاتينية على أنها "؟" أو "¿" في قاعدة بيانات 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 );

في أوراكل ، استخدم ما يلي:

 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-tring-to-hex--hex-to-string-in-net.aspx https://forums.oracle.com/thread/44799

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top