将Boost::uint64转换为Java的最有效方法

Most efficient way to convert Boost::uint64 to Java

本文关键字:有效 Java 方法 Boost uint64 转换      更新时间:2023-10-16

作为一个简短的例子,我有C++JNI代码,它将获取某个文件的文件大小,我想将其传递回Java。

A) 这是明智的做法吗?

B) 有没有比将数据转储到字符串中更好的方法呢?

C++代码段:

JNIEXPORT jstring JNICALL Java_test_TestClass_getNumBytes(...) {
  boost::uintmax_t numBytes = 0;
  try {
    numBytes = boost::filesystem::file_size(MY_GLOBAL_FILE_NAME);
  } catch(const boost::filesystem::filesystem_error& e) {
    return env->NewStringUTF("0");
  }
  return env->NewStringUTF(boost::lexical_cast<std::string>(numBytes));
}

Java代码段:

private native String getNumBytes();
public void doStuff() {
  final String s = getNumBytes();
  final BigInteger bi = new BigInteger(s);
  final StringBuilder sb = new StringBuilder("Comparing: ");
  sb.append(s).append(" to ").append(bi);
  System.out.println("Values should look the same: " + sb.toString());
}

假设Java无法访问MY_GLOBAL_FILE_NAME。

只需将boost::uintmax_t强制转换为jlong。很可能,可能的精度损失仍然是一个理论问题。Java中的任何I/O API都使用签名的long

如果您想为符号成为问题的大小做好准备,您仍然可以将值作为jlong传递给Java代码,并在Java端进行修复,因为溢出不会破坏信息,而且符号提供了一个易于检查的溢出指示符。

代码可能看起来像这样:

// 2⁶⁴
private static BigInteger twoP64=BigInteger.ZERO.flipBit(64);
public static BigInteger getNumBytes()
{
  long longValue=getNumByteNative();
  BigInteger i=BigInteger.valueOf(longValue);
  if(longValue<0) i=i.add(twoP64);
  return i;
}
private native long getNumByteNative();

这比在本地端构建BigInteger要容易得多。它提供了在Java方面有条件地进行操作,只要合适就使用long,只有在必要时才使用BigInteger(我想永远不会)。