Windows で msvc11 を使用して ICU4C を使用して、UTF-8 でエンコードされたファイルを読み込もうとしています。UnicodeString を作成するには、バッファーのサイズを決定する必要があります。ICU4C API には fseek のような関数がないため、基になる C ファイルを使用できると考えました。
#include <unicode/ustdio.h>
#include <stdio.h>
/*...*/
UFILE *in = u_fopen("utfICUfseek.txt", "r", NULL, "UTF-8");
FILE* inFile = u_fgetfile(in);
fseek(inFile, 0, SEEK_END); /* Access violation here */
int size = ftell(inFile);
auto uChArr = new UChar[size];
このコードには 2 つの問題があります。
- 何らかの理由で fseek() 行でアクセス違反を「スロー」します (test.exe の 0x000007FC5451AB00 (ntdll.dll) で未処理の例外: 0xC0000005: アクセス違反書き込み場所 0x0000000000000024)。
- ftell 関数によって返されるサイズは、UTF-8 がコード ポイントに最大 4 バイトを使用できるため、必要なサイズにはなりません (u8"tю" 文字列の長さは 3 になります)。
質問は次のとおりです。
- 入力ファイルが UTF-8 でエンコードされていることがわかっている場合、UnicodeString のバッファー サイズを決定するにはどうすればよいですか?
- ICU の UnicodeString の読み取りと書き込みの両方に iostream/fstream を使用するポータブルな方法はありますか?
編集:最初の回答とC++ 11標準に基づく可能な解決策(msvc11およびgcc 4.8.1でテスト済み)は次のとおりです。ISO IEC 14882 2011 からのいくつかのこと:
- 「C++ メモリ モデルの基本的なストレージ ユニットはバイトです。1 バイトは少なくとも、基本実行文字セット (2.3) の任意のメンバーと、Unicode UTF-8エンコード形式の 8 ビット コード単位を格納するのに十分な大きさです。 ..」
- 「基本的なソース文字セットは 96 文字で構成されています...」 - すでに 7 ビット必要
- 「基本実行文字セットと基本実行ワイド文字セットには、それぞれ基本ソース文字セットのすべてのメンバーが含まれます...」
- 「文字 (char) として宣言されたオブジェクトは、実装の基本文字セットのメンバーを格納するのに十分な大きさでなければなりません。」
したがって、実装で定義された char のサイズが 1 バイト = 8 ビットであるプラットフォームでこれを移植可能にするために (これがどこに当てはまらないかはわかりません)、フォーマットされていない入力操作を使用して Unicode 文字を char に読み取ることができます。
std::ifstream is;
is.open("utfICUfSeek.txt");
is.seekg(0, is.end);
int strSize = is.tellg();
auto inputCStr = new char[strSize + 1];
inputCStr[strSize] = '\0'; //add null-character at the end
is.seekg(0, is.beg);
is.read(inputCStr, strSize);
is.seekg(0, is.beg);
UnicodeString uStr = UnicodeString::fromUTF8(inputCStr);
is.close();
私が困っているのは、char 用に追加のバッファーを作成してから、それらを必要な UnicodeString に変換する必要があることです。