将jbyteArray转换为字符数组,然后打印到控制台

Sea*_*ang 6 java-native-interface type-conversion

我正在编写一个JNI程序,其中.cpp文件获取jbyteArray,我希望能够使用printf打印jbyteArray.为此,我相信我必须将jbyteArray转换为字符数组.

对于背景知识,我的JNI的java端将String转换为byteArray,然后将byteArray作为参数传递给我的JNI函数.

到目前为止我所做的正确打印出String,但后面是垃圾字符,我不知道如何摆脱这些/如果我做错了.

以下是String的内容:

dsa
Run Code Online (Sandbox Code Playgroud)

什么打印到控制台:

dsa,?
Run Code Online (Sandbox Code Playgroud)

垃圾字符根据字符串的内容而变化.以下是相关代码的一部分:

.java文件:

public class tcr extends javax.swing.JFrame{

static{
    System.loadLibrary("tcr");
}

public native int print(byte file1[]);

    .....

    String filex1 = data1TextField.getText();//gets a filepath in the form of a String from a GUI jtextfield.
    byte file1[]= filex1.getBytes();//convert file path from string to byte array

        tcr t = new tcr();
        t.print(file1);
}
Run Code Online (Sandbox Code Playgroud)

.cpp代码:

JNIEXPORT jint JNICALL Java_tcr_print(JNIIEnv *env, jobject thisobj, jbyteArray file1){

    jboolean isCopy;
    jbyte* a = env->GetByteArrayElements(file1,&isCopy);
    char* b;
    b = (char*)a;
    printf("%s\n",b);
}
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激.

mai*_*n-- 7

看看你在做什么:

jbyte* a = env->GetByteArrayElements(file1,&isCopy);
Run Code Online (Sandbox Code Playgroud)

a现在指向存储字符串的字节内容的存储器地址.我们假设该文件包含字符串"Hello world".在UTF-8编码中,那将是:

48 65 6c 6c 6f 20 77 6f 72 6c 64

char* b = (char*)a;
Run Code Online (Sandbox Code Playgroud)

b现在指向那个记忆区域.它是一个char指针,因此您可能希望将其用作C字符串.但是,这不起作用.C字符串定义为一些字节,以零字节结尾.现在查看那里,你会发现在这个字符串的末尾没有零字节.

printf("%s\n",b);
Run Code Online (Sandbox Code Playgroud)

这里是.您正在过字符指针,以printf作为%s它告诉printf它的C字符串.但是,它不是C字符串,但printf仍会尝试打印所有字符,直到达到零字节.所以你所看到dsa的实际上是字节数组结束后内存中的字节,直到(巧合)为零字节.您可以通过将字节复制到比字节数组长一个字节的缓冲区然后将最后一个元素设置为零来解决此问题.

更新:

您可以创建更大的缓冲区并附加如下所示的空字节:

int textLength = strlen((const char*)a);
char* b = malloc(textLength + 1);
memcpy(b, a, textLength);
b[textLength] = '\0';
Run Code Online (Sandbox Code Playgroud)

Now b是一个有效的以null结尾的C字符串.另外,不要忘记打电话给ReleaseByteArrayElements.你可以在memcpy电话结束后立即这样做.