5

UCS-2 リトル エンディアンの *.rc ファイル エンコーディングで情報を取得するプログラムを作成しています。

int _tmain(int argc, _TCHAR* argv[]) {
  wstring csvLine(wstring sLine);
  wifstream fin("en.rc");
  wofstream fout("table.csv");
  wofstream fout_rm("temp.txt");
  wstring sLine;
  fout << "en\n";
  while(getline(fin,sLine)) {
    if (sLine.find(L"IDS") == -1)
      fout_rm << sLine << endl;
    else
      fout << csvLine(sLine);
  }
  fout << flush;
  system("pause");
  return 0;
}

「en.rc」の最初の行は次のよう#include <windows.h>sLineなります。

[0]     255 L'ÿ'
[1]     254 L'þ'
[2]     35  L'#'
[3]     0
[4]     105 L'i'
[5]     0
[6]     110 L'n'
[7]     0
[8]     99  L'c'
.       .
.       .
.       .

このプログラムは、UTF-8 で正しく動作します。UCS-2 にするにはどうすればよいですか?

4

2 に答える 2

10

ワイド ストリームは、ワイド ストリーム バッファを使用してファイルにアクセスします。ワイド ストリーム バッファはファイルからバイトを読み取り、その codecvt ファセットを使用してこれらのバイトをワイド文字に変換します。デフォルトの codecvt ファセットはstd::codecvt<wchar_t, char ,std::mbstate_t>と のネイティブ文字セット間で変換しwchar_tますchar(つまり、mbstowcs() が行います)。

ネイティブの char 文字セットを使用していないため、必要なのはUCS-2、マルチバイト シーケンスとして読み取ってワイド文字に変換する codecvt ファセットです。

#include <fstream>
#include <string>
#include <codecvt>
#include <iostream>

int main(int argc, char *argv[])
{
    wifstream fin("en.rc", std::ios::binary); // You need to open the file in binary mode

    // Imbue the file stream with a codecvt facet that uses UTF-16 as the external multibyte encoding
    fin.imbue(std::locale(fin.getloc(),
              new std::codecvt_utf16<wchar_t, 0xffff, consume_header>));

    // ^ We set 0xFFFF as the maxcode because that's the largest that will fit in a single wchar_t
    //   We use consume_header to detect and use the UTF-16 'BOM'

    // The following is not really the correct way to write Unicode output, but it's easy
    std::wstring sLine;
    std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> convert;
    while (getline(fin, sLine))
    {
        std::cout << convert.to_bytes(sLine) << '\n';
    }
}

ここに問題があることに注意してUTF-16ください。の目的wchar_tは、1wchar_tつのコードポイントを表すことです。ただし、Windows ではUTF-16、一部のコードポイントを2 つ wchar_tの として表す which を使用します。これは、標準 API が Windows でうまく機能しないことを意味します。

ここでの結果は、ファイルにサロゲート ペアが含まれている場合、 はcodecvt_utf16そのペアを読み取り、それを 16 ビットより大きい単一のコードポイント値に変換し、値を 16 ビットに切り捨ててwchar_t. これは、このコードが実際に制限されていることを意味しますUCS-2。これを反映するために maxcode テンプレート パラメーターを に設定しました0xFFFF

には他にも多くの問題がありwchar_t、完全に回避したい場合があります: C++ wchar_t の「問題」は何ですか?

于 2012-07-25T17:34:35.623 に答える
0
#include <filesystem>
namespace fs = std::filesystem;

    FILE* f = _wfopen(L"myfile.txt", L"rb");
    auto file_size = fs::file_size(filename);
std::wstring buf;       
buf.resize((size_t)file_size / sizeof(decltype(buf)::value_type));// buf in my code is a template object, so I use decltype(buf) to decide its type.
    fread(&buf[0], 1, 2, f); // escape UCS2 BOM
    fread(&buf[0], 1, file_size, f);
于 2020-11-24T08:56:54.037 に答える