我们这里有一个JAVA应用程序,它加载和使用许多外部库。操作系统(视窗)的默认编码是“视窗-1252”(或“cp-1252”)。但是有一个外部库想要“utf-8”中的所有字符串(传入和传出)。我该怎么做?我如何才能只为一个JNA库更改字符串编码类型?
我发现的唯一方法是使用JNA的函数类(参见https://java-native-access.github.io/jna/5.2.0/javadoc/com/sun/jna/Function.html)就像这样:
public void setIp(String ip) {
Function fSetIp = Function.getFunction("myLib", "setIp", Function.C_CONVENTION, "utf-8");
Object[] args = {ip};
fSetIp.invoke(args);
}
但我必须为我想调用的每个函数实现这个。不确定是否有更好/更简单的方法。如果是,请回答我的问题。
Matthias Bläsing的答案是针对这个特定用例的更好的解决方案。如果你只需要字符编码,请先阅读。
下面是我最初的答案,对于更广泛的应用来说更为普遍。
处理它的一个简单方法是根本不直接映射String
字段/args。只需从库中发送和接收字节数组,并创建一个助手函数来进行Strings和字节数组之间的转换。正如您已经指出的,您可以将这些字节写入分配的Memory
块并传递指针。
如果你想要一个更持久的解决方案在幕后做同样的事情,你可以为这个特定的库使用一个类型映射器。
W32 PitypeMapper是一个很好的参考,它的stringConverter
变量显示了它如何在unicode中将String
映射到宽字符串WString
(UTF16)。
创建自己的UTF8TypeMapper
(或类似)并使用Java的字符集/编码函数将字符串转换为UTF-8字节序列。
这是未经测试的,但应该接近您需要的。您可以做更多的抽象来创建一个新的处理细节的UTF8String
类型。
public class UTF8TypeMapper extends DefaultTypeMapper {
public UTF8TypeMapper() {
TypeConverter stringConverter = new TypeConverter() {
@Override
public Object toNative(Object value, ToNativeContext context) {
if (value == null)
return null;
String str = (String) value;
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
// Allocate an extra byte for null terminator
Memory m = new Memory(bytes.length + 1);
// write the string's bytes
m.write(0, bytes, 0, bytes.length);
// write the terminating null
m.setByte((long) bytes.length, (byte) 0);
return m;
}
@Override
public Object fromNative(Object value, FromNativeContext context) {
if (value == null)
return null;
Pointer p = (Pointer) value;
// handles the null terminator
return p.getString(0, StandardCharsets.UTF_8.name());
}
@Override
public Class<?> nativeType() {
return Pointer.class;
}
};
addTypeConverter(String.class, stringConverter);
}
}
然后,在加载库时将类型映射器添加到选项中:
private static final Map<String, ?> UTF8_OPTIONS =
Collections.singletonMap(Library.OPTION_TYPE_MAPPER, new UTF8TypeMapper());
TheUTF8Lib INSTANCE = Native.load("TheUTF8Lib", TheUTF8Lib.class, UTF8_OPTIONS);
正常的JNA模式是:
public interface DemoLibrary extends Library {
DemoLibrary INSTANCE = Native.load("demoLibrary", DemoLibrary.class);
// abstract method declarations as interface to native library
}
然而,本机#加载被多次重载,以支持自定义绑定。相关重载是:本机#加载(字符串、类、映射
这里的相关选项是库。选项_字符串_编码
。该选项被传递给加载的NativeLibrary
实例,并将用作此类的默认编码。
上面的样本变成了然后
public interface DemoLibrary extends Library {
DemoLibrary INSTANCE = Native.load("demoLibrary", DemoLibrary.class,
Collections.singletonMap(Library.OPTION_STRING_ENCODING, "UTF-8"));
}
如果您需要自定义更多(typemapper,调用约定),您需要创建选项映射,例如在静态初始化器块中。
目前,我有一个很大的JavaScript字符串,我正试图写入一个文件,但编码方式不同(ISO-8859-1)。我希望使用类似downloadify的东西。Downloadify只接受普通JavaScript字符串或base64编码字符串。 因此,我决定使用JSZip压缩我的字符串,JSZip生成一个很好的base64编码字符串,可以传递给downloadify并下载到我的桌面。胡萨!问题是,我压缩
问题内容: Python中替换字符串中字符的最简单方法是什么? 例如: 问题答案: 不要修改字符串。 与他们一起工作作为清单;仅在需要时才将它们转换为字符串。 Python字符串是不可变的(即无法修改)。有很多的原因。使用列表,直到你别无选择,然后将它们变成字符串。
我正在尝试制作一个打字游戏,我为用户输入创建了一个文本字段,并尝试制作游戏,以便文本字段的最后一个字符是红色的,如果它不匹配要键入的单词中的相应字符。以下是我目前所掌握的相关节点的类型。
我想用Java将一个文件放入Windows中的回收站。以便用户能够还原它。
我认为每次更改字符串后,Python字符串的id都必须更改。但我发现真正的行为是不同的。例如,并非输出下面的所有代码字符串都不同: 这就是为什么我认为Python内核正在尝试优化代码,并开始对内存中的字符串进行奇怪的操作。该假设的另一个论点是,常量ID与大小为2的幂的段相关联: 但这其中还有一件奇怪的事。让我们看看随着字符串大小的增加,段大小会发生什么变化: 最后,我们可以尝试近似地将char添加
我正在处理一个关于codingbat的问题,这个问题说:给定一个字符串和第二个“单词”字符串,我们会说这个单词匹配字符串,如果它出现在字符串的前面,除了它的第一个字符不需要完全匹配...在匹配时,返回字符串的前面,或以其他方式返回空字符串。所以,所以用字符串“河马”,“嗨”这个词返回“嗨”,“xip”返回“臀部”。单词长度至少为1。我不能解决它,但在网上找到了一个解决方案,代码如下所示。代码工作,