7 ردود في هذا الموضوع

السلام  عليكم 

 

موضوع  شامل و  أكثر  من  رائع  يستحق  التقييم   و فقك  الله

 

لكن  هل  الدول  العربية  في  ذلك  الوقت  صنعت  لنفسها  ترميز  ام  اننا  اكتفينا  بالمشاهدة  فقط  ؟!! 

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
لكن  هل  الدول  العربية  في  ذلك  الوقت  صنعت  لنفسها  ترميز  ام  اننا  اكتفينا  بالمشاهدة  فقط  ؟!!

من قرائتي لم يرد ذكر أى من الدول العربية.

 

 

و الله ولي التوفيق

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

شكراً لك أخي محمد على المقالة الرائعة.

 

معلومات بسيطة عند التعامل مع العربية، قد يكون لديك ملفين فيهم كلمة معينة إلا أن محتويات كل ملف ستختلف كلياً عن الآخر إذا كان الترميز مختلف. أيضاً عند ظهور الكلام بلغة أخرى أو يظهر رموز فالأرجح أنك تقرأها بالترميز الخطأ.

 

اللغة العربية غالباً نخزن بأحد الترميزين windows-1256 أو utf-8 كلهم مختلفين:

 

ترميز windows-1256 شائع الإستخدام، يمكنك تمييزه بأن حجم الملف بالبايت يساوي عدد الحروف، كلمة "أبجد" ستخزن 0xc3 0xc8 0xcc 0xcf (يفترض أن يكون عندك محرر هكس):

00000000 C3 C8 CC CF                                        ....            

التعامل مع الملف ببايثون، لاحظ أني فتحت الملف كـrb (قراءة كبيانات read-binary) كي لاتتدخل اللغة وتعدل في الحروف:

> python -c "print(open('windows-1256.txt', 'rb').read())"b'\xc3\xc8\xcc\xcf'> python -c "print(open('windows-1256.txt', 'rb').read().decode('windows-1256'))"أبجد>

عند فتح ملف بهذا الترميز وكنت تستخدم ترميز اللغات الاتينية (windows-1252, ISO-8859-1, Latin-1) فسيظهر لك ÃÈÌÏ، أحرف أو أرقام إنجليزية أو أحرف مع علامات.

 

ترميز utf-8 يمكنك تمييزة بعلامة BOM 0xef 0xbb 0xbf (لن تجدها دائماً ولا ينصح باستخدامها)، حجم الملف بالبايت يساوي ضعف عدد الأحرف إذا كانت الأحرف فقط عربية (بايتين لكل حرف عربي و بايت لحروف الآسكي، و 3 بايتات إضافية إن كان علامة BOM موجودة) .

 

ملف أبجد مع علامة BOM:

00000000 EF BB BF D8 A3 D8 A8 D8 AC D8 AF                   ...........     

القراءة من بايثون، حذفت علامة BOM قبل فك ترميز الملف، وإلا فستعطيني خطأ عند فك الترميز:

> python -c "print(open('utf-8.txt', 'rb').read())"b'\xef\xbb\xbf\xd8\xa3\xd8\xa8\xd8\xac\xd8\xaf'> python -c "print(open('utf-8.txt', 'rb').read()[3:].decode('utf-8'))"أبجد>

إذا قرأته بترميز اللغات الغربية فسيظهر أبجد. إذا قرأته بترميز العربية windows-1256 فسيظهر ط£ط¨ط¬ط¯.

 

====================================================

 

بالنسبة لمبرمجين ويندوز، أغلب المصادر والكتب تشير لأن ويندوز يستخدم داخلياً اليونيكود، النظام تحديداً يستنخدم ترميز utf-16le، ترميز utf-16 مع بايتات مقلوبة little endian. ملف أبجد سيحتوي عند ترميزه بـutf-16le:

00000000 23 06 28 06 2C 06 2F 06                            #.(.,./.

محتويات الملف:

> python -c "print(open('utf-16.txt', 'rb').read())"b'#\x06(\x06,\x06/\x06'> python -c "print(open('utf-16.txt', 'rb').read().decode('utf-16le'))"أبجد>

لينكس يستخدم داخلياً ترميز utf-8.

3

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

ملحوظة: كل الأكواد  التالية تهدف للتوضيح و إن اردت إستخدامها داخل برامجك يمكنك إجراء تحسينات كثيرة عليها.

 

قد يتسائل أحدكم:

ما هى الطريقه التى يمكنني بها التحويل بين الـ code-pages بدون إستخدام أى مكتبات خارجية أو المكتبة الإفتراضية التى تأتى مع لغتي؟

 

الإجابه: بمعرفة أن أى صفحة محارف تحتوى فقط على 256 كود و الـ 128 الأوليين هما لـ ASCII، يمكننا كتابة مصفوفة من 128 عنصر و قيمة كل عنصر يساوى كود Unicode لذلك العنصر، بمعني الحرف 'م' من صفحة محارف 'windows-1526' له الكود 227 و بالتالي داخل مصفوفتنا سيأخذ الكود 99 (227-128) و قيمة ذلك العنصر ستكون قيمة الحرف 'م' داخل Unicode و هو U+0645 (و هذا يجعل نوع هذه المصفوفه Unisgned 16-bit Integer)، و شكلها فى لغة C++/C كالتالي:

const unsigned short windows1256[] ={	0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,	0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA,	0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,	0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F,	0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,	0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643,	0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF,	0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2};

هذه المصفوفة تحتوى على كود UTF-32 للحروف، و حيث أن حروف صفحة المحارف هذه يمكن حفظه داخل 16 بت دون مشاكل فكانت هذه المساحة التى أستخدمتها.

 

لتحويل محتوى نص من صفحة المحارف windows-1256 ليونيكود كل ما تحتاجه هو الحصول على موقع كود الحرف داخل المصفوفة ثم العودة به: (الكود التالي بفترض ان النص قد يحتوى على حروف ASCII أيضا)

unsigned short to_unicode (char c){	unsigned char uc = (unsigned char)c ;	if (uc < 128) return uc;		return windows1256[uc-128];}

الكود السابق يقوم بتحويل حرف بصفحة محارف windows-1256 ليونيكود و يمكنك كتابة حلقو تكرار لإستدعاء الدالة و الحصول على محتوى النص بأكمله داخل ترميز يونيكود.

 

قبل حفظ قيمة الحرف يمكنك كتابة دوال لتحويل قيمة الحرف من UTF-32 إلى UTF-16 أو UTF-8 كما تريد.

 

سؤال أخر: ماذا يحدث لو أردت التحويل بين صفحتان محارف مثل windows-1256 و oem720 حيث كلاهما يحتوى على حروف العربية؟

الإجابه: الحل يكون فى كتابتك مصفوفتين كل منهم يحتوى على 128 عنصر، أما الأولي فستكتبها بنفسك، و الأخرى ستقوم بتوليدها تلقائيا:

unsigned short oem720[] ={	0xffff, 0xffff, 0x00E9, 0x00E2, 0xffff, 0x00E0, 0xffff, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0xffff, 0xffff, 0xffff, 	0xffff, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, 	0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, 	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 	0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 	0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 	0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0};

المصفوفه oem720 تم تحديد محتوياتها كما تم تحديد محتويات المصفوفة windows1256 و يوجد هنا أمر جديد و هو القيمة 0xffff حيث هذه القيمة انا استخدمتها خصيصا لسبيبن:

  1. يونيكود تؤكد ان هذا الكود غير مرتبط بحرف و لا يمكن استخدامه داخل سلسلة أكواد.
  2. أثناء التحويل إذا وجد هذا الكود فإن عملية التحويل فاشلة لإن المصفوفة oem720 لا تستطيع ترميز كل الحروف الموجوده بالمصفوفه (صفحة المحارف) التى تقوم بالتحويل منها.

المصفوفة الثانية التى سنقوم بتوليدها سنعطيها الإسم WinToOem حيث موقع كل عنصر بها هو موقع حرف داخل صفحة المحارف windows-1256 و قيمة ذلك الحرف هى موقع العنصر داخل صفحة محارف oem720، و بالتالي إذا اردنا تحويل نص من صفحة محارف windows1256 إلى oem720 كل ما سنفعله هو تمرير الكود للمصفوفة WinToOem و الناتج سيكون قيمة الحرف داخل صفحة محارف oem720.

char WinToOem[128];int find(unsigned short* array, unsigned short value){    for(int i=0; i<128; ++i)    {        if (array[i] == value) return i;    }    return -1;}void gen_array(){    for(int i=0; i<128; ++i)    {        int r = find(oem720, windows1256[i]);                if (r == -1)            WinToOem[i] = 0;        else            WinToOem[i] = i + 128;    }}

كل عنصر بالمصفوفة WinToOem يحتوى على صفر و هذا يعنى انه الحرف لا يوجد له مثيل فى oem720 (تذكر المصفوفة لا تحتوى على أكواد ASCII و الكود صفر لا يتم إستخدامه أبدا داخل اى صفحة محارف ماعدا للحرف NULL و هذا مؤكد) أو كود الحرف داخل oem720.

 

الإسلوب السابق هو ما اتبعته داخل مكتبة charset مع بعض التعميم لتطبيق الطريقة على العديد من صفحات المحارف.

 

 

و الله ولي التوفيق

تم تعديل بواسطه C++er
4

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

موضوع جميل جداً و أشكرك على طرحه :)

 

بالنسبة للعربي فالمعروف هو استخدامنا لـ Windows-1256 على نظام الوندوز و UTF-8 عموماً و لكن هناك أيضاً ISO و تم تخصيص رقم 6 للغة العربية ليصبح اسمه ISO 8859-6 و لكنه غير مستخدم أو لا أراه مستخدم في برامج مهمه و لكن هناك برامج تتعامل معه مثل برنامج Kate و KWrite  و ما يشتق منهم و ذلك على اللينوكس.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

انا شاكر لحضرتك جدا على الشرح

 

كنت محتاجه جدا

 

بارك الله فيك

تم تعديل بواسطه مصطفى 36a2
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



سجل دخولك الان

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .