如何在 Zig 中打印 UTF-16 字符串?

Sap*_*ick 3 unicode utf-16 zig

我一直在尝试编写 UTF-16 字符串结构,尽管标准库提供了一个unicode模块,但它似乎没有提供打印出u16. 我试过这个:

const std = @import("std");
const unicode = std.unicode;
const stdout = std.io.getStdOut().outStream();

pub fn main() !void {
    const unicode_str = unicode.utf8ToUtf16LeStringLiteral(" hello! ");
    try stdout.print("{}\n", .{unicode_str});
}
Run Code Online (Sandbox Code Playgroud)

这输出:

[12:0]u16@202e9c
Run Code Online (Sandbox Code Playgroud)

有没有办法打印 unicode 字符串 ( []u16) 而不将其转换回非 unicode 字符串 ( []u8)?

pfg*_*pfg 6

无论[]const u8[]const u16存储编码Unicode代码点。Unicode 代码点适合在 0..1,114,112 范围内,因此每个代码点具有一个数组索引的实际 Unicode 字符串必须是[]const u21. utf-8 和 utf-16 都需要对不适合的代码点进行编码。除非出于 utf-16 的兼容性原因(如某些 Windows 函数),否则您可能应该使用[]const u8unicode 字符串。

要将 utf-16 打印到 utf-8 流,您必须解码 utf-16 并将其重新编码为 utf-8。目前没有格式说明符可以自动执行此操作。

您可以一次转换整个字符串,需要分配:

const utf8string = try std.unicode.utf16leToUtf8Alloc(alloc, utf16le);
Run Code Online (Sandbox Code Playgroud)

或者,没有分配:

var writer = std.io.getStdOut().writer();
var it = std.unicode.Utf16LeIterator.init(utf16le);
while (try it.nextCodepoint()) |codepoint| {
    var buf: [4]u8 = [_]u8{undefined} ** 4;
    const len = try std.unicode.utf8Encode(codepoint, &buf);
    try writer.writeAll(buf[0..len]);
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您正在编写需要系统调用写入的地方,那么如果不使用缓冲写入器,这将非常慢。

  • @Sapphire_Brick 输出流当前仅写入字节和字节片。如果您有一个引人注目的用例(例如需要 utf-16 的平台或代码),您可以建议添加 utf-16 编写器和格式化程序。 (2认同)