You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求Android NDK示例:通过JNI将Java读取的文件传入C/C++

JNI传递文件数据到C/C++的实现示例(基于hello-jni扩展)

一、两种常见的文件传递方案

1. 传递文件路径,让C/C++直接读取

这种方式无需在Java层预读文件内容,直接传递路径给JNI,由C/C++侧打开文件读取,效率更高。

Java代码(扩展hello-jni的MainActivity)

public class MainActivity extends AppCompatActivity {
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 将assets中的示例文件复制到本地存储,获取路径
        String filePath = copyAssetToLocal("sample.pdf");
        if (filePath != null) {
            String processResult = processFileFromPath(filePath);
            Log.d("JNI_FILE", "处理结果: " + processResult);
        }
    }

    private String copyAssetToLocal(String fileName) {
        try {
            File localFile = new File(getFilesDir(), fileName);
            if (!localFile.exists()) {
                InputStream is = getAssets().open(fileName);
                FileOutputStream fos = new FileOutputStream(localFile);
                byte[] buffer = new byte[1024];
                int len;
                while ((len = is.read(buffer)) != -1) {
                    fos.write(buffer, 0, len);
                }
                is.close();
                fos.close();
            }
            return localFile.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    // JNI方法声明
    public native String processFileFromPath(String filePath);
}

JNI代码(native-lib.cpp)

#include <jni.h>
#include <string>
#include <fstream>
#include <sstream>

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_hellojni_MainActivity_processFileFromPath(
        JNIEnv* env,
        jobject,
        jstring filePath) {
    // 转换Java字符串为C字符串
    const char* path = env->GetStringUTFChars(filePath, nullptr);
    if (path == nullptr) {
        return env->NewStringUTF("路径转换失败");
    }

    // 打开并读取文件
    std::ifstream file(path);
    if (!file.is_open()) {
        env->ReleaseStringUTFChars(filePath, path);
        return env->NewStringUTF("文件打开失败");
    }

    std::stringstream buffer;
    buffer << file.rdbuf();
    std::string fileContent = buffer.str();
    file.close();

    env->ReleaseStringUTFChars(filePath, path);
    // 返回文件大小(实际可替换为PDF/Office解析逻辑)
    std::string result = "文件大小: " + std::to_string(fileContent.size()) + " 字节";
    return env->NewStringUTF(result.c_str());
}

2. 传递文件字节数组到C/C++

如果已经在Java层读取了文件内容,可以直接将字节数组传给JNI处理。

Java代码新增部分

public native String processFileFromBytes(byte[] fileBytes);

// 在onCreate中调用
byte[] fileBytes = readAssetToBytes("sample.docx");
if (fileBytes != null) {
    String result = processFileFromBytes(fileBytes);
    Log.d("JNI_FILE", "字节数组处理结果: " + result);
}

// 读取assets文件为字节数组
private byte[] readAssetToBytes(String fileName) {
    try {
        InputStream is = getAssets().open(fileName);
        byte[] bytes = new byte[is.available()];
        is.read(bytes);
        is.close();
        return bytes;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

JNI代码新增函数

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_hellojni_MainActivity_processFileFromBytes(
        JNIEnv* env,
        jobject,
        jbyteArray fileBytes) {
    jsize byteLen = env->GetArrayLength(fileBytes);
    jbyte* bytes = env->GetByteArrayElements(fileBytes, nullptr);
    if (bytes == nullptr) {
        return env->NewStringUTF("字节数组获取失败");
    }

    // 直接操作字节数组(可传给PDF/Office解析库处理)
    std::string result = "接收字节数组长度: " + std::to_string(byteLen) + " 字节";

    env->ReleaseByteArrayElements(fileBytes, bytes, 0);
    return env->NewStringUTF(result.c_str());
}

二、C/C++解析PDF/Office文件的扩展方向

要解析PDF或docx文件,需集成对应的C/C++库:

  • PDF解析:可使用MuPDF、Poppler等轻量级库,将库编译为Android兼容的.so文件后,在JNI代码中调用其API解析文件路径或字节数组。
  • docx解析:docx本质是ZIP包,可使用minizip库解压后解析内部XML结构,或使用专门的文档解析库。

伪代码示例(基于MuPDF解析PDF)

#include <mupdf/fitz.h>

std::string parsePdfPageCount(const char* path) {
    fz_context* ctx = fz_new_context(nullptr, nullptr, FZ_STORE_UNLIMITED);
    if (!ctx) return "MuPDF初始化失败";

    fz_try(ctx) {
        fz_register_document_handlers(ctx);
        fz_document* doc = fz_open_document(ctx, path);
        int pageCount = fz_count_pages(ctx, doc);
        fz_close_document(ctx, doc);
        fz_drop_context(ctx);
        return "PDF页数: " + std::to_string(pageCount);
    } fz_catch(ctx) {
        fz_drop_context(ctx);
        return "PDF解析失败";
    }
}

// 在processFileFromPath中替换原有逻辑为:
std::string result = parsePdfPageCount(path);

内容的提问来源于stack exchange,提问作者p2511

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 00:25:22