1

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 つの問題があります。

  1. 何らかの理由で fseek() 行でアクセス違反を「スロー」します (test.exe の 0x000007FC5451AB00 (ntdll.dll) で未処理の例外: 0xC0000005: アクセス違反書き込み場所 0x0000000000000024)。
  2. ftell 関数によって返されるサイズは、UTF-8 がコード ポイントに最大 4 バイトを使用できるため、必要なサイズにはなりません (u8"tю" 文字列の長さは 3 になります)。

質問は次のとおりです。

  1. 入力ファイルが UTF-8 でエンコードされていることがわかっている場合、UnicodeString のバッファー サイズを決定するにはどうすればよいですか?
  2. ICU の UnicodeString の読み取りと書き込みの両方に iostream/fstream を使用するポータブルな方法はありますか?

編集:最初の回答とC++ 11標準に基づく可能な解決策(msvc11およびgcc 4.8.1でテスト済み)は次のとおりです。ISO IEC 14882 2011 からのいくつかのこと:

  1. 「C++ メモリ モデルの基本的なストレージ ユニットはバイトです。1 バイトは少なくとも、基本実行文字セット (2.3) の任意のメンバーと、Unicode UTF-8エンコード形式の 8 ビット コード単位を格納するのに十分な大きさです。 ..」
  2. 「基本的なソース文字セットは 96 文字で構成されています...」 - すでに 7 ビット必要
  3. 「基本実行文字セットと基本実行ワイド文字セットには、それぞれ基本ソース文字セットのすべてのメンバーが含まれます...」
  4. 「文字 (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 に変換する必要があることです。

4

2 に答える 2

0

まあ、何らかの後処理のためにファイル全体を一度に読み込みたいicu::UnicodeString、その場合は実際には最良のコンテナではありません...

#include <iostream>
#include <fstream>
#include <sstream>

int main()
{
    std::ifstream in( "utfICUfSeek.txt" );
    std::stringstream buffer;
    buffer << in.rdbuf();
    in.close();
    // ...
    return 0;
}

...または、本当にicu::UnicodeString必要なのは、他の文字列オブジェクトと同じように読み込むことですが、長い道のりを歩んできました...

#include <iostream>
#include <fstream>

#include <unicode/unistr.h>
#include <unicode/ustream.h>

int main()
{
    std::ifstream in( "utfICUfSeek.txt" );
    icu::UnicodeString uStr;
    in >> uStr;
    // ...
    in.close();
    return 0;
}

...または、あなたの問題が実際に何であるかを完全に見逃しています。;)

于 2014-08-29T16:50:19.587 に答える