سؤال

كنت أكتب أداة CLI لـ Mac OS X (10.5+) يجب أن تتعامل مع وسائط خط الأوامر التي من المحتمل جدًا أن تحتوي على أحرف غير ASCII.

لمزيد من المعالجة ، أقوم بتحويل هذه الوسائط باستخدام +[NSString StringWithCstring: الترميز:].

مشكلتي هي أنني لم أتمكن من العثور على معلومات جيدة حول كيفية تحديد ترميز الشخصية المستخدمة من قبل الصدفة التي يتم فيها تشغيل CLI-Tool.
ما توصلت إليه كحل هو ما يلي:

NSDictionary *environment = [[NSProcessInfo processInfo] environment];
NSString *ianaName = [[environment objectForKey:@"LANG"] pathExtension];
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(
  CFStringConvertIANACharSetNameToEncoding( (CFStringRef)ianaName ) );

NSString *someArgument = [NSString stringWithCString:argv[someIndex] encoding:encoding];

أجد ذلك خامًا قليلاً - مما يجعلني أعتقد أنني فاتني شيئًا واضحًا ... لكن ماذا؟

هل هناك طريقة SANER/أنظف لتحقيق نفس الشيء؟

شكرا مقدما

د

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

المحلول 3

حسنًا ، يبدو أنه لا يوجد شيء!

كما أشار Yuji ، فإن الترميز الأساسي لأسماء الملفات هو UTF-8 ، بغض النظر عن ماذا. لذلك ، يحتاج المرء للتعامل مع سيناريوهين:

  1. الوسيطات التي يتم كتابتها في ، شخصية للشخصية ، من قبل المستخدم.
  2. الوسيطات التي يتم استكمال علامة التبويب أو إخراج أوامر مثل ls, ، لأنهم لا يحولون أي أحرف.

تتم تغطية الحالة الثانية ببساطة بافتراض UTF-8.

الحالة الأولى ، مع ذلك ، هي مشكلة:

  • على MAC OS 10.6 ، يحتوي $ LANG على اسم IANA NAME من التشفير المستخدم مثل de_DE.IANA_NAME.
  • قبل الثلج الفهد ، ليست هذه هي القضية إلى عن على charsets غير UTF-8!

لم أختبر كل شارت التي يمكن أن أفكر فيها ، لكن لم يتم تضمين أي من الأوروبيين. بدلاً من ذلك ، كان $ lang فقط محطًا اللغة (de_DE في حالتي)!

منذ نتائج الاتصال +[NSString stringWithCString:encoding:] مع تشفير غير صحيح غير محددة, ، لا يمكنك أن تفترض بأمان أنه سيعود nil في هذه الحالة* (إذا كان على سبيل المثال ، فهو Ascii فقط ، فقد يعمل بشكل جيد تمامًا!).

ما يضيف إلى الفوضى الكلية هو ذلك $LANG لا ينسجم لتكون موجودًا ، على أي حال: هناك خانة اختيار في تفضيلات terminal.app ، والتي تمكن المستخدم من عدم تعيينه $LANG على الإطلاق (لا تتحدث عن X11.APP الذي لا يبدو أنه يتعامل مع أي مدخلات غير ASCII ...).

إذن ما تبقى:

  1. تحقق من وجود $LANG. إذا لم يتم تعيينه ، goto: 4!
  2. تحقق فيما لو $LANG يحتوي على معلومات حول الترميز. إذا لم يحدث ، goto: 4!
  3. تحقق مما إذا كان الترميز الذي تجده هناك UTF-8. إذا كان Goto: 6 ، آخر ...
  4. إذا argc أكبر من 2 و [[NSString stringWithCString: argv[0] encoding: NSUTF8StringEncoding] isEqualToString: yourForceUTFArgumentFlag], ، طباعة أنك تجبر UTF-8 الآن و Goto 6. إذا لم يكن الأمر كذلك:
  5. افترض أنك لا تعرف أي شيء ، فأصدر تحذيرًا بأنه يجب على المستخدم تعيين الجهاز الترميز على UTF-8 وقد يفكر في المرور yourForceUTFArgumentFlag كحجة أولى و خروج().
  6. افترض UTF-8 وافعل ما عليك ...

يبدو غزر؟ هذا لأنه كذلك ، لكن لا يمكنني التفكير في أي شيء سانر طريقة للقيام بذلك.


ملاحظة أخرى على الرغم من ذلك: إذا كنت تستخدم UTF-8 كترميز ، stringWithCString: الترميز: إرجاع NIL كلما واجهت أحرف غير ASCII في سلسلة C ليس مشفرة في UTF-8.)

نصائح أخرى

الجواب يعتمد على ما يأتي منه عدم الأوعية.

  1. في OS X ، متغير البيئة LANG يفعل ليس تعكس اختيار اللغة في واجهة المستخدم الرسومية. قلة قليلة من الناس سوف يضعون LANG في سطر الأوامر.
  2. يتم تخزين اختيار "ترميز النظام" في واجهة المستخدم الرسومية ~/.CFUserTextEncoding, ويمكن الحصول عليها بواسطة CFStringGetSystemEncoding, ، انظر الى هذا Apple Doc.
  3. ومع ذلك ، فإن هذا "ترميز النظام" هو نادرا ما تستخدم إلا في برامج قديمة للغاية ، غير unicode. يستخدم أي برنامج عاقل الكاكاو يونيكود فقط ولا شيء آخر.
  4. على وجه الخصوص ، يتم تشفير مسار الملف على مستوى الكاكاو دائمًا في (متغير) UTF-8. لذلك ، للحصول على NSString من سلسلة C ، استخدم

     NSString*string=[NSString stirngWithCString:cString encoding:NSUTF8Encoding];
    

    وللحصول على سلسلة C لمسار الملف من NSString, ، استعمال

     char*path=[string fileSystemRepresentation];
    

    هنا يوصى بعدم استخدام فقط [string UTF8String], ، بسبب الدقة ، انظر هذا Apple Doc.

  5. لذلك ، أوصيك بعدم الاهتمام بالترميز وتولي UTF-8 فقط.

  6. ومع ذلك ، قد يكون هناك عدد صغير جدًا من الأشخاص الذين يرقون LANG على سطر الأوامر ، وقد ترغب في الاعتناء بهم. ثم ، ما فعلته هو الشيء الوحيد الذي يمكنني التوصل إليه.

لا يمكنك استخدام فقط [[NSProcessInfo processInfo] arguments]?

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