簡體   English   中英

如何在C++中將文件編碼格式設置為UTF8

[英]How to set file encoding format to UTF8 in C++

我的軟件的要求是包含導出數據的文件的編碼應為 UTF8。 但是當我將數據寫入文件時,編碼始終是 ANSI。 (我使用 Notepad++ 檢查這個。)

我目前正在做的是嘗試通過讀取手動轉換文件,將其轉換為 UTF8 並將文本寫入新文件。

line是一個std::string
inputFile是一個std::ifstream
pOutputFile是一個FILE*

// ...

if( inputFile.is_open() )
{
    while( inputFile.good() )
    {
        getline(inputFile,line);

        //1
        DWORD dwCount = MultiByteToWideChar( CP_ACP, 0, line.c_str(), -1, NULL, 0 );
        wchar_t *pwcharText;
        pwcharText = new wchar_t[ dwCount];

        //2
        MultiByteToWideChar( CP_ACP, 0, line.c_str(), -1, pwcharText, dwCount );

        //3
        dwCount = WideCharToMultiByte( CP_UTF8, 0, pwcharText, -1, NULL, 0, NULL, NULL );
        char *pText;
        pText = new char[ dwCount ];

        //4
        WideCharToMultiByte( CP_UTF8, 0, pwcharText, -1, pText, dwCount, NULL, NULL );

        fprintf(pOutputFile,pText);
        fprintf(pOutputFile,"\n");

        delete[] pwcharText;
        delete[] pText;
    }
}

// ...

不幸的是,編碼仍然是 ANSI。 我搜索了一段時間的解決方案,但我總是通過 MultiByteToWideChar 和 WideCharToMultiByte 遇到解決方案。 但是,這似乎不起作用。 我在這里錯過了什么?

我也在 SO 上尋找解決方案,但大多數 UTF8 問題都涉及 C# 和 php 的東西。

在 VC++2010 中的 Windows 上,有可能(據我所知尚未在 GCC 中實現)使用本地化方面 std::codecvt_utf8_utf16(即在 C++11 中)。 來自cppreference.com的示例代碼包含讀/寫 UTF-8 文件所需的所有基本信息。

std::wstring wFromFile = _T("𤭢teststring");
std::wofstream fileOut("textOut.txt");
fileOut.imbue(std::locale(fileOut.getloc(), new std::codecvt_utf8_utf16<wchar_t>));
fileOut<<wFromFile;

它將 ANSI 編碼文件設置為 UTF-8(在記事本中選中)。 希望這就是您所需要的。

在 Windows 上,文件沒有編碼。 每個應用程序都將根據自己的規則采用一種編碼。 您能做的最好的事情就是在文件的前面放置一個字節順序標記,並希望它能被識別。

AFAIK, fprintf()進行字符轉換,因此不能保證將 UTF-8 編碼數據傳遞給它實際上會將 UTF-8 寫入文件。 由於您已經自己轉換了數據,因此請改用fwrite()以便按原樣編寫 UTF-8 數據,例如:

DWORD dwCount = MultiByteToWideChar( CP_ACP, 0, line.c_str(), line.length(), NULL, 0 );  
if (dwCount == 0) continue;

std::vector<WCHAR> utf16Text(dwCount);  
MultiByteToWideChar( CP_ACP, 0, line.c_str(), line.length(), &utf16Text[0], dwCount );  

dwCount = WideCharToMultiByte( CP_UTF8, 0, &utf16Text[0], utf16Text.size(), NULL, 0, NULL, NULL );  
if (dwCount == 0) continue;

std::vector<CHAR> utf8Text(dwCount);  
WideCharToMultiByte( CP_UTF8, 0, &utf16Text[0], utf16Text.size(), &utf8Text[0], dwCount, NULL, NULL );  

fwrite(&utf8Text[0], sizeof(CHAR), dwCount, pOutputFile);  
fprintf(pOutputFile, "\n");  

char類型沒有任何編碼的線索,它所能做的就是存儲 8 位。 因此,任何文本文件都只是一個字節序列,用戶必須猜測底層編碼。 以 BOM 開頭的文件表示 UTF 8,但不建議再使用 BOM。 相比之下,類型wchar_t在 Windows 中總是被解釋為 UTF 16。

假設您有一個以 UTF 8 編碼的文件,只有一行:“Confucius says: Smile. 孔子說:微笑!”。 以下代碼片段再次附加此文本,然后讀取第一行並將其顯示在MessageBoxWMessageBoxA中。 請注意, MessageBoxW顯示正確的文本,而MessageBoxA顯示一些垃圾,因為它假定我的本地代碼頁 1252 用於char*字符串。

請注意,我使用了方便的CA2W類而不是MultiByteToWideChar 請注意, CP_Whatever參數是可選的,如果省略,則使用本地代碼頁。

#include <iostream>
#include <fstream>
#include <filesystem>
#include <atlbase.h>

int main(int argc, char** argv)
{
  std::fstream  afile;
  std::string line1A = u8"Confucius says: Smile. 孔子說:微笑! 😊";
  std::wstring line1W;

  afile.open("Test.txt", std::ios::out | std::ios::app);
  if (!afile.is_open())
        return 0;

  afile << "\n" << line1A;
  afile.close();

  afile.open("Test.txt", std::ios::in);
  std::getline(afile, line1A);
  line1W = CA2W(line1A.c_str(), CP_UTF8);
  MessageBoxW(nullptr, line1W.c_str(), L"Smile", 0);
  MessageBoxA(nullptr, line1A.c_str(), "Smile", 0);
  afile.close();

  return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM