返回首页
当前位置: 主页 > 编程语言 > JAVA教程 >

JNI Windows平台(包、解决中文路径乱码、数组传入、传出)

时间:2016-11-11 22:13来源:电脑教程学习网 www.etwiki.cn 编辑:admin

以C++实现读写文件,Java调用为例。包括中文路径的传递和数组的传入传出。

1.环境准备

保证Java代码能够正确编译运行(安装JDK,正确配置环境变量)

保证C++代码能够正确编译(安装VS或者Eclipse等)

文件目录结构

E:\JNI\com\yiluboke\zxy\WriteReadJ.java

E:\JNI\WriteReadC++

2.编写java代码(WriteReadJ.java)
package com.yiluboke.zxy;
class WriteReadJ {
// 函数功能:将内存数据写入文件
// 传入参数:bData 内存数据
// iLen 内存数据的长度
// strFilePath 文件路径
// 返回参数:
public native int writeFile(byte bData[], String strFilePath);
// 函数功能:文件是否正确读取
// 传入参数:strFilePath 文件路径
// 返回参数:0 正确
public native int readFilePre(String strFilePath);
// 函数功能:读取文件
// 传入参数:strFilePath 文件路径
// 返回参数:返回文件的内容
public native byte[] readFile(String strFilePath);
static {
// 调用动态链接库
System.loadLibrary("jniwritereadfile");
}
public static void main(String[] args){
WriteReadJ demo = new WriteReadJ();
byte[] bytes = new byte[3];
bytes[0] = '7';
bytes[1] = '8';
bytes[2] = 'h';
int nResult = 0;
String strFilePathName = "E:\\JNI\\新建文本文档.txt";
try {
strFilePathName = new String(strFilePathName.getBytes(),"gb2312");
} catch (Exception ex) {
System.out.println(ex);
return;
}
nResult = demo.writeFile(bytes, strFilePathName);
if (nResult == 0) {
System.out.println("写入成功");
} else {
System.out.println("写入失败错误码:" + nResult);
}
nResult = demo.readFilePre(strFilePathName);
if (nResult == 0) {
System.out.println("读取成功");
byte[] fileReadData = demo.readFile(strFilePathName);
System.out.println("获取数据如下: ");
for (int index = 0; index < fileReadData.length; index++) {
System.out.println(fileReadData[index]);
}
} else {
System.out.println("读取失败错误码:" + nResult);
}
}
}

3.编译Java代码,生成class文件

在E:\JNI目录下

javac E:\JNI\com\yiluboke\zxy\WriteReadJ.java,在该java文件所在目录下生成WriteReadJ.class文件。

 


4.生成.h文件

在E:\JNI目录下

javah -jni com.yiluboke.zxy.WriteReadJ,在当前目录下生成com_yiluboke_zxy_WriteReadJ.h文件

 


5.编写C++代码,并编译成dll文件

writeReadDo.h
#ifndef __WRITEREADDO__H
#define __WRITEREADDO__H
typedef unsigned char BYTE;
const int MAXLEN = 1024;
extern BYTE gbData[MAXLEN];
extern int gbLen;
//函数功能:将内存数据写入文件
//传入参数:bData 内存数据
// iLen 内存数据的长度
// strFilePath 文件路径
//返回参数: 0 成功 非0参见错误码
int writeFile(BYTE bData[],int iLen,const char* strFilePath);
//函数功能:读取写入的数据
//传入参数:strFilePath 文件路径
//返回参数:0 成功 非0参见错误码
int readFile(const char* strFilePath);
#endif

writeReadDo.cpp

#include "writeReadDo.h"
#include "fstream"
using namespace std;
int writeFile(BYTE bData[],int iLen,const char* strFilePath)
{
fstream fOut(strFilePath, ios::out | ios::binary);
if(!fOut)
return -1;
fOut.write((const char*)&bData[0],iLen);
fOut.close();
return 0;
}
BYTE gbData[MAXLEN] = {};
int gbLen = 0;
int readFile(const char* strFilePath)
{
ifstream fIn(strFilePath,ios::in | ios::binary);
if(!fIn)
return -1;
fIn.seekg(0,ios_base::end);
int bCount = fIn.tellg();
fIn.seekg(0 , ios::beg);
if (bCount < MAXLEN)
{
gbLen = bCount;
fIn.read((char*)&gbData[0], bCount);
}
else
{
gbLen = MAXLEN;
fIn.read((char*)&gbData[0], MAXLEN);
}
fIn.close();
return 0;
}

com_yiluboke_zxy_WriteReadJ.cpp

#include "com_yiluboke_zxy_WriteReadJ.h"
#include "writeReadDo.h"
#include
static const char* encodeMode = "GB2312";
char* Jstring2CStr(JNIEnv* env, jstring jstr, int* charLen)
{
char* chRet = NULL;
jclass classStr = env->FindClass("java/lang/String");
jstring jstrEncode = env->NewStringUTF(encodeMode);
jmethodID methodId = env->GetMethodID(classStr, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray bArray = (jbyteArray)env->CallObjectMethod(jstr, methodId, jstrEncode);
jsize bArrayLen = env->GetArrayLength(bArray);
*charLen = bArrayLen + 1;
jbyte* pByte = env->GetByteArrayElements(bArray,JNI_FALSE);
if(bArrayLen > 0)
{
chRet =new char[bArrayLen + 1];
memcpy(chRet,pByte,bArrayLen);
chRet[bArrayLen]=0;
}
env->ReleaseByteArrayElements(bArray,pByte,0);
return chRet;
}
JNIEXPORT jint JNICALL Java_com_yiluboke_zxy_WriteReadJ_writeFile
(JNIEnv *env, jobject, jbyteArray bData, jstring jstrFilePath)
{
int chlen = 0;
const char* chFilePath = Jstring2CStr( env, jstrFilePath, &chlen) ;//jstringToWindows( env, jstrFilePath ); //(*env).GetStringUTFChars(jstrFilePath, 0); //修改文件名乱码
jbyte *jData = (jbyte*)env->GetByteArrayElements(bData, 0);
jsize jSize = env->GetArrayLength(bData);
BYTE* bytearr = (BYTE*)jData;
int len = (int)jSize;
int nResult = writeFile(bytearr,len, chFilePath);
//(*env).ReleaseStringUTFChars(jstrFilePath, chFilePath);
if(chFilePath)
{
delete [] chFilePath;
chFilePath = NULL;
}
return nResult;
}
JNIEXPORT jint JNICALL Java_com_yiluboke_zxy_WriteReadJ_readFilePre
(JNIEnv *env, jobject, jstring jstrFilePath)
{
int chlen = 0;
const char* chFilePath =Jstring2CStr( env, jstrFilePath, &chlen) ;// (*env).GetStringUTFChars(jstrFilePath, 0);//jstringToWindows(env,jstrFilePath);
int nResult = readFile(chFilePath);
//(*env).ReleaseStringUTFChars(jstrFilePath, chFilePath);
if(chFilePath)
{
delete [] chFilePath;
chFilePath = NULL;
}
return nResult;
}
JNIEXPORT jbyteArray JNICALL Java_com_yiluboke_zxy_WriteReadJ_readFile
(JNIEnv *env, jobject, jstring)
{
jbyte *by = (jbyte*)gbData;
int len = gbLen;
jbyteArray jarray = (*env).NewByteArray(len);
(*env).SetByteArrayRegion(jarray, 0, len, by);
return jarray;
}

 

6.运行java文件

在E:\JNI目录下

java com.yiluboke.zxy.WriteReadJ

 


7.完整Demo下载

百度网盘地址:http://pan.baidu.com/s/1bot3wyr

本文采 用的JDK是 64位版本1.8.0_60。

E:\JNI>java -version

java version "1.8.0_60"

Java(TM) SE Runtime Environment (build 1.8.0_60-b27)

Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

编译错误:

如果遇到编译错误jni.h错误,替换工程中jni.h及jni.md.h为电脑中JDK安装路径中的jni.h及jni_md.h即可。

运行错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: E:\JNI\jniwritereadfile.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform

dll编译成:64位dll

顶一下
(0)
0%
踩一下
(0)
0%
标签(Tag):java Java编程技术 编程技术
------分隔线----------------------------
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
验证码:点击我更换图片
推荐内容