寻找JDK 19 Foreign API中MemorySegment.getUtf8String的UTF-16等效方法
针对JDK Foreign Function and Memory API处理Windows UTF-16LE空终止字符串的优化方案
当前JDK现状
JDK 19及后续早期版本的Foreign Function and Memory API(JEP 424)仅为UTF-8编码的C风格空终止字符串提供了MemorySegment.getUtf8String()/setUtf8String()便捷方法,确实没有内置的Windows UTF-16LE(宽字符串)等效方法。
更优实现方案
1. 处理未知大小的内存段(高效查找空终止符)
避免逐字符遍历,利用MemorySegment.mismatch()方法批量查找双字节空终止符(0x0000),底层为优化的内存操作,性能远高于手动遍历:
public static String getUtf16LeString(MemorySegment segment, long offset) { // 匹配UTF-16LE的空终止符(连续两个0字节) long nullTerminatorPos = segment.mismatch(MemorySegment.ofArray(new byte[]{0, 0}), offset, 0, 2); if (nullTerminatorPos == -1) { throw new IllegalArgumentException("未找到UTF-16LE字符串的空终止符"); } // 计算有效字符串的字节长度 long validByteLength = nullTerminatorPos - offset; // 切片并解码为字符串 return segment.asSlice(offset, validByteLength).getString(0, StandardCharsets.UTF_16LE); }
2. 处理固定大小缓冲区
无需使用split()或trim(),直接解码后截取到第一个空字符(\u0000)即可,性能更优:
public static String getUtf16LeStringFromFixedBuffer(MemorySegment segment, long offset, long bufferSize) { String fullDecodedStr = segment.asSlice(offset, bufferSize).getString(0, StandardCharsets.UTF_16LE); int nullCharIndex = fullDecodedStr.indexOf('\u0000'); return nullCharIndex != -1 ? fullDecodedStr.substring(0, nullCharIndex) : fullDecodedStr; }
3. 写入UTF-16LE空终止字符串
对应写入操作可结合setString()和空终止符写入,保证符合Windows宽字符串规范:
public static void setUtf16LeString(MemorySegment segment, long offset, String str) { // 计算字符串对应的字节长度(每个UTF-16LE字符占2字节) long strByteLength = str.length() * 2; // 写入字符串内容 segment.asSlice(offset, strByteLength).setString(0, str, StandardCharsets.UTF_16LE); // 追加双字节空终止符 segment.set(offset + strByteLength, (short) 0); }
补充说明
这些方案基于JDK内存段的内置优化能力,相比手动遍历或全量数组操作,在性能和代码简洁性上都有明显提升。若需要跟踪官方是否会添加内置方法,可关注OpenJDK的相关功能提案,但目前自定义实现是最优选择。
内容的提问来源于stack exchange,提问作者Daniel Widdis
相关产品推荐
相关产品推荐

