سؤال

أنا أعمل حاليًا على برنامج MFC يجب أن يعمل مع UTF-8 على وجه التحديد. في مرحلة ما ، يجب أن أكتب بيانات UTF-8 في ملف ؛ للقيام بذلك ، أنا أستخدم CFILES و CSTRINGS.

عندما أحصل على كتابة بيانات UTF-8 (الأحرف الروسية ، لأكون أكثر دقة) في ملف ، يبدو أن الإخراج

Ðàñïå÷àòàíî:
Ñèñòåìà
Ïðîèçâîäñòâî

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

CFile CSVFile( m_sCible, CFile::modeCreate|CFile::modeWrite);
CString sWorkingLine;
//Add stuff into sWorkingline
CSVFile.Write(sWorkingLine,sWorkingLine.GetLength());
//Clean sWorkingline and start over

هل فاتني شيء؟ هل يمكنني استخدام شيء آخر بدلاً من ذلك؟ هل هناك نوع من الصيد الذي فاتني؟ سوف يتم ضبطها من أجل حكمتك وخبرتك ، زملائك المبرمجين.

تحرير: بالطبع ، كما سألت للتو سؤالًا ، أجد أخيرًا شيئًا قد يكون مثيرًا للاهتمام ، ويمكن العثور عليه هنا. اعتقدت أنني قد أشاركها.

تحرير 2:

حسنًا ، لقد أضفت BOM إلى ملفي ، الذي يحتوي الآن على حرف Chineese ، ربما لأنني لم أحول خطي إلى UTF-8. لإضافة بوم فعلت ...

char BOM[3]={0xEF, 0xBB, 0xBF};
CSVFile.Write(BOM,3);

وبعد ذلك ، أضفت ...

    TCHAR TestLine;
    //Convert the line to UTF-8 multibyte.
    WideCharToMultiByte (CP_UTF8,0,sWorkingLine,sWorkingLine.GetLength(),TestLine,strlen(TestLine)+1,NULL,NULL);
    //Add the line to file.
    CSVFile.Write(TestLine,strlen(TestLine)+1);

ولكن بعد ذلك ، لا يمكنني التجميع ، لأنني لا أعرف حقًا كيفية الحصول على طول Testline. لا يبدو أن سترلين يقبل Tchar.ثابت ، استخدمت static endenght من 1000 بدلا من ذلك.

تحرير 3:

لذا ، أضفت هذا الرمز ...

    wchar_t NewLine[1000];
    wcscpy( NewLine, CT2CW( (LPCTSTR) sWorkingLine ));
    TCHAR* TCHARBuf = new TCHAR[1000];

    //Convert the line to UTF-8 multibyte.
    WideCharToMultiByte (CP_UTF8,0,NewLine,1000,TCHARBuf,1000,NULL,NULL);

    //Find how many characters we have to add
    size_t size = 0;
    HRESULT hr = StringCchLength(TCHARBuf, MAX_PATH, &size);

    //Add the line to the file
    CSVFile.Write(TCHARBuf,size);

إنه يجمع بشكل جيد ، لكن عندما أذهب إلى إلقاء نظرة على ملفي الجديد ، فإنه تمامًا كما لو لم يكن لدي كل هذا الرمز الجديد (على سبيل المثال: ðàñïå ÷ àòàíî :). يبدو الأمر وكأنني لم أقم بخطوة للأمام ، على الرغم من أنني أعتقد أن شيئًا صغيرًا فقط هو ما يفصلني عن النصر.

تحرير 4:

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

        CT2CA outputString(sWorkingLine, CP_UTF8);

    //Add line to file.
    CSVFile.Write(outputString,::strlen(outputString));

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

التحرير النهائي (آمل) من خلال تغيير الطريقة التي حصلت بها لأول مرة على شخصيات UTF-8 (قمت بإعادة الترميز دون أن أعرف حقًا) ، وهو ما كان خطأ في طريقتي الجديدة لإخراج النص ، حصلت على نتائج مقبولة. عن طريق إضافة UTF-8 BOM char في بداية ملفي ، يمكن قراءته كوحدة في البرامج الأخرى ، مثل Excel.

يا هلا! شكرا لكل شخص!

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

المحلول

عندما تقوم بإخراج البيانات التي تحتاج إلى القيام بها (هذا يفترض أنك تقوم بتجميعها في وضع Unicode ، وهو موصى به للغاية):

CString russianText = L"Привет мир";

CFile yourFile(_T("yourfile.txt"), CFile::modeWrite | CFile::modeCreate);

CT2CA outputString(russianText, CP_UTF8);
yourFile.Write(outputString, ::strlen(outputString));

إذا _UNICODE لم يتم تعريفه (أنت تعمل في وضع متعدد البايت بدلاً من ذلك) ، فأنت بحاجة إلى معرفة صفحة الكود التي يوجد فيها نص الإدخال الخاص بك وتحويله إلى شيء يمكنك استخدامه. يوضح هذا المثال العمل مع النص الروسي الموجود بتنسيق UTF-16 ، مما يوفره إلى UTF-8:

// Example 1: convert from Russian text in UTF-16 (note the "L"
// in front of the string), into UTF-8.
CW2A russianTextAsUtf8(L"Привет мир", CP_UTF8);
yourFile.Write(russianTextAsUtf8, ::strlen(russianTextAsUtf8));

على الأرجح ، نصك الروسي موجود في صفحة رمز أخرى ، مثل KOI-8R. في هذه الحالة ، تحتاج إلى تحويل من صفحة التعليمات البرمجية الأخرى إلى UTF-16. ثم تحويل UTF-16 إلى UTF-8. لا يمكنك التحويل مباشرة من KOI-8R إلى UTF-8 باستخدام وحدات الماكرو للتحويل لأنها تحاول دائمًا تحويل النص الضيق إلى صفحة رمز النظام. لذا فإن الطريقة السهلة هي القيام بذلك:

// Example 2: convert from Russian text in KOI-8R (code page 20866)
// to UTF-16, and then to UTF-8. Conversions between UTFs are
// lossless.
CA2W russianTextAsUtf16("\xf0\xd2\xc9\xd7\xc5\xd4 \xcd\xc9\xd2", 20866);
CW2A russianTextAsUtf8(russianTextAsUtf16, CP_UTF8);
yourFile.Write(russianTextAsUtf8, ::strlen(russianTextAsUtf8));

لا تحتاج إلى BOM (إنه اختياري ؛ لن أستخدمه إلا إذا كان هناك سبب محدد للقيام بذلك).

تأكد من قراءة هذا: http://msdn.microsoft.com/en-us/library/87zae4a3(vs.80).aspx. إذا كنت تستخدم بشكل غير صحيح CT2CA (على سبيل المثال ، باستخدام مشغل الواجب) سوف تواجه مشكلة. تعرض صفحة الوثائق المرتبطة أمثلة على كيفية الاستخدام وكيفية عدم استخدامها.

مزيد من المعلومات:

  • ال ج في CT2CA يشير const. أستخدمه عندما يكون ذلك ممكنًا ، لكن بعض التحويلات تدعم فقط الإصدار غير المؤلف (على سبيل المثال CW2A).
  • ال ر في CT2CA يشير إلى أنك تتحول من و LPCTSTR. وبالتالي ، سيعمل ما إذا تم تجميع الكود الخاص بك مع _UNICODE العلم أم لا. يمكنك أيضا استخدام CW2A (أين ث يشير إلى أحرف واسعة).
  • ال أ في CT2CA يشير إلى أنك تتحول إلى سلسلة "ANSI" (8 بت char).
  • أخيرًا ، المعلمة الثانية CT2CA يشير إلى صفحة التعليمات البرمجية التي تقوم بتحويلها إليها.

للقيام بالتحويل العكسي (من UTF-8 إلى LPCTST) ، يمكنك القيام:

CString myString(CA2CT(russianText, CP_UTF8));

في هذه الحالة ، نحن نتحول من سلسلة "ANSI" بتنسيق UTF-8 ، إلى LPCTSTR. ال LPCTSTR يُفترض دائمًا أن يكون UTF-16 (إذا _UNICODE تم تعريفه) أو صفحة رمز النظام الحالية (إذا _UNICODE غير محدد).

نصائح أخرى

عليك التحويل sWorkingLine إلى UTF-8 ثم اكتبه في الملف.

Widechartomultibyte يمكن تحويل سلاسل Unicode إلى UTF-8 إذا قمت بتحديد CP_UTF8 codepage.multibytetoWidechar يمكن تحويل chars ASCII إلى Unicode.

تأكد من أنك تستخدم Unicode (Tchar هو WCHAR_T). ثم قبل كتابة البيانات ، قم بتحويلها باستخدام وظيفة API WIDECHARTOMultiByte WIN32.

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