UTF-8 byte[] إلى string في C#: أي طريقة أسرع وأفضل؟

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

لماذا لا يزال سؤال "UTF-8 byte[] to string" ملحًا؟

\n\n

تخيل: لقد تلقيت مصفوفة بايتات من طلب شبكة، أو قرأت ملفًا ثنائيًا، أو ألغيت تسلسل بيانات من API. بداخلها — نص عادي بالروسية أو الإنجليزية أو رموز تعبيرية. لكن C# يرى فقط byte[]. مهمتك هي تحويل هذه الأصفار والواحدات إلى سلسلة string مفهومة.

\n\n

قد يبدو الأمر بسيطًا؟ استدعاء طريقة واحدة — وينتهي الأمر. لكن على Stack Overflow، سؤال "How to convert UTF-8 byte[] to string" يجمع آلاف المشاهدات وعشرات الإجابات. لماذا؟ لأن الشيطان يكمن في التفاصيل: الترميز، الأداء، الأمان، والاستثناءات غير المتوقعة.

\n\n

في هذه المقالة، لن نقدم فقط كودًا جاهزًا. سنقوم بمقارنة المناهج، وقياس السرعة، ومناقشة المزالق، واختيار أفضل أداة لكل مهمة. إذا كنت تكتب بلغة C# وتعمل مع الشبكات أو الملفات أو التسلسل — فهذه المادة لك.

\n\n

المشكلة: byte[] ليس سلسلة

\n\n

في C#، يتم تخزين السلسلة string بترميز UTF-16. أما البايتات التي حصلت عليها، فمن المرجح أنها مشفرة بـ UTF-8 (معيار الإنترنت، JSON، معظم البروتوكولات النصية). التحويل المباشر غير ممكن — سيعطي المترجم خطأ.

\n\n

نحتاج إلى وحدة فك ترميز تحول تسلسل بايتات UTF-8 إلى أحرف UTF-16. وهنا يبدأ الجزء المثير: لدى المطور ثلاثة مسارات مختلفة جوهريًا على الأقل.

\n\n

الطريقة 1: الكلاسيكية — Encoding.UTF8.GetString

\n\n

الطريقة الأكثر وضوحًا والتي توصي بها Microsoft هي استخدام الفئة الثابتة System.Text.Encoding:

\n\n
byte[] utf8Bytes = { 72, 101, 108, 108, 111, 32, 208, 191, 209, 128, 208, 176, 208, 178, 208, 176 }; // "Hello права"\nstring result = Encoding.UTF8.GetString(utf8Bytes);\nConsole.WriteLine(result); // الإخراج: Hello права
\n\n

الإيجابيات:

\n
    \n
  • البساطة — سطر واحد من الكود.
  • \n
  • دعم جميع الترميزات، بما في ذلك UTF-8 وUTF-16 وASCII وLatin-1.
  • \n
  • معالجة مدمجة لـ BOM (علامة ترتيب البايت) — إذا كان هناك علامة UTF-8 في بداية المصفوفة، سيتم تجاهلها.
  • \n
  • الأمان — لا توجد كتل unsafe.
  • \n
\n\n

السلبيات:

\n
    \n
  • كل استدعاء ينشئ سلسلة جديدة ومخزنًا مؤقتًا داخليًا.
  • \n
  • إذا كانت البايتات تالفة أو تحتوي على تسلسل UTF-8 غير صالح، فستلقي الطريقة افتراضيًا استثناء DecoderFallbackException (إذا لم يتم ضبط fallback).
  • \n
  • غير مثالية للمصفوفات الكبيرة جدًا (مئات الميغابايت) — نسخ مزدوج للبيانات.
  • \n
\n\n

متى تستخدمها؟

\n

في 95% من الحالات. هذا هو المعيار الصناعي. إذا كنت لا تكتب محللًا عالي التحميل أو لا تعمل مع غيغابايت من السجلات — استخدم Encoding.UTF8.GetString.

\n\n

الطريقة 2: سريعة وخطيرة — unsafe مع المؤشرات

\n\n

لأولئك الذين يطاردون السرعة ولا يخافون من unsafe. الفكرة: نحن نعلم أن UTF-8 وUTF-16 هما ترميزان مختلفان، ولكن إذا كانت المصفوفة تحتوي فقط على أحرف ASCII (رموز حتى 127)، فيمكن "تمديد" كل بايت إلى حرف ثنائي البايت دون فك ترميز.

\n\n
unsafe string UnsafeAsciiBytesToString(byte[] bytes)\n{\n    fixed (byte* pBytes = bytes)\n    {\n        return new string((sbyte*)pBytes, 0, bytes.Length);\n    }\n}
\n\n

هذا الكود يعمل فقط مع ASCII! بالنسبة للنص الروسي (أحرف > 127)، ستكون النتيجة غير صالحة. لكن بالنسبة للإنجليزية الخالصة، فهو أسرع بمقدار 2-3 مرات من Encoding.UTF8.GetString.

\n\n

الإيجابيات:

\n
    \n
  • أقل تكلفة إضافية — لا نسخ، لا فك ترميز.
  • \n
  • مثالي لتحليل رؤوس HTTP ومفاتيح JSON (إذا كانت ASCII).
  • \n
\n\n

السلبيات:

\n
    \n
  • خطير للأحرف متعددة البايت — تلف البيانات.
  • \n
  • يتطلب إذن unsafe في المشروع (غير مسموح به في كل مكان).
  • \n
  • لا يعالج

المدونات

توصيات الكتب