سؤال

لدي مشكلة مع الأحرف التركية الخاصة على الأجهزة المختلفة. الرمز التالي:

String turkish = "ğüşçĞÜŞÇı";

String test1 = new String(turkish.getBytes());
String test2 = new String(turkish.getBytes("UTF-8"));
String test3 = new String(turkish.getBytes("UTF-8"), "UTF-8");

System.out.println(test1);
System.out.println(test2);
System.out.println(test3);

على Mac، تكون السلاسل الثلاثة هي نفس السلسلة الأصلية. على جهاز Windows الأسطر الثلاثة (مطبوعة باستخدام وحدة التحكم Netbeans 6.7):

?ü?ç?Ü?Ç?
ğüşçĞÜŞÇı
?ü?ç?Ü?Ç?

أنا لا أحصل على المشكلة.

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

المحلول

String test1 = new String(turkish.getBytes());

أنت تأخذ سلسلة Unicode بما في ذلك الأحرف التركية، وتحويلها إلى بايت باستخدام الترميز الافتراضي (باستخدام الترميز الافتراضي عادة ما يكون خطأ). يمكنك بعد ذلك أخذ هذه البايتات ويقوم بإعادة فكها إلى سلسلة، مرة أخرى باستخدام الترميز الافتراضي. النتيجة لم تتحقق شيئا (باستثناء فقدان أي أحرف لا تنسجم في الترميز الافتراضي)؛ سواء كنت قد وضعت سلسلة من خلال دورة تشفير / فك التشفير لديها بدون تأثير على ما يلي System.out.println(test1) هل لأن هذا لا يزال طباعة سلسلة وليس بايت.

String test2 = new String(turkish.getBytes("UTF-8"));

ترميز باسم UTF-8 ثم فك التشفير باستخدام الترميز الافتراضي. على Mac الترميز الافتراضي هو UTF-8 لذلك هذا لا يفعل شيئا. على نظام التشغيل Windows، فإن الترميز الافتراضي ليس UTF-8 لذلك والنتيجة هي الأحرف الخاطئة.

String test3 = new String(turkish.getBytes("UTF-8"), "UTF-8");

لا شيء بالضبط.

لكتابة سلاسل إلى Stdout مع ترميز مختلف من الترميز الافتراضي، ستقوم بإنشاء شيء تشفير new OutputStreamWriter(System.out, "cp1252") وإرسال محتوى السلسلة إلى ذلك.

ولكن في هذه الحالة، يبدو أن وحدة التحكم تستخدم كود Windows Page 1252 أوروبا الغربية (+1 أوروريس). لا توجد مشكلة عدم تطابق تشفير هنا على الإطلاق، لذلك لن تتمكن من حلها عن طريق إعادة ترميز السلاسل!

يطابق الترميز الافتراضي CP1252 من ترميز وحدة التحكم، فهو فقط لا يحتوي CP1252 على الأحرف التركية ğşĞŞı على الاطلاق. يمكنك رؤية الأحرف الأخرى التي نكون في CP1252، üçÜÇ, ، تعال من خلال غرامة فقط. ما لم تتمكن من إعادة تكوين وحدة التحكم لاستخدام ترميز مختلف يتضمن كل الأحرف التي تريدها، لا توجد طريقة ستتمكن من إخراج تلك الأحرف.

من المفترض على تثبيت Windows التركي، ستكون صفحة الرموز الافتراضية CP1254 بدلا من ذلك، وسوف تحصل على الأحرف التي تتوقعها (ولكن الأحرف الأخرى لا تعمل). يمكنك اختبار هذا عن طريق تغيير "اللغة لاستخدام" إعداد تطبيقات غير Unicode "في تطبيق لوحة التحكم في الخيارات الإقليمية واللغة.

لسوء الحظ، لا يستخدم Windows Locale UTF-8 كصفحة الرموز الافتراضية. إن وضع إخراج غير ASCII على وحدة التحكم مع وظائف Studio Stream ليس شيئا موثوقا حقا على الإطلاق. هناك API Win32 لكتابة Unicode مباشرة إلى وحدة التحكم، ولكن لسوء الحظ، لا شيء يستخدمه كثيرا.

نصائح أخرى

لا تعتمد على وحدة التحكم، أو في ترميز النظام الأساسي الافتراضي. حدد دائما ترميز الشخصية للمكالمات مثل getBytes وبناء سلسلة أخذ صفيف بايت، وإذا كنت ترغب في فحص محتويات السلسلة، قم بطباعة قيمة Unicode لكل حرف.

أود أيضا أن أنصح إما تقييد شفرة المصدر الخاصة بك لاستخدام ASCII (و uxxxx لترميز أحرف غير ASCII) أو تحديد صراحة ترميز الأحرف عند الترجمة.

الآن، ما المشكلة الكبيرة التي تحاول حلها؟

قد تكون تتعامل مع إعدادات مختلفة من الترميز الافتراضي.

java -Dfile.encoding=utf-8

عكس

java -Dfile.encoding=something else

أو، قد ترى فقط حقيقة أن نافذة Mac Terminal تعمل في UTF-8، ويعمل مربع Windows DOS ليس العمل في UTF-8.

وفقا للسيد Skeet، لديك مشكلة محتملة ثالثة، وهي أنك تحاول تضمين الأحرف UTF-8 في المصدر الخاص بك. اعتمادا على خيارات المحول البرمجي، قد تحصل أو لا تحصل على ما تنويه هناك. ضع هذه البيانات في ملف الخصائص، أو استخدم يو يهرب.

أخيرا، أيضا في السيد Skeet، لا تسميه أبدا، من أي وقت مضى Getbytes من الصفر

إذا كنت تستخدم GESTERSJ مترجم لا تنسى تعيين ترميزه إلى UTF-8 أيضا. لقد كافحت للعثور على هذا لساعات.

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