程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> JNI Windows平台(包、解決中文路徑亂碼、數組傳入、傳出)

JNI Windows平台(包、解決中文路徑亂碼、數組傳入、傳出)

編輯:關於JAVA
 

以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

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved