gpt4 book ai didi

c++ - 使用 ICU (ICU4C) 读取 UTF-8 编码文件的缓冲区大小

转载 作者:行者123 更新时间:2023-11-30 04:16:48 25 4
gpt4 key购买 nike

我正在尝试在 Windows 上使用 ICU4C 和 msvc11 读取一个 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];

这段代码有两个问题:

  1. 它出于某种原因在 fseek() 行“抛出”访问冲突(test.exe 中 0x000007FC5451AB00 (ntdll.dll) 处的未处理异常:0xC0000005:访问冲突写入位置 0x0000000000000024。)
  2. ftell 函数返回的大小不是我想要的大小,因为 UTF-8 最多可以使用 4 个字节作为代码点(u8"t+"字符串的长度为 3)。

所以问题是:

  1. 如果我知道输入文件是 UTF-8 编码的,如何确定 UnicodeString 的缓冲区大小?
  2. 是否有一种可移植的方式来使用 iostream/fstream 来读取和写入 ICU 的 UnicodeString?

编辑:这是基于第一个答案和 C++11 标准的可能解决方案(在 msvc11 和 gcc 4.8.1 上测试)。 ISO IEC 14882 2011 中的一些内容:

  1. “C++ 内存模型中的基本存储单元是字节。A字节至少足够大以包含基本的任何成员执行字符集(2.3)和八位代码单元Unicode UTF-8编码形式……”
  2. “基本源字符集由 96 个字符组成...”,- 已经需要 7 位
  3. 》基本执行字符集和基本执行宽字符集应包含基本的所有成员源字符集...”
  4. “声明为字符 (char) 的对象应足够大存储实现的基本字符集的任何成员。”

因此,为了使其适用于实现定义的 char 大小为 1 字节 = 8 位的平台(不知道哪里不正确),我们可以使用未格式化的输入操作将 Unicode 字符读入 chars:

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();

让我烦恼的是,我必须为字符创建一个额外的缓冲区,然后才将它们转换为所需的 UnicodeString。

最佳答案

这是使用 ICU 的替代方法。

使用标准的 std::fstream 您可以将文件的整个/部分读入标准的 std::string 然后使用 unicode 感知迭代器对其进行迭代. http://code.google.com/p/utf-iter/

std::string get_file_contents(const char *filename)
{
std::ifstream in(filename, std::ios::in | std::ios::binary);
if (in)
{
std::string contents;
in.seekg(0, std::ios::end);
contents.reserve(in.tellg());
in.seekg(0, std::ios::beg);
contents.assign((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
in.close();
return(contents);
}
throw(errno);
}

然后在你的代码中

std::string myString = get_file_contents( "foobar" );
unicode::iterator< std::string, unicode::utf8 /* or utf16/32 */ > iter = myString.begin();

while ( iter != myString.end() )
{
...
++iter;
}

关于c++ - 使用 ICU (ICU4C) 读取 UTF-8 编码文件的缓冲区大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17511783/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com