مدخل إلى ترميز النصّ على Windows - تشوّه النصّ عند التعامل مع Linux

· آخر تحديث: · · Windows, mojibake, UTF-8, CP932, Linux, PowerShell, Unicode

سجل التعديلات (4 تحديثات، آخر تحديث 3 Sep، 2026)

سجل بالتغييرات التي أُجريت على هذا المقال. وحيثما حُفظت نسخة سابقة، تبقى متاحة للقراءة عبر رابط دائم يحمل معرّف DOI.

أُضيفت روابط الاستشارة الموجودة في الأصل الياباني (consultation_services). ولم يتغيّر نصّ المقالة نفسه. قراءة النسخة السابقة لهذا التحديث (DOI: 10.5281/zenodo.22240874)
أُعيدَت الترجمة العربية كترجمة كاملة عن النص الياباني الأصلي، وأُضيفَت خريطة المعرفة.
أعيدت الترجمة كترجمة كاملة عن النص الياباني الأصلي. كانت النسخة العربية السابقة مختصراً يسقط أبواباً وجداول ورسوم Mermaid وتعليقات الأشكال وFAQ. أُعيدت هذه العناصر وفق الأصل الياباني، والادّعاءات التقنية مطابقة للنسخة اليابانية.
تم إصلاح خلل في العرض كان يجعل الأسطر التي تحتوي على الشرطة العموديّة تُعرض كجدول، فتصبح روابط المراجع غير قابلة للنقر. لم يتغيّر نصّ المقالة.
النشر الأول
الاستشهاد بهذا المقال(DOI: 10.5281/zenodo.21621441)

هذا المقال محفوظ على Zenodo. يرد أدناه معرّف DOI الذي يشير دائمًا إلى أحدث نسخة، ومعرّف DOI المثبَّت على النسخة التي تقرؤها.

小村 豪 (2026). مدخل إلى ترميز النصّ على Windows - تشوّه النصّ عند التعامل مع Linux. شركة كومورا سوفت ذ.م.م.. https://doi.org/10.5281/zenodo.21621441 https://comcomponent.com/ar/blog/2026/03/21/000-windows-text-encoding-mojibake-linux/

DOI (أحدث نسخة)
10.5281/zenodo.21621441
DOI (هذه النسخة)
10.5281/zenodo.22279874

تشوّه النصّ على Windows لا يحدث لأن اليابانيّة صعبة. في معظم الحالات السبب هو قراءة البايتات نفسها بترميز مختلف، أو حفظ نتيجة القراءة الخاطئة بترميز آخر.

يظهر ذلك بقوّة عند عبور Windows وLinux. يبقى في جانب Windows سياقات متعدّدة: CP932 وUTF-8 وUTF-16 وcode page لوحدة التحكّم وفروق إصدارات PowerShell، بينما يجري جانب Linux في كثير من الأحيان بفرضيّة UTF-8، فينكشف دفعة واحدة انحراف الفرضيّات الذي كان خفيّاً في الاستخدام اليومي.

شكل انحراف الفرضيّات بين Windows وLinuxمخطّط يبيّن أن جانب Windows تبقى فيه سياقات متعدّدة مثل CP932 وUTF-16 وcode page لوحدة التحكّم وفروق الإصدارات، وأن الجمع مع جانب Linux الذي يجري غالباً بفرضيّة UTF-8 يكشف انحراف الفرضيّات.جانب WindowsCP932 / UTF-16 / code page / فروق الإصدارجانب Linuxفرضيّة UTF-8 قويّةينكشف انحراف الفرضيّات

الشكل 1: عند التقاء السياقات المتعدّدة المتبقّية في Windows مع فرضيّة UTF-8 في Linux، ينكشف الانحراف دفعة واحدة.

المسألة أقرب إلى محاذاة الفرضيّة التي تُعالَج بها البايتات منها إلى صعوبة معالجة اليابانيّة. ترتّب هذه المقالة ترميز Windows من زاوية «لماذا يحدث تشوّه النصّ»، وتلخّص عمليّاً النقاط التي تزداد فيها الحوادث عند الجمع مع Linux.

الجمهور من يمرّر CSV أو سجلاّت أو ملفّات إعداد صُنعت على Windows إلى جانب Linux، أو العكس، ويريد تشخيص التشوّه واستعادته بنفسه. لا نفترض معرفة بلغة أو إطار معيّن. أمثلة الأوامر تستخدم iconv وPowerShell.

1. ما ينبغي تثبيته أوّلاً

إن اقتصرنا على النقاط المهمّة، فهذه ستّة.

  • تشوّه النصّ ليس مشكلة «حروف» بل مشكلة «كيف فُسِّرت البايتات».
  • يتعايش على Windows مسار Unicode مع مسار code page القديم، فتختلف الفرضيّة حتى داخل الجهاز الواحد حسب السياق.
  • فرضيّة UTF-8 قويّة في جانب Linux، لذا يسهل الحادث إذا اختلط CP932 أو UTF-16 من جانب Windows.
  • مرحلة انهيار العرض وحدها ومرحلة حفظ المحتوى التالف ينبغي فصلهما.
  • اجعل UTF-8 الخيار الأوّل للنصّ الجديد، وأبقِ ملفّات legacy القائمة كما هي حتى مهمّة ترحيل صريحة.
  • encoding الملفّ، وencoding المحرّر، وcode page لوحدة التحكّم، وتمثيل السلسلة داخل التطبيق، أمور مختلفة. خلطها يُضيّع التحقيق.

قول «تشوّه النصّ على Windows» لا يحدّد السبب. على الأقل افصل أيّ من التالي انحرف.

  • ترميز الملفّ نفسه
  • ترميز الحفظ
  • تفسير المحرّر
  • code page للإدخال/الإخراج في وحدة التحكّم
  • تمثيل السلسلة داخل التطبيق
  • locale في جانب Linux والـ encoding المتوقّع
الطبقات التي تُفصَل عند تشخيص تشوّه النصّمخطّط يبيّن أن قول «تشوّه النصّ على Windows» لا يحدّد السبب، وأنّه يلزم فصل أيّ من ترميز الملفّ نفسه وترميز الحفظ وتفسير المحرّر وcode page لوحدة التحكّم وتمثيل السلسلة داخل التطبيق وlocale في Linux قد انحرف.تشوّه النصّ على Windowsأين الانحرافترميز الملفّ نفسهترميز الحفظتفسير المحرّرcode page لوحدة التحكّمتمثيل السلسلة داخل التطبيقlocale في Linux

الشكل 2: «تشوّه النصّ» وحده لا يحدّد السبب؛ انظر أيّاً من هذه الطبقات الستّ انحرف.

1.1 مصطلحات تظهر لاحقاً

نلخّص باختصار الاختصارات التي تظهر في المتن دون شرح.

المصطلح التوسعة معناه في هذه المقالة
BOM Byte Order Mark علامة بعدّة بايتات في رأس الملفّ تخبر القارئ بأيّ Unicode encoding هو، وفي UTF-16 تبيّن أيضاً ترتيب البايتات. في UTF-8 يجوز وضعها أو تركها
code page - آلية يحمل بها Windows برقم «بأيّ ترميز legacy يُفسَّر». CP932 على Windows الياباني أحد تلك الأرقام
ANSI - في Windows تعبير يعني «active code page في تلك اللحظة». الماهيّة تتغيّر حسب البيئة، وفي البيئة اليابانيّة تكون CP932
locale - إعداد يجمع اللغة والمنطقة وترميز الحروف الافتراضي. في Linux يُحدَّد بـ LANG أو LC_ALL، ويتضمّن encoding مثل ja_JP.UTF-8
WSL Windows Subsystem for Linux آلية لتشغيل Linux على Windows. فرضيّات جانبي Windows وLinux تتعايش في جهاز واحد، لذا تكثر حوادث هذه المقالة
ETL Extract / Transform / Load معالجة تستخرج البيانات وتحوّلها وتعيد كتابتها. نقطة يتغيّر فيها encoding لأن الملفّ يُعاد فتحه وحفظه في الطريق

في المخطّط، يشير الخطّ المتّصل إلى علاقة قائمة دائماً، ويشير الخطّ المتقطّع إلى علاقة مشروطة (شروط قيامها مذكورة في شرح كلّ علاقة في الصفحة التفصيليّة). القائمة الكاملة للعلاقات (المجموع 17، مع الأدلّة ودرجة اليقين) وتعريفات المفاهيم الرئيسة مجمّعة في صفحة تفاصيل خريطة المعرفة (باليابانية). البيانات: JSON-LD / Turtle

2. ماهيّة تشوّه النصّ

ماهيّة تشوّه النصّ بسيطة جدّاً.

  1. تُرمَّز السلسلة (encode) بترميز ما إلى بايتات
  2. تُفَكّ تلك البايتات (decode) بترميز ما إلى سلسلة
  3. إن لم تتطابق فرضيّة encode مع decode، تُقرأ كسلسلة أخرى
تطابق فرضيّة encode وdecodeمخطّط يبيّن أن البايتات الناتجة عن encode السلسلة إذا أُعيدت decode إلى سلسلة، تعود إلى الأصل عند تطابق الفرضيّتين، وتُقرأ كسلسلة أخرى عند الانحراف.متطابقتانمنحرفتانencode السلسلة إلى بايتاتdecode البايتات إلى سلسلةهل الفرضيّتان متطابقتانتعود السلسلة الأصليّةتُقرأ كسلسلة أخرى

الشكل 3: ماهيّة تشوّه النصّ هي عدم تطابق فرضيّة encode وdecode.

مثلاً، حفظ あ بـ UTF-8 يعطي البايتات التالية.

E3 81 82

قراءتها كـ UTF-8 تعطي あ، أمّا قراءتها في سياق CP932 فتظهر كسلسلة أخرى مثل 縺�. هذا هو تشوّه النصّ.

المهم أن ما يحدث هنا ليس «اليابانيّة انكسرت»، بل انحرفت تفسيرات البايتات نفسها.

انظر الاتجاه المعاكس أيضاً. حفظ あ بـ CP932 يعطي البايتات التالية.

82 A0

محاولة قراءتها كـ UTF-8 تفشل لأن 0x82 و0xA0 لا يصلحان كبايت بداية لـ UTF-8، فيصيران حرفَي استبدال ويظهران مثل ��. من جهة UTF-8 لا تقوم كحرف أصلاً.

مثال أطول يُظهر السمة أوضح. حفظ 日本語 بـ CP932 يعطي البايتات التالية.

93 FA 96 7B 8C EA

قراءتها كـ UTF-8 تصير مثل ���{��. ما ينبغي النظر إليه هنا هو أن البايت الرابع 0x7B وحده يمرّ كـ { في ASCII. البايت الثاني في CP932 قد يقع في نطاق ASCII، فتختلط في النتيجة رموز مثل { أو \.

أي أن الأعراض تختلف حسب الاتجاه.

البايتات الفعليّة فرضيّة القارئ المظهر
UTF-8 CP932 تتوالى كانجي أو كاتاكانا تبدو معقولة مثل 縺
CP932 UTF-8 تمتلئ بأحرف الاستبدال �، وتختلط أحياناً رموز ASCII مثل {

يمكن تخمين السبب بسرعة: «إن توالت كانجي غير مقروءة فأنت تقرأ UTF-8 كـ CP932» و«إن امتلأت بأحرف الاستبدال فأنت تقرأ CP932 كـ UTF-8». تذكّر هذا اللاتماثل يسرّع التشخيص.

2.1 إن انهار العرض فقط، فقد يبقى الاسترداد ممكناً

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

الخطر هو التسلسل التالي.

  1. قراءة ملفّ UTF-8 خطأً كـ CP932
  2. يظهر على الشاشة مثل 縺�
  3. حفظ «السلسلة الظاهرة» كما هي
  4. تضيع بايتات UTF-8 الأصليّة

عند دخول هذه المرحلة لا يبقى الأمر انهيار عرض، بل تلفاً للبيانات.

مسار تحوّل انهيار العرض إلى تلف بياناتمخطّط يبيّن أن قراءة ملفّ UTF-8 خطأً كـ CP932 حتى يظهر مشوّهاً على الشاشة، ثم حفظ السلسلة الظاهرة كما هي حتى تضيع بايتات UTF-8 الأصليّة، يحوّل المسألة من انهيار عرض إلى تلف بيانات.قراءة ملفّ UTF-8 خطأً كـ CP932يظهر مشوّهاً على الشاشةحفظ السلسلة الظاهرة كما هيتضيع بايتات UTF-8 الأصليّةحتى هنا يكفي إعادة الفتحمن هنا تلف بيانات

الشكل 4: القراءة الخاطئة وحدها قابلة للاسترداد، أمّا حفظ المحتوى المقروء خطأ فيحوّلها إلى تلف بيانات.

2.2 أخطر منه إسقاط «حرف لا يُمثَّل» إلى code page ضيّق

حادث نموذجي آخر هو إسقاط سلسلة Unicode إلى code page قديم مثل CP932.

إذا تضمّنت السلسلة حرفاً غير موجود في code page الطرف:

  • يُستبدَل بـ ?
  • يدخل حرف الاستبدال �
  • يُحوَّل إلى حرف قريب مختلف
  • تفشل التحويلة

هذا الحادث لا يُرى بـ مقروء / غير مقروء فقط، بل بـ هل تعود السلسلة بعد التحويل ذهاباً وإياباً. الحرف الضائع مرّة لا يُستعاد حتى بعد معرفة الـ encoding الصحيح.

حادث الإسقاط إلى code page ضيّقمخطّط يبيّن أن تحويل سلسلة Unicode إلى code page ضيّق مثل CP932 يستبدل الحروف غير الموجودة أو يفشل التحويل، فلا تعود بعد الذهاب والإياب، وأن الحرف الضائع لا يُستعاد حتى بمعرفة الـ encoding الصحيح.سلسلة Unicodeتحويل إلى code page ضيّق مثل CP932الحرف غير الموجود لدى الطرفيتحوّل إلى ? أو حرف استبدالحرف مختلف أو فشل التحويللا يعود بعد الذهاب والإيابالحرف الضائع لا يُستعاد

الشكل 5: حادث الإسقاط إلى code page ضيّق يُرى بالذهاب والإياب لا بمقروء / غير مقروء.

3. لماذا يسهل التعقيد على Windows

تعقيد Windows ليس لأنّه قديم فحسب. السبب أن عالم Unicode وعالم code page القديم ما زالا يتعايشان.

3.1 مساران في Windows API: Unicode وcode page

في Windows API مساران كبيران.

  • عائلة W: wide character. تعامل Unicode كـ UTF-16
  • عائلة A: مسار code page يُدعى ANSI

أي أن داخل Windows يوجد منذ البداية «طريق Unicode» و«طريق active code page في تلك اللحظة». لذلك تتغيّر الفرضيّة حتى على Windows نفسه حسب أيّ API أو أيّ أداة مرّت.

مسارا Windows APIمخطّط يبيّن أن Windows API يتعايش فيه منذ البداية مسار W الذي يعامل Unicode كـ UTF-16 ومسار A الذي يعامل active code page في تلك اللحظة، فتتغيّر الفرضيّة حسب المسار.Windows APIعائلة W (wide character)عائلة A (تُدعى ANSI)تعامل Unicode كـ UTF-16تعامل بـ active code pageالفرضيّة تتغيّر حسب المسار

الشكل 6: داخل Windows يوجد منذ البداية طريق Unicode وطريق code page.

3.2 «اليابانيّة على Windows» ليست واحدة

في اليابانيّة على Windows تختلط عمليّاً أربعة أمور.

  • CP932: شائع في النصّ القديم على Windows الياباني
  • UTF-8: يزداد في الأصول النصّيّة الجديدة والويب والأنظمة متعدّدة المنصّات
  • UTF-16LE: ما زال يظهر بانتظام في سياق أدوات Windows وواجهات API
  • code page لوحدة التحكّم: طبقة أخرى تؤثّر في إدخال/إخراج cmd.exe وبعض أدوات وحدة التحكّم

المهم هنا أن chcp 65001 لا يجعل الملفّ أيضاً UTF-8. تغيير code page لوحدة التحكّم ومسألة ماهيّة بايتات الملفّ القائم أمران منفصلان.

chcp 65001 والملفّ القائم مسألتان منفصلتانمخطّط يبيّن أن chcp 65001 يغيّر code page لوحدة التحكّم فقط، وأن بايتات الملفّ القائم لا تتغيّر، فإعداد وحدة التحكّم ومحتوى الملفّ مسألتان منفصلتان.تنفيذ chcp 65001يتغيّر code page لوحدة التحكّمبايتات الملفّ القائملا تتغيّروحدة التحكّم والملفّ مسألتان منفصلتان

الشكل 7: chcp 65001 يغيّر تفسير وحدة التحكّم فقط، وتبقى بايتات الملفّ كما هي.

يُدعى النصّ القديم على Windows الياباني كثيراً «Shift_JIS» على عجل، لكن في الممارسة الوعي باسم CP932 يقلّل انحراف الحوار. يكفي أن يُصرَّح بأن الحديث عن «ترميز ياباني قديم آتٍ من Windows».

3.3 اسم الملفّ ومحتوى الملفّ مسألتان منفصلتان

إذا ظهرت أسماء الملفّات اليابانيّة على Windows بشكل طبيعي، يسهل الظنّ «إذن المحتوى سليم أيضاً». هنا الخطر.

  • طبقة التعامل مع المسار / اسم الملفّ
  • طبقة قراءة محتوى الملفّ
  • طبقة العرض في وحدة التحكّم

هذه الثلاث مختلفة.

مثلاً، قد يُعالَج المسار الياباني بلا مشكلة بينما محتوى الملفّ محفوظ بـ CP932 فيُكسَر عندما يقرأه جانب Linux كـ UTF-8. والعكس: حتى إن كان المحتوى UTF-8، ينهار العرض وحده إن لم يطابق code page لوحدة التحكّم.

علاقة الطبقات كالتالي.

الكاتبتطبيق / محرّر / سكربتبايتات الملفّهذه وحدها هي الحقيقةقارئ A: المحرّركشف تلقائي أو encoding محدّدقارئ B: وحدة التحكّمcode page للإدخال/الإخراجقارئ C: داخل التطبيقencoding الافتراضي للمكتبةقارئ D: جانب Linuxفرضيّة UTF-8 وفق localeينهار العرض فقطوإعادة الحفظ تحوّله إلى تلفينهار العرض فقطالملفّ سليمتفسد نتيجة المعالجةوتنتقل إلى المصبّdecode error أو حرف استبدال

الشكل 8: الحقيقة بايتات الملفّ وحدها، وقرّاء المحرّر ووحدة التحكّم والتطبيق وجانب Linux مستقلّون عن بعضهم.

نقطتان للنظر. الأولى فصل هل التالف هو البايتات في الوسط أم القارئ على اليمين. والثانية أن الأربعة على اليمين مستقلّة، فـ تأكيد واحد لا يضمن الثلاثة الأخرى. «ظهر صحيحاً في وحدة التحكّم إذن المحرّر سليم» لا يقوم بسبب هذا الشكل.

3.4 القيم الافتراضيّة في PowerShell والأدوات المحيطة غير موحّدة

ما يزيد الحوادث بهدوء على Windows هو أن البايتات الناتجة تختلف حسب المسار حتى مع نيّة «كتابة نصّ» نفسها.

ما يستحق الانتباه خصوصاً:

  • Windows PowerShell 5.1 encoding الافتراضي فيه غير متّسق
  • بعض cmdlet وإعادة التوجيه تنتج UTF-16LE
  • مسارات أخرى تستخدم active ANSI code page
  • من PowerShell 7 فما فوق الافتراضي UTF-8 بدون BOM

أي أن «نصّ أخرجه PowerShell» لا يحدّد encoding. يلزم النظر حتى أيّ إصدار، وأيّ cmdlet، وأيّ مسار كتابة.

أي مسار ينتج أيّ بايتات مرتَّب في about_Character_Encoding على Microsoft Learn. استخراج الشائع يعطي الجدول التالي.

مسار الكتابة افتراضي Windows PowerShell 5.1 افتراضي PowerShell 7
Out-File، >، >> UTF-16LE (مع BOM) UTF-8 بدون BOM
Set-Content، Add-Content (ملفّ جديد أو فارغ) ANSI = active code page. في البيئة اليابانيّة CP932 UTF-8 بدون BOM
Export-Csv ASCII. يسقط غير ASCII UTF-8 بدون BOM
Export-Clixml، New-ModuleManifest UTF-16LE UTF-8 بدون BOM
New-Item -Type File -Value UTF-8 بدون BOM UTF-8 بدون BOM
Start-Transcript UTF-8 مع BOM UTF-8 بدون BOM

جانب القراءة أيضاً فيه فرق. عند قراءة ملفّ بلا BOM، Get-Content في 5.1 يعدّه ANSI، بينما Import-Csv وSelect-String يعدّانه UTF-8. الفرضيّة منقسمة داخل الجلسة نفسها.

ما يصيب الممارسة أكثر هو أن نفس «كتابة نصّ» تجعل Out-File UTF-16LE وSet-Content CP932. «النصّ الذي يشبه الثنائي لكثرة بايتات NUL» المذكور في 4.3 يأتي في الغالب من افتراضي > أو Out-File.

لاتماثل جانب القراءة في Windows PowerShell 5.1مخطّط يبيّن أن قراءة ملفّ بلا BOM في Windows PowerShell 5.1 تجعل Get-Content يعدّه ANSI بينما Import-Csv وSelect-String يعدّانه UTF-8، فتنقسم الفرضيّة داخل الجلسة نفسها.ملفّ بلا BOMالقراءة بـ Get-Contentالقراءة بـ Import-Csv أو Select-Stringيُعدّ ANSIيُعدّ UTF-8الفرضيّة تنقسم داخل الجلسة نفسها

الشكل 9: في 5.1 حتى الملفّ نفسه بلا BOM يُفترَض له encoding مختلف حسب cmdlet القراءة.

كذلك في 5.1 حتى تحديد -Encoding UTF8 يصير مع BOM. لكتابة UTF-8 بدون BOM في 5.1 تُكتَب من جانب .NET.

# Windows PowerShell 5.1 で UTF-8 no BOM を書く
$text = "日本語を含む本文"
[System.IO.File]::WriteAllText(
    "C:\work\output.txt", $text,
    (New-Object -TypeName System.Text.UTF8Encoding -ArgumentList $false))

جعل وسيط UTF8Encoding مساوياً $false هو تحديد عدم إرفاق BOM. في PowerShell 7 النتيجة نفسها بـ -Encoding utf8NoBOM.

4. حوادث نموذجيّة عند الجمع مع Linux

ما كان يدور تقريباً على Windows وحده ينكسر فجأة عند إدخال Linux، وهذا شائع. السبب بسيط: فرضيّة UTF-8 قويّة في جانب Linux.

4.1 نصّ حُفظ بـ CP932 على Windows يقرأه Linux كـ UTF-8

الحادث الأكثر شيوعاً.

  • تطبيق قديم أو تشغيل قديم على Windows يكتب CSV / TXT / log بـ CP932
  • سكربت أو أداة في جانب Linux تقرأ بفرضيّة UTF-8 وفق locale
  • النتيجة decode error أو � أو سلسلة بلا معنى

ليس العيب في أداة Linux حينها، بل السبب الجذري أن البايتات المستلمة بلا عقد encoding.

حادث قراءة نصّ CP932 كـ UTF-8 في Linuxمخطّط يبيّن أن تطبيقاً قديماً أو تشغيلاً قديماً على Windows يكتب CSV أو سجلاّت بـ CP932، ثم يقرأ سكربت أو أداة في Linux بفرضيّة UTF-8 وفق locale بلا عقد encoding، فينتج decode error أو حرف استبدال.تطبيق قديم يكتب CSV / log بـ CP932تمرير بلا عقد encodingجانب Linux يقرأ بفرضيّة UTF-8 وفق localedecode error / حرف استبدالالسبب الجذري غياب العقد

الشكل 10: العيب ليس في أداة Linux، بل في غياب عقد encoding على البايتات.

4.2 UTF-8 بدون BOM صُنع في Linux / VS Code يعدّه جانب Windows ANSI

هناك حادث في الاتجاه المعاكس أيضاً.

  • صناعة سكربت / إعداد / نصّ UTF-8 بدون BOM في Linux أو VS Code
  • Windows PowerShell 5.1 أو أداة قديمة تعدّ الملفّ بلا BOM code page من جانب ANSI
  • تتكسّر فقط الأسطر التي تتضمّن يابانيّة أو non-ASCII

يُلام UTF-8 غالباً هنا، لكن السبب الفعلي هو اختلاط قارئ لا يخمن UTF-8 بدون BOM تخميناً صحيحاً.

حادث عدّ UTF-8 بدون BOM كـ ANSIمخطّط يبيّن أن ملفّ UTF-8 بدون BOM صُنع في Linux أو VS Code إذا قرأه Windows PowerShell 5.1 أو أداة قديمة كـ code page من جانب ANSI، تتكسّر فقط الأسطر التي تتضمّن يابانيّة أو non-ASCII.صناعة UTF-8 بدون BOM في Linux / VS Codeقراءة 5.1 أو أداة قديمةعدّ الملفّ بلا BOM من جانب ANSIتتكسّر فقط أسطر non-ASCIIالسبب قارئ لا يخمن

الشكل 11: في الحادث المعاكس السبب قارئ لا يستطيع تخمين UTF-8 بدون BOM.

4.3 جانب Windows يكتب UTF-16LE، وفي Linux «لا يبدو نصّاً»

هذا أيضاً كثير.

  • بعض مخرجات Windows PowerShell 5.1 أو أدوات قديمة تكتب UTF-16LE
  • أدوات النصّ في Linux تفترض دفق بايت واحد بـ UTF-8
  • النتيجة «نصّ يشبه الثنائي» اختلطت فيه بايتات NUL بكثرة

UTF-16LE نفسه ليس سيّئاً. لكن فرضيّة تمريره كما هو إلى أدوات معالجة النصّ في Linux لا تتوافق في كثير من المواضع.

حادث ظهور UTF-16LE كثنائي في جانب Linuxمخطّط يبيّن أن UTF-16LE الذي تكتبه بعض مخرجات Windows PowerShell 5.1 أو أدوات قديمة، إذا أُمرر إلى أداة نصّ في Linux تفترض دفق بايت واحد بـ UTF-8، يبدو كنصّ يشبه الثنائي لكثرة بايتات NUL.بعض مخرجات 5.1 أو أدوات قديمةتكتب UTF-16LEأداة النصّ في Linux تفترض دفق بايت واحدتختلط بايتات NUL فيبدو كثنائي

الشكل 12: UTF-16LE نفسه ليس سيّئاً، لكنّه لا يتوافق مع فرضيّة معالجة النصّ في Linux.

4.4 وجود BOM أو غيابه يولّد احتكاكاً أيضاً

BOM ليس الـ encoding نفسه، لكنّه يؤثّر بقوّة في الممارسة.

  • بعض أدوات Windows تستفيد من وجود BOM
  • بعض أدوات Linux تعامل BOM كبايتات زائدة في الرأس
  • النتيجة انكسار العمود الأوّل أو رأس السطر الأوّل فقط، أو فضلات غير مرئيّة، أو انحراف نتيجة المقارنة

في UTF-8 خصوصاً، البايتات مختلفة حتى مع نفس UTF-8 حسب وجود BOM أو غيابه. «جعلناه UTF-8» وحده لا يحدّد بعد نصف قاعدة التشغيل.

الاحتكاك الناجم عن وجود BOM أو غيابهمخطّط يبيّن أن البايتات تختلف حتى مع نفس UTF-8 حسب وجود BOM أو غيابه، وأن بعض أدوات Windows تستفيد من BOM بينما بعض أدوات Linux تعاملها كبايتات زائدة في الرأس، فينكسر الرأس فقط.حتى نفس UTF-8 بايتات مختلفة مع BOM / بدونهبعض أدوات Windowsبعض أدوات Linuxوجود BOM يفيدتعامل كبايتات زائدة في الرأسينكسر الرأس فقط أو تلحق فضلات غير مرئيّة

الشكل 13: «جعلناه UTF-8» لا يكفي؛ القاعدة تكتمل بقرار وجود BOM أو غيابه.

4.5 الثقة بمظهر وحدة التحكّم تُضلّل

عند عبور Windows وLinux، وحدة التحكّم أيضاً خطرة.

  • لوحدة التحكّم في Windows code page للإدخال / الإخراج
  • طرف Linux يعمل غالباً بفرضيّة locale UTF-8
  • المرور عبر WSL أو SSH أو حاوية أو CI يزيد مسارات العرض

في هذه الحالة يسهل الخطأ في الحكم بأن «ظهر في وحدة التحكّم إذن الملفّ سليم» أو «انهار في وحدة التحكّم إذن الملفّ تالف». هل التالف هو الظاهر أم البايتات المحفوظة، يؤكَّد كلّ على حدة بأمان أكبر.

4.6 جدول الحوادث النموذجيّة

المشهد البايتات الفعليّة فرضيّة القارئ العَرَض النموذجي
CSV حفظه تطبيق قديم على Windows CP932 جانب Linux UTF-8 �، decode error، يابانيّة بلا معنى
ملفّ صُنع في Linux / VS Code UTF-8 بدون BOM Windows PowerShell 5.1 يعامله كـ ANSI تتكسّر الأسطر اليابانيّة فقط
بعض مخرجات Windows PowerShell 5.1 UTF-16LE أو ANSI جانب Linux يتوقّع نصّ UTF-8 اختلاط بايتات NUL، سلوك يشبه الثنائي
ملفّ UTF-8 مع BOM UTF-8 + BOM أدوات Unix تفترض UTF-8 صافياً ينكسر العمود الأوّل فقط، تلحق حروف زائدة
الثقة بعرض وحدة التحكّم وحدها فرضيّتان مختلفتان للملفّ ووحدة التحكّم المحقّق يحكم بالعرض وحده يخطئ التشخيص

5. تحقيق تشوّه النصّ بأربعة أسئلة

إذا ضللت في التحقيق، أسرع طريق هو العودة إلى الأسئلة الأربعة التالية.

5.1 ما البايتات الأصليّة

أوّل ما يُنظَر إليه هو «ما بايتات هذا الملفّ الآن». الوعي بالبايتات لا بالمظهر.

  • UTF-8؟
  • UTF-8 مع BOM؟
  • CP932؟
  • UTF-16LE؟
  • هل أُعيد الحفظ في الطريق فصار شيئاً آخر؟

5.2 من كتب أوّلاً، وبأيّ فرضيّة

ثم حدّد «الكاتب الأوّل».

  • تطبيق قديم على Windows؟
  • PowerShell 5.1 أم 7؟
  • سكربت Linux؟
  • VS Code؟
  • تصدير من Excel؟
  • وسيط / دفعة / CI ما؟

ما دام هذا غامضاً، يبقى تخمين encoding حظّاً.

5.3 من يقرأ الآن، وبأيّ فرضيّة

يلزم أيضاً فرضيّة القارئ لا الكاتب وحده.

  • هل المحرّر يكشف تلقائيّاً؟
  • هل PowerShell ينظر إلى BOM؟
  • هل جانب Linux يعامل UTF-8 وفق locale؟
  • هل المكتبة تستخدم encoding افتراضيّاً؟
  • هل حُدِّد صراحة Encoding.UTF8 أو cp932؟

تشوّه النصّ يحدث هنا تقريباً.

5.4 هل حُفظ المحتوى المقروء خطأ بالفعل

أخيراً تأكّد هل الضرر توقّف عند العرض.

  • هل البايتات ما زالت كما هي؟
  • هل حفظ أحد المحتوى الظاهر تالفاً؟
  • هل دخل ? أو � في الفرق؟
  • هل أُعيدت كتابة النصّ كاملاً بترميز آخر؟

إذا امتلأت هذه الأربعة يظهر السبب في الغالب.

أربعة أسئلة لتحقيق تشوّه النصّمخطّط يبيّن أن ملء أربعة أسئلة بالترتيب، ما البايتات الأصليّة، ومن كتب أوّلاً وبأيّ فرضيّة، ومن يقرأ الآن وبأيّ فرضيّة، وهل حُفظ المحتوى المقروء خطأ، يُظهر في الغالب سبب تشوّه النصّ.س1: ما البايتات الأصليّةس2: من كتب أوّلاً وبأيّ فرضيّةس3: من يقرأ الآن وبأيّ فرضيّةس4: هل حُفظ المحتوى المقروء خطأيظهر السبب

الشكل 14: إذا ضللت في التحقيق، أسرع طريق هو العودة إلى هذه الأربعة وملؤها بالترتيب.

6. كيف تُصلَح الملفّات المكسورة

إذا ظهر السبب فالخطوة التالية الاستعادة. أوّل قرار هنا هو هل ما زالت البايتات الأصليّة موجودة.

  • البايتات الأصليّة موجودة: أعد القراءة بالـ encoding الصحيح واكتب بالـ encoding المطلوب. هذا إجراء هذا الفصل
  • نتيجة القراءة الخاطئة حُفظت بالفعل: لا يبقى إلا الرجوع من نسخة احتياطيّة أو تاريخ Git. الحروف التي صارت حرف استبدال � أو ? لا تُستعاد حتى بمعرفة الـ encoding الصحيح

لذلك أوّل ما ينبغي فعله هو أخذ نسخة من هدف العمل. نفّذ التحويل على النسخة ولا تلمس الملفّ الأصلي.

أوّل تفرع في الاستعادةمخطّط يبيّن أن الاستعادة تبدأ بالتأكّد من بقاء البايتات الأصليّة، فإن بقيت أُعيدت القراءة والكتابة بالـ encoding الصحيح، وإن حُفظت نتيجة القراءة الخاطئة فلا يبقى إلا الرجوع من نسخة احتياطيّة أو تاريخ Git، وأن العمل يتمّ على نسخة.بقيتضاعت بالحفظخذ نسخة أوّلاًهل بقيت البايتات الأصليّةأعد القراءة والكتابة بالـ encoding الصحيحارجع من نسخة احتياطيّة أو تاريخ Gitالحروف التي صارت حرف استبدال لا تُستعاد

الشكل 15: الاستعادة بعد أخذ نسخة، ثم ينقسم الطريق حسب بقاء البايتات الأصليّة.

6.1 إن كنت في جانب Linux فاستخدم iconv

لجعل ملفّ CP932 UTF-8، iconv هو الأوضح.

# CP932 -> UTF-8
iconv -f CP932 -t UTF-8 input.csv > output.csv

إن أخطأت encoding المصدر يتوقّف في الوسط كالتالي.

iconv: illegal input sequence at position 0

التوقّف نفسه معلومة أنّه «ليس ذلك الـ encoding»، لذا أسرع تجربة المرشّحين بتغييرهم. إن لم يتوقّف مهما مرّرت، فقد يكون الملفّ ASCII فقط.

لإسقاط UTF-16LE إلى UTF-8 استخدم -f UTF-16LE. لكن تحويل ملفّ مع BOM مع التصريح بـ -f UTF-16LE قد يُبقي BOM كحرف U+FEFF في المخرج. إن أردت ترك التعامل مع BOM لـ iconv استخدم -f UTF-16، وتأكّد دائماً من الحرف الأوّل بعد التحويل.

6.2 إن كنت في جانب Windows فاستخدم PowerShell

من PowerShell 6.2 فما فوق يمكن تمرير رقم code page مباشرة إلى -Encoding. CP932 هو 932.

# PowerShell 6.2 以降。CP932 -> UTF-8 no BOM
Get-Content -Path .\input.csv -Encoding 932 |
    Set-Content -Path .\output.csv -Encoding utf8NoBOM

والعكس، لتمرير ملفّ UTF-8 صُنع في Linux إلى طرف لا يقرأ إلا CP932:

Get-Content -Path .\input.csv -Encoding utf8 |
    Set-Content -Path .\output.csv -Encoding 932

لكن لهذه الكتابة أثرين جانبيّين.

  1. Get-Content يقسم إلى أسطر، وSet-Content يعيد إرفاق سطر جديد بعد كل سطر. أي أن رمز السطر الجديد يُوحَّد
  2. حتى إن لم يكن في نهاية الملفّ الأصلي سطر جديد، يُرفَق في المخرج

للحفاظ على البايتات بما فيها السطر الجديد، عالج الكلّ دون تقسيم إلى أسطر.

# 改行をそのまま保ったまま CP932 -> UTF-8 no BOM
$text = [System.IO.File]::ReadAllText(
    "C:\work\input.csv", [System.Text.Encoding]::GetEncoding(932))
[System.IO.File]::WriteAllText(
    "C:\work\output.csv", $text,
    (New-Object -TypeName System.Text.UTF8Encoding -ArgumentList $false))

GetEncoding(932) يُستخدم كما هو في Windows PowerShell 5.1. إن رمى استثناء في PowerShell 7 في تلك البيئة، نفّذ التالي مرّة ثم استخدمه.

[System.Text.Encoding]::RegisterProvider(
    [System.Text.CodePagesEncodingProvider]::Instance)

إرفاق BOM أو لا يُقرَّر حسب الطرف الآخر كما في 7.1. في المثال أعلاه جعل وسيط UTF8Encoding مساوياً $true يرفق BOM.

6.3 ما يجب النظر إليه حتماً بعد التحويل

التحويل لا ينتهي عند «لم يظهر خطأ». انظر على الأقل التالي.

  • هل تُقرأ سطران أو ثلاثة يابانيّة نموذجيّة قراءة صحيحة
  • هل ازداد ? أو �. إن ازدادا فذلك الحرف ضاع
  • هل تغيّر عدد الأسطر
  • هل BOM ورمز السطر الجديد يطابقان فرضيّة الطرف المستلم
  • هل تغيّر حجم الملفّ تغيّراً متطرّفاً. التحويل من CP932 إلى UTF-8 يزيد الجزء الياباني من 2 بايت إلى 3، فزيادة طفيفة طبيعيّة

الثاني مهم خصوصاً. إسقاط UTF-8 يتضمّن حروفاً غير موجودة في CP932 إلى CP932 يُسقط معلومات حتماً. كما في 2.2، تأكّد حتى من العودة بعد الذهاب والإياب.

ما يجب النظر إليه حتماً بعد التحويلمخطّط يبيّن أن التحويل لا ينتهي عند غياب الخطأ، بل يُؤكَّد أن أسطراً يابانيّة نموذجيّة تُقرأ، وأن ? أو حرف الاستبدال لم يزددا، وأن عدد الأسطر وBOM والسطر الجديد وحجم الملفّ كما هو متوقّع، وأن ازدياد حرف الاستبدال يعني ضياع ذلك الحرف.ينتهي التحويل بلا خطأاقرأ سطرين أو ثلاثة يابانيّة نموذجيّةهل ازداد ? أو حرف الاستبدالأكّد عدد الأسطر وBOM والسطر الجديد والحجمإن ازدادا فذلك الحرف ضاع

الشكل 16: التحويل لا ينتهي عند «لم يظهر خطأ»؛ تأكيد المحتوى جزء من المجموعة.

6.4 اقطع التحويل بالجملة كمهمّة ترحيل

أخيراً حديث التشغيل. إصلاح ملفّ واحد مكسور وتقريب المستودع كلّه من CP932 إلى UTF-8 عملان مختلفان. الثاني، كما في 7.2 من الفصل التالي، لا يُفعَل في أثناء إصلاح وظيفة يومي؛ خطّطه كمهمّة ترحيل مستقلّة.

7. قواعد تشغيل تقلّل الحوادث

من هنا حديث أقرب إلى الممارسة. في القضايا التي تعبر Windows وLinux، تقرير القواعد التالية أوّلاً يقلّل الحوادث كثيراً.

7.1 اجعل UTF-8 الخيار الأوّل للملفّات الجديدة

للملفّات النصّيّة الجديدة، جعل UTF-8 الخيار الأوّل معقول. لكن لا تتوقّف هنا. يلزم تقرير التعامل مع BOM أيضاً.

طريقة تقرير موصى بها:

  • نصّ يُقرأ كثيراً من جانب Linux: اجعل الأساس UTF-8 بدون BOM
  • سكربت تقرأه أداة قديمة على Windows أو Windows PowerShell 5.1: صرّح بوجود BOM أو غيابه حسب الطرف الآخر
  • إن وُجد طرف واضح يحتاج UTF-16LE، اكتب ذلك المتطلّب كمواصفة

كتابة «توحيد UTF-8» وحدها تُشعل نزاع BOM لاحقاً.

طريقة تقرير encoding للملفّ الجديدمخطّط يبيّن أن الملفّ النصّي الجديد يُجعَل UTF-8 خياره الأوّل دون التوقّف هناك: إن كثر القراءة من Linux فالأساس UTF-8 بدون BOM، وإن قرأته أداة قديمة أو Windows PowerShell 5.1 يُصرَّح بوجود BOM حسب الطرف، وإن وُجد طرف يحتاج UTF-16LE يُكتَب المتطلّب كمواصفة.جانب Linux أكثر5.1 أو أداة قديمةطرف يحتاج UTF-16LEملفّ نصّي جديداجعل UTF-8 الخيار الأوّلمن يقرأالأساس UTF-8 بدون BOMصرّح بوجود BOM حسب الطرفاكتب المتطلّب كمواصفة

الشكل 17: للملفّ الجديد اجعل UTF-8 الخيار الأوّل، ثم احسم التعامل مع BOM حسب الطرف.

7.2 أبقِ ملفّات legacy القائمة حتى مهمّة ترحيل صريحة

إن كان الملفّ القائم CP932، أأمن ألّا يُحوَّل إلى UTF-8 من تلقاء نفسه في أثناء إصلاح وظيفة يومي.

شكل التشغيل الآمن:

  • الملفّ القائم يحافظ على encoding / BOM / السطر الجديد الأصلي
  • تغيير encoding يُفصَل كمهمّة ترحيل
  • التحويل بالجملة بعد تأكيد الأهداف ونطاق التأثير ومستهلكي المصبّ

كثير من حوادث تشوّه النصّ يبدأ من «تحويل إلى UTF-8 في أثناء ذلك» بحسن نيّة.

7.3 عامل encoding كجزء من الواجهة

CSV وTXT والسجلّ وملفّ الإعداد والبروتوكول البسيط، ليس المحتوى وحده بل encoding نفسه واجهة.

مثلاً، نريد كتابة التالي على الأقل كمواصفة.

  • هل هذا الملفّ UTF-8 أم CP932 أم UTF-16LE
  • في حالة UTF-8 هل يُرفَق BOM
  • هل السطر الجديد LF أم CRLF
  • أيّ من Linux / Windows هو المنتج / المستهلك
  • هل دفعة أو ETL في الطريق يعيد الحفظ

«نمرّر كنصّ» ليست مواصفة.

7.4 لا تثق بالقيمة الافتراضيّة؛ صرّح عند الكتابة

في الشيفرة كما في السكربت، التصريح بـ encoding أأمن.

الخطر في تفكير من هذا النوع:

  • الحفظ بالافتراضي
  • سيصير مناسباً على الأرجح حسب نظام التشغيل
  • ظهر في وحدة التحكّم إذن الملفّ سليم
  • هناك كشف تلقائي إذن لا بأس

القيمة الافتراضيّة تتغيّر عادة بين Windows / Linux، وPowerShell 5.1 / 7، والمحرّر، ووقت التشغيل. ما لم تصرّح، يسهل أن يكون العمل صدفة.

7.5 افصل تأكيد وحدة التحكّم عن تأكيد الملفّ

قاعدة تؤثّر بهدوء وبقوّة.

  • تأكيد العرض في وحدة التحكّم
  • تأكيد إعادة فتح الملفّ

افصل هذين.

حتى إن طابق chcp أو عرض الطرفيّة، فلا معنى إن كان الملفّ المحفوظ بترميز آخر. والعكس: حتى إن كان الملفّ سليماً، ينكسر المظهر وحده إن لم يطابق code page عرض وحدة التحكّم.

7.6 Git لا يصلح encoding

هادئ لكن مهم.

Git أساساً يتتبّع البايتات فقط. أي أن البايتات التالفة أيضاً تُدخَل في التاريخ بجدّيّة كما هي.

لذلك عندما:

  • يظهر فرق ضخم دون أن تغيّر شيئاً
  • يصير فرق غامض في الأسطر اليابانيّة فقط
  • يتغيّر السطر الأوّل فقط
  • يتغيّر السطر الجديد وencoding معاً

أولى أن تشكّ في حادث إعادة ترميز قبل تغيير المحتوى.

Git لا يصلح encodingمخطّط يبيّن أن Git يتتبّع البايتات أساساً فقط فتدخل البايتات التالفة في التاريخ كما هي، لذا عند ظهور فرق ضخم دون تغيير أو فرق غامض في الأسطر اليابانيّة فقط ينبغي الشكّ في حادث إعادة ترميز قبل تغيير المحتوى.Git يتتبّع البايتات فقطالبايتات التالفة تدخل التاريخ كما هيفرق ضخم أو فرق غامض في الأسطر اليابانيّة فقطاشكّ في حادث إعادة الترميز قبل تغيير المحتوى

الشكل 18: Git يسجّل البايتات التالفة أيضاً بجدّيّة، لذا الشكّ أوّلاً في إعادة الترميز عند الفرق الغامض.

8. قائمة التحقّق الدنيا

نضع قائمة التحقّق التي نريد تثبيتها أوّلاً في القضايا التي يختلط فيها Windows وLinux.

تدفّق قائمة التحقّقمخطّط يبيّن تدفّق تأكيد encoding وBOM والسطر الجديد الحالي قبل التحرير، وتجنّب الاتّكال على الافتراضي والكشف التلقائي أثناءه، وتأكيد إعادة الفتح والفرق بعده، مع التعامل مع التحويل بالجملة كمهمّة ترحيل منفصلة.قبل التحرير: أكّد encoding وBOM والسطر الجديد الحاليأثناء التحرير: تجنّب الاتّكال على الافتراضي والكشف التلقائيبعد التحرير: أكّد إعادة الفتح والفرقالتحويل بالجملة يُفصَل كمهمّة ترحيل

الشكل 19: التحقّق يُقسَم إلى قبل التحرير وأثناءه وبعده، والتحويل بالجملة يُقطَع كمهمّة منفصلة.

8.1 قبل التحرير

  • ما encoding هذا الملفّ الآن
  • هل يوجد BOM
  • هل السطر الجديد LF أم CRLF
  • هل سجّلت سطرين أو ثلاثة يابانيّة نموذجيّة
  • هل عرفت أيّ من جانب Linux / Windows هو المستهلك النهائي

8.2 أثناء التحرير

  • هل تكتب معتمداً على encoding الافتراضي
  • هل تحفظ متّكلاً على الكشف التلقائي
  • هل تستخدم مسار PowerShell أو إعادة توجيه الصدفة على عجل
  • هل تطمئن لمجرّد أن العرض مقروء

8.3 بعد التحرير

  • هل أكّدت بإعادة الفتح بعد الحفظ
  • هل الأسطر النموذجيّة لم تنهار في جانب Linux وفي جانب Windows
  • هل ازداد ? أو � في الفرق
  • هل انكسر السطر الأوّل أو العمود الأوّل فقط
  • هل صار الفرق الضخم BOM / السطر الجديد فقط

8.4 ما ينبغي فعله كمهمّة ترحيل

  • تحويل جملة من CP932 إلى UTF-8
  • توحيد سياسة BOM لـ UTF-8
  • جرد السكربتات بافتراض PowerShell 5.1
  • تدوين تمرير النصّ عبر CI / حاوية / WSL / SSH
  • توحيد إعدادات الحفظ في المحرّر / المنسّق / الدفعة

9. الخلاصة

إن لخّصنا مشكلة ترميز Windows بجملة، فالجوهر أن عالم Unicode وعالم code page القديم ما زالا يتعايشان.

وتزداد الحوادث عند الجمع مع Linux لأن جانب Linux يجري غالباً بفرضيّة UTF-8، فتظهر دفعة واحدة CP932 وUTF-16 وcode page لوحدة التحكّم وفروق إصدارات PowerShell في جانب Windows.

النقاط الخمس التي ينبغي تذكّرها:

  • تشوّه النصّ انحراف في تفسير البايتات
  • انهيار العرض وتلف البيانات مختلفان
  • على Windows فكّر بفصل طبقات الملفّ / المحرّر / وحدة التحكّم / API
  • اجعل UTF-8 الخيار الأوّل للنصّ المتبادَل مع Linux
  • افصل تحويل ملفّات legacy القائمة عن الإصلاح العادي

معاملة «تشوّه النصّ على Windows» كما هي توسّع الحديث أكثر من اللازم. لكن القطع بأربعة أسئلة:

  • ما البايتات الأصليّة
  • من كتب وكيف
  • من قرأ وكيف
  • هل حُفظ بالفعل

يرتب المسألة كثيراً.

الترميز هادئ، لكن بين Windows وLinux هو عقد الإدخال/الإخراج نفسه. أوّل إجراء ينفع هو ألّا تُترَك هذه النقطة غامضة.

روابط مرجعية

Windows / Microsoft

PowerShell / VS Code

GNU / Linux locale

أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.

ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.

الأسئلة الشائعة

أسئلة شائعة حول موضوع هذه المقالة.

ما سبب تشوّه النصّ على Windows؟
في معظم الحالات السبب هو قراءة البايتات نفسها بترميز مختلف، أو حفظ نتيجة القراءة الخاطئة بترميز آخر. مثلاً بايتات `あ` المحفوظة بـ UTF-8 (E3 81 82) إذا قُرئت في سياق CP932 تظهر كنصّ آخر مثل `縺`. ليست المسألة أن اليابانيّة صعبة، بل أن فرضيّة encode وdecode غير متطابقتين.
هل يمكن إعادة ملفّ تشوّه نصّه إلى أصله؟
إذا لم تتغيّر البايتات الأصليّة، قد يكفي إعادة فتحه بالـ encoding الصحيح. الخطر هو حفظ المحتوى الظاهر بعد القراءة الخاطئة كما هو؛ عندئذ لا يبقى الأمر عرضاً منهاراً بل تلفاً للبيانات. كذلك إذا أُسقطت سلسلة Unicode إلى code page ضيّق مثل CP932 فتحوّلت إلى `?` أو حرف استبدال، فإن الحروف الضائعة لا تُستعاد حتى بعد معرفة الـ encoding الصحيح.
هل يجعل chcp 65001 الملفّات UTF-8 أيضاً؟
لا. تغيير code page لوحدة التحكّم مسألة منفصلة عن ماهيّة بايتات الملفّ القائم. على Windows، ترميز الملفّ نفسه، وتفسير المحرّر، وcode page للإدخال/الإخراج في وحدة التحكّم، وتمثيل السلسلة داخل التطبيق، طبقات مختلفة ينبغي فصلها. الحكم بأن الملفّ سليم لأنّه ظهر صحيحاً في وحدة التحكّم يسهل أن يخطئ، لذا افصل تأكيد عرض وحدة التحكّم عن إعادة فتح الملفّ.
ما القاعدة الآمنة لتبادل النصّ بين Windows وLinux؟
اجعل UTF-8 الخيار الأوّل للملفّات الجديدة، وقرّر أيضاً التعامل مع BOM. للنصّ الذي يُقرأ كثيراً من جانب Linux اجعل الأساس UTF-8 بدون BOM، ولأدوات legacy مثل Windows PowerShell 5.1 صرّح بوجود BOM أو غيابه حسب الطرف الآخر. لا تحوّل ملفّات CP932 القائمة في أثناء إصلاح يومي؛ افصل ذلك كمهمّة ترحيل صريحة. CSV والسجلّات encoding نفسه فيها جزء من الواجهة، لذا اكتب encoding وBOM ورمز السطر الجديد كمواصفات.

الملف الشخصي للمؤلف

صفحة الملف الشخصي لمؤلف المقالة.

غو كومورا

مؤسّس شركة كومورا سوفت ذ.م.م.

يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.

العودة إلى المدونة