C ++中的JNI将文件读取到jbyteArray

Posted

技术标签:

【中文标题】C ++中的JNI将文件读取到jbyteArray【英文标题】:JNI in C++ to read file to jbyteArray 【发布时间】:2012-10-12 07:34:40 【问题描述】:

我正在 UNIX 中编写一个 C++ 程序来生成一个共享库,该库将使用 JNI 在 java 中调用。这个 C++ 程序必须读取 UNIX 框中的文件,然后必须将其转换为 jbyteArray(JNI 数据类型),以便 JAVA 可以使用它。

我将 C++ 中的文件读入char*,但无法转换为jbyteArray。请帮忙。

代码如下::

#include <iostream>
#include <fstream>
#include <stdio.h>
#include "com_sp_dll_NativeMethods.h"   // this header file was generated by java

using namespace std;

JNIEXPORT void JNICALL Java_HelloWorld_displayMessage(JNIEnv *env, jobject obj)

    printf("Hello World!\n");


JNIEXPORT jbyteArray JNICALL Java_com_sp_dll_NativeMethods_getFile(JNIEnv *env, jobject obj)

    ifstream fl("/home/rkannan/myFile.txt");
    fl.seekg(0, ios::end );
    size_t len = fl.tellg();
    char *ret = new char[len];
    fl.seekg(0, ios::beg);
    fl.read(ret, len);
    fl.close();

    int i = 0;
    jbyte *a1 = null;

    while(ret[i] != '\0')
        cout<<ret[i];
        al[i] = ret[i];
        i++;
    

    jbyteArray result = env->NewByteArray( len);
    env->SetByteArrayRegion( result, 0, len, (const jbyte*) ret );
    delete[] ret;
    return result;
  

报错如下

bash-3.00$ g++ -I /usr/jdk/instances/jdk1.5.0/include -I /usr/jdk/instances/jdk1.5.0/include/solaris -o libSample.so -shared com_sp_dll_NativeMethods.cpp
        Text relocation remains                         referenced
            against symbol                  offset      in file
        std::__ioinit                       0x550       /var/tmp//ccKCiEKq.o
        std::__ioinit                       0x554       /var/tmp//ccKCiEKq.o
        std::__ioinit                       0x588       /var/tmp//ccKCiEKq.o
        std::__ioinit                       0x58c       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x204       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x208       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x244       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x248       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x2f4       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x2f8       /var/tmp//ccKCiEKq.o
        std::fpos<__mbstate_t>::operator long long() const0x348         /var/tmp//ccKCiEKq.o
        std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)0x400             /var/tmp//ccKCiEKq.o
        std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)0x2cc      /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::is_open()0x260      /var/tmp//ccKCiEKq.o
        std::basic_istream<char, std::char_traits<char> >::read(char*, int)0x39c        /var/tmp//ccKCiEKq.o
        JNIEnv_::SetByteArrayRegion(_jbyteArray*, int, int, signed char const*)0x468            /var/tmp//ccKCiEKq.o
        operator new[](unsigned int)        0x364       /var/tmp//ccKCiEKq.o
        std::basic_istream<char, std::char_traits<char> >::seekg(long long, std::_Ios_Seekdir)0x31c             /var/tmp//ccKCiEKq.o
        std::basic_istream<char, std::char_traits<char> >::seekg(long long, std::_Ios_Seekdir)0x384             /var/tmp//ccKCiEKq.o
        std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >&, char*)0x2b4       /var/tmp//ccKCiEKq.o
        printf                              0x20c       /var/tmp//ccKCiEKq.o
        JNIEnv_::NewByteArray(int)          0x444       /var/tmp//ccKCiEKq.o
        std::ios_base::Init::Init()         0x558       /var/tmp//ccKCiEKq.o
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::size() const0x14        /var/tmp//ccKCiEKq.o
        std::cout                           0x2c0       /var/tmp//ccKCiEKq.o
        std::cout                           0x2c4       /var/tmp//ccKCiEKq.o
        std::cout                           0x3f4       /var/tmp//ccKCiEKq.o
        std::cout                           0x3f8       /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream()0x234       /var/tmp//ccKCiEKq.o
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator[](unsigned int) const0x9c              /var/tmp//ccKCiEKq.o
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator[](unsigned int) const0x128             /var/tmp//ccKCiEKq.o
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator[](unsigned int) const0x184             /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::open(char const*, std::_Ios_Openmode)0x250          /var/tmp//ccKCiEKq.o
        std::ios_base::Init::~Init()        0x590       /var/tmp//ccKCiEKq.o
        std::basic_ios<char, std::char_traits<char> >::eof() const0x288         /var/tmp//ccKCiEKq.o
        unsigned int const& std::min<unsigned int>(unsigned int const&, unsigned int const&)0x44        /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()0x49c      /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()0x4ac      /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()0x4d4      /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()0x4f8      /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::close()0x2e4        /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::close()0x3ac        /var/tmp//ccKCiEKq.o
           std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(char const*,     std::_Ios_Openmode)0x300        /var/tmp//ccKCiEKq.o
            operator delete[](void*)            0x484       /var/tmp//ccKCiEKq.o
           std::basic_istream<char, std::char_traits<char> >::tellg()       0x334         /var/tmp//ccKCiEKq.o
            _Unwind_Resume                      0x508       /var/tmp//ccKCiEKq.o
            ld: fatal: relocations remain against allocatable but non-writable sections
            collect2: ld returned 1 exit status

【问题讨论】:

JNI: passing bytes from c++ to java的可能重复 你可能想用 JavaCPP 再试一次,它比原始 JNI 更容易在 IMO 上工作 为什么?您可以在 Java 中完成所有这些工作。没有什么可以得到的。并不是说您应该首先将整个文件读入内存。 【参考方案1】:

您似乎没有为数组设置任何字节数据。事实上,由于 jbyte 是类型定义为 char,您可以直接在 setByteArrayRegion 中设置 char 数组,如下所示:

env->SetByteArrayRegion( result, 0, 100, ret );

编辑:另外,假设 al[i] 应该是 a1[i] 你正在做一些非常危险的事情,因为你没有为 a1 分配空间。基本上按照我上面的建议进行操作意味着您可以摆脱整个循环。完成后不要忘记删除 C++ 数组(即复制到 jByteArray 中)!

JNIEXPORT jbyteArray JNICALL Java_com_sp_dll_NativeMethods_getFile
       (JNIEnv *env, jobject obj)

        ifstream fl("/home/rkannan/myFile.txt");
        fl.seekg(0, ios::end );
        size_t len = fl.tellg();
        char *ret = new char[len];
        fl.seekg(0, ios::beg);
        fl.read(ret, len);
        fl.close();

        jbyteArray result = env->NewByteArray( len);
        env->SetByteArrayRegion( result, 0, len, (const jbyte*)ret );

        delete[] ret;

        return result;

【讨论】:

+1;我还建议在创建和设置字节数组时使用len 变量,而不是固定值100 您可以使用 std::string 或 std::vector 作为临时容器。 谢谢 Goz 和其他人。错误:来自char*' to const jbyte*' com_sp_dll_NativeMethods.cpp 的无效转换:: 错误:初始化 `void 的参数 4 我收到了上述错误。对不起,害虫。我不熟悉 C++ 和 JNI 数据类型 @Renga:然后编辑您的原始问题并发布错误。

以上是关于C ++中的JNI将文件读取到jbyteArray的主要内容,如果未能解决你的问题,请参考以下文章

C语言中如何将文件中的数据读取到链表中

C ++将文本文件中的数字读取到数组中

将数字从文本文件读取到 C 中用户定义函数中的数组

如何将 dos 命令的输出读取/重定向到 C/C++ 中的程序变量?

c语言中从文件中按行读取字符串,并进行相应操作。

c语言读取文件然后保存到数组中