C++ Unicode文件输入输出

4
我需要一个文件io库,可以给我的程序提供utf-16(小端)接口,但可以处理其他编码的文件,主要是ascii(仅输入),utf-8,utf-16,utf-32 / ucs4,包括小端和大端字节顺序。
我搜寻了一圈,唯一找到的库是ICU ustdio.h库。
我尝试过它,但是我甚至无法让它与一个非常简单的文本一起工作,并且几乎没有关于其使用的文档,只有ICU文件参考页面,其中没有示例和很少的详细信息(例如从现有文件创建UFILE后,是否安全使用其他接受FILE *的函数?以及其他几个问题...)。
而且,我更喜欢一个能够为我提供宽流接口而不是C样式接口的c++库。
std::wstring str = L"Hello World in UTF-16!\nAnother line.\n";
UFILE *ufile = u_fopen("out2.txt", "w", 0, "utf-16");
u_file_write(str.c_str(), str.size(), ufile);
u_fclose(ufile);

输出

Hello World in UTF-16!਍䄀渀漀琀栀攀爀 氀椀渀攀⸀ഀ

hex

FF FE 48 00 65 00 6C 00 6C 00 6F 00 20 00 57 00
6F 00 72 00 6C 00 64 00 20 00 69 00 6E 00 20 00
55 00 54 00 46 00 2D 00 31 00 36 00 21 00 0D 0A
00 41 00 6E 00 6F 00 74 00 68 00 65 00 72 00 20
00 6C 00 69 00 6E 00 65 00 2E 00 0D 0A 00

编辑:在Windows上的正确输出应该是:

FF FE 48 00 65 00 6C 00 6C 00 6F 00 20 00 57 00 
6F 00 72 00 6C 00 64 00 20 00 69 00 6E 00 20 00 
55 00 54 00 46 00 2D 00 31 00 36 00 21 00 0D 00 
0A 00 41 00 6E 00 6F 00 74 00 68 00 65 00 72 00
20 00 6C 00 69 00 6E 00 65 00 2E 00 0D 00 0A 00
5个回答

4
你看到的问题来自于换行符转换。不幸的是,它是在字节级别上进行的(在代码转换之后),并且不知道编码。也就是说,你必须禁用自动转换(通过以二进制模式打开文件,并带有“b”标志),如果你想让0A00扩展为0D00A00,你必须自己完成。
你提到你更喜欢C++宽流接口,所以我将概述我们在软件中实现它的方法:
使用ICU UConverter编写std::codecvt facet以执行转换。 使用std::wfstream打开文件。 在wfstream中imbue()您的自定义codecvt。 打开wfstream时使用二进制标志,以关闭自动(且错误的)换行符转换。 编写“WNewlineFilter”以对wchar进行换行符转换。从boost::iostreams::newline_filter获得灵感。 使用boost::iostreams::filtering_wstream将wfstream和WNewlineFilter绑定在一起作为流。

4

2
"

UTF8-CPP提供了UTF-8、16和32之间的转换。非常好用且轻量级。

关于ICU,UTF8-CPP的创建者有一些评论:

ICU库。它非常强大、完整、功能丰富、成熟且被广泛使用。但也很大、侵入式、非通用,并且与标准库不兼容。我强烈建议即使您不打算使用它,也要看看ICU。

:)

"

1

我认为问题来自于 0D 0A 00 的换行符。你可以尝试其他的换行符,比如\r\n或者只使用LF或CR(最好使用\r)。

编辑:看起来你需要的是0D 00 0A 00,所以你可以尝试这个。

std::wstring str = L"Hello World in UTF-16!\15\12Another line.\15\12";

尝试过那种东西,\r 可以使用,\n 被一个损坏的 \r\n 替换,所以我的字符串中的 \r\n 变成了 0D 00 0D 0A 00。 - Fire Lancer
是的,我想这会发生在\r\n上。我甚至猜测0D 00 0A 00也不好,因为你会得到两个换行符而不是一个。 - schnaader
(最好的选择可能是使用\r,我想)我宁愿使用一个能够在给定平台上写入有效文件的库,即对于dos/windows,\r\n,对于linux,\n,对于mac,\r。除了ar之外,还有很多其他使用期望具有Windows换行符的有效小端UTF-16文件的文件的东西都可能会出问题... - Fire Lancer
"0D 00 0A 00" 在 Windows 上是正确的,所以这正是我想要输出(并能够读取)作为新行的内容。\r 或 \n 对于 Windows 文件来说都不正确。 - Fire Lancer

1
你可以尝试使用 iconv (libiconv) 库。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接