كيف يمكنني ترجمة أحرف 8 بت إلى أحرف 7 بت؟(أي.Ü إلى U)

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

  •  02-07-2019
  •  | 
  •  

سؤال

أنا أبحث عن رمز زائف، أو رمز نموذجي، لتحويل أحرف ascii ذات بت أعلى (مثل، Ü الذي يمتد ascii 154) إلى U (وهو ascii 85).

تخميني الأولي هو أنه نظرًا لوجود حوالي 25 حرفًا من أحرف ascii تشبه أحرف ascii ذات 7 بت، فيجب استخدام مصفوفة ترجمة.

اسمحوا لي أن أعرف إذا كنت تستطيع التفكير في أي شيء آخر.

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

المحلول

في الواقع كما اقترح غير موجود :وظيفة "iconv" موجودة للتعامل مع جميع التحويلات الغريبة بالنسبة لك، وهي متاحة في جميع لغات البرمجة تقريبًا ولها خيار خاص يحاول تحويل الأحرف المفقودة في المجموعة المستهدفة بتقريبات.

استخدم Iconv لتحويل سلسلة UTF-8 المدخلة إلى 7 بت ASCII.

وإلا، فسوف تنتهي دائمًا من ضرب حالة الزاوية :إدخال 8 بت باستخدام صفحة رموز مختلفة مع مجموعة مختلفة من الأحرف (وبالتالي لا يعمل على الإطلاق مع جدول التحويل الخاص بك)، نسيت تعيين حرف معلمة غبي أخير (لقد قمت بتعيين كل لهجة خطيرة/حادة، ولكن نسيت تعيين كارون التشيكية أو الشمال '°')، الخ.

بالطبع إذا كنت ترغب في تطبيق الحل على مشكلة محددة صغيرة (إنشاء أسماء ملفات صديقة لنظام الملفات لمجموعة الموسيقى الخاصة بك) فإن مصفوفات البحث هي الطريقة التي يجب اتباعها (إما مصفوفة لكل رقم رمز أعلى من 128 يعين تقريب أقل من 128 كما اقترحته JeeBee، أو أزواج المصدر/الهدف التي اقترحتها vIceBerg اعتمادًا على وظائف الاستبدال المتوفرة بالفعل باللغة التي تختارها)، لأنه يتم اختراقها معًا بسرعة والتحقق بسرعة من العناصر المفقودة.

نصائح أخرى

لمستخدمي .NET مقالة في CodeProject (بفضل نصيحة GvS) يجيب بالفعل على السؤال بشكل صحيح أكثر من أي سؤال آخر رأيته حتى الآن.

لكن الكود الموجود في تلك المقالة (في الحل رقم 1) مرهق.وهنا نسخة مدمجة:

// Based on http://www.codeproject.com/Articles/13503/Stripping-Accents-from-Latin-Characters-A-Foray-in
private static string LatinToAscii(string inString)
{
    var newStringBuilder = new StringBuilder();
    newStringBuilder.Append(inString.Normalize(NormalizationForm.FormKD)
                                    .Where(x => x < 128)
                                    .ToArray());
    return newStringBuilder.ToString();
}

للتوسع قليلاً في الإجابة، تستخدم هذه الطريقة سلسلة.تطبيع أيّ:

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

على وجه التحديد في هذه الحالة نستخدم نموذج التطبيع FormKD, ، الموصوفة في نفس مستندات MSDN على هذا النحو:

FormKD - يشير إلى أنه تمت تسوية سلسلة Unicode باستخدام تحليل التوافق الكامل.

لمزيد من المعلومات حول نماذج تسوية Unicode، راجع ملحق يونيكود رقم 15.

تمتلك معظم اللغات طريقة قياسية لاستبدال الأحرف المحركة بـ ASCII القياسي، لكن ذلك يعتمد على اللغة، وغالبًا ما يتضمن استبدال حرف واحد مُعلم بحرفين ASCII.على سبيل المثالفي الألمانية ü يصبح ue.لذا، إذا كنت تريد التعامل مع اللغات الطبيعية بشكل صحيح، فالأمر أكثر تعقيدًا مما تعتقد.

هل التحويل من Ü إلى U هو ما تريد فعله حقًا؟لا أعرف شيئًا عن اللغات الأخرى ولكن في الألمانية Ü ستصبح Ue، ö ستصبح oe، وما إلى ذلك.

أعتقد أنك لا تستطيع ذلك.

عادةً ما أفعل شيئًا كهذا:

AccentString = '"كل الأشياء الأخرى"'
ConvertString = 'AAAEEE[وجميع الأشياء الأخرى]'

البحث عن الحرف في AccentString واستبداله بنفس الفهرس في ConvertString

هث

في صفحة الرموز 1251، يتم ترميز الأحرف بـ 2 بايت:واحد للحرف الأساسي والآخر للتنوع.وبعد ذلك، عندما تقوم بالترميز مرة أخرى باستخدام ASCII، يتم الاحتفاظ بالأحرف الأساسية فقط.

public string RemoveDiacritics(string text)
{

  return System.Text.Encoding.ASCII.GetString(System.Text.Encoding.GetEncoding(1251).GetBytes(text));

}

من : http://www.clt-services.com/blog/post/Enlever-les-accents-dans-une-chaine-(proprement).aspx

يبدو أنك قد مسمر على ما أعتقد.مصفوفة طويلة من البايتات بطول 128 بايت، مفهرسة بواسطة char&127، تحتوي على حرف 7 بت مطابق للحرف 8 بت.

حسنًا، لماذا لا نقوم فقط بتغيير ترميز السلسلة باستخدام Iconv؟

يعتمد الأمر حقًا على طبيعة سلاسل المصدر الخاصة بك.إذا كنت تعرف تشفير السلسلة، وتعرف أنه تشفير 8 بت - على سبيل المثال، ISO Latin 1 أو ما شابه - فإن المصفوفة الثابتة البسيطة ستكون كافية:

static const char xlate[256] = { ..., ['é'] = 'e', ..., ['Ü'] = 'U', ... }
...
new_c = xlate[old_c];

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

هناك مقال عن CodeProject هذا يبدو جيدا.

كما أن التحويل باستخدام صفحة الرموز 1251 يثير اهتمامي (انظر الإجابة الأخرى).

لا أحب جداول التحويل، نظرًا لأن عدد الأحرف في Unicode كبير لدرجة أنه من السهل أن تفوت حرفًا واحدًا.

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

ربما تكون مصفوفة البحث هي أبسط وأسرع طريقة لتحقيق ذلك.هذه إحدى الطرق التي يمكنك من خلالها تحويل ASCII إلى EBCDIC.

الأحرف الـ 128 العليا ليس لها معاني قياسية.يمكنهم أخذ تفسيرات مختلفة (صفحات الرموز) اعتمادًا على لغة المستخدم.

على سبيل المثال، انظرالبرتغاليةعكسكندي فرنسي

ما لم تكن تعرف صفحة الرموز، فإن "ترجمتك" ستكون خاطئة في بعض الأحيان.

إذا كنت ستفترض صفحة رموز معينة (على سبيل المثال.صفحة رموز IBM الأصلية) فستعمل مصفوفة الترجمة، ولكن بالنسبة للمستخدمين الدوليين الحقيقيين، سيكون الأمر خاطئًا كثيرًا.

وهذا هو أحد أسباب تفضيل Unicode على النظام الأقدم لصفحات الرموز.

بالمعنى الدقيق للكلمة، ASCII هو 7 بتات فقط.

جرب ال uni2ascii برنامج.

أستخدم هذه الوظيفة لإصلاح متغير به علامات لتمريره إلى دالة الصابون من VB6:

Function FixAccents(ByVal Valor As String) As String

    Dim x As Long
    Valor = Replace(Valor, Chr$(38), "&#" & 38 & ";")

    For x = 127 To 255
        Valor = Replace(Valor, Chr$(x), "&#" & x & ";")
    Next

    FixAccents = Valor

End Function

وداخل وظيفة الصابون أفعل هذا (بالنسبة للمتغير Filename):

FileName = HttpContext.Current.Server.HtmlDecode(FileName)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top