本文實(shí)例講述了Android在JNI中使用ByteBuffer的方法。分享給大家供大家參考。具體如下:
一、ByteBuffer 定義
在NIO中,數(shù)據(jù)的讀寫操作始終是與緩沖區(qū)相關(guān)聯(lián)的(讀取時信道(SocketChannel)將數(shù)據(jù)讀入緩沖區(qū),寫入時首先要將發(fā)送的數(shù)據(jù)按順序填入緩沖區(qū))
緩沖區(qū)是定長的,基本上它只是一個列表,它的所有元素都是基本數(shù)據(jù)類型。ByteBuffer是最常用的緩沖區(qū),它提供了讀寫其他數(shù)據(jù)類型的方法,且信道的讀寫方法只接收ByteBuffer。
ByteBuffer有以下幾種常見屬性:
mark:初始值為-1,標(biāo)記索引地點(diǎn);
position:初始值為0,索引下標(biāo);
limit:最好定義成bytebuffer的長度,即允許可讀空間長度;
capacity:緩沖區(qū)能容納的數(shù)據(jù)元素的最大數(shù)量,創(chuàng)建之后無法被改變;
二、ByteBuffer使用
1. 創(chuàng)建ByteBuffer
① 使用allocate()創(chuàng)建:
1
2
|
ByteBuffer buf = ByteBuffer.allocate(length); //length表示buf的長度 |
② 使用數(shù)組創(chuàng)建:
1
2
|
ByteBuffer buf = ByteBuffer.wrap(byteArray); //byteArray表示一個數(shù)組 |
2. 回繞緩沖區(qū)
1
|
buf.flip(); |
這個方法用來將緩沖區(qū)準(zhǔn)備為數(shù)據(jù)傳出狀態(tài),執(zhí)行以上方法后,輸出通道會從數(shù)據(jù)的開頭而不是末尾開始.回繞保持緩沖區(qū)中的數(shù)據(jù)不變,只是準(zhǔn)備寫入而不是讀取。
3. 清除緩沖區(qū)
1
|
buf.clear(); |
這個方法實(shí)際上也不會改變緩沖區(qū)的數(shù)據(jù),而只是簡單的重置了緩沖區(qū)的主要索引值.不必為了每次讀寫都創(chuàng)建新的緩沖區(qū),那樣做會降低性能.相反,要重用現(xiàn)在的緩沖區(qū),在再次讀取之前要清除緩沖區(qū)。
4. ByteBuffer與byte[]交互
1
2
3
4
5
6
7
|
byte [] bytearray = new byte [ 10 ]; ByteBuffer buf = ByteBuffer.wrap(bytearray); //將數(shù)組寫入buf bytearray = new byte [buf.remaining()]; buf.get(bytearray, 0 ,bytearray.length()); //將數(shù)據(jù)讀到數(shù)組中 bytearray = new byte [buf.capacity()]; |
三、ByteBuffer與JNI交互
在Java1.4版本中引入的JNI有三個函數(shù)可以用于NIO的直接緩沖器。一個直接字節(jié)緩沖器是一個用于字節(jié)數(shù)據(jù)的容器,Java將盡力在它上面執(zhí)行本機(jī)I/O操作。JNI定義了三個用于NIO操作的函數(shù)。
基于到存儲器地址的指針以及存儲器長度(容量),函數(shù)分配并且返回一個新的Java.nio.ByteBuffer。如果函數(shù)沒有針對當(dāng)前Java虛擬機(jī)實(shí)現(xiàn),則返回NULL,或者拋出一個異常。如果沒有存儲器可用,則將會拋出一個OutOfMemoryException。
1
|
jobject NewDirectByteBuffer( void * address, jlong capacity); |
GetDirectBufferAddress函數(shù)返回一個指向被傳入的java.nio.ByteBuffer對象的地址指針。如果函數(shù)尚未針對當(dāng)前虛擬機(jī)實(shí)現(xiàn),或者如果buf不是java.nio.ByteBuffer的一個對象,又或者存儲器區(qū)尚未定義,則都將返回NULL。
1
|
void * GetDirectBufferAddress(jobject buf); |
GetDirectBufferCapacity函數(shù)返回被傳入的java.nio.ByteBuffer對象的容量(以字節(jié)計數(shù))。如果函數(shù)沒有針對當(dāng)前環(huán)境實(shí)現(xiàn),或者如果buf不是java.nio.ByteBuffer類型的對象返回-1。
1
|
jlong GetDirectBufferCapacity(jobject buf); |
1. Jni中調(diào)用
Java層:
1
|
public final int processData(ByteBuffer data); |
Native 接口:
1
|
private native long native_Process(ByteBuffer data); |
Jni層:
1
|
static jlong native_Process(JNIEnv *env,jobject obj,jobject data); |
注意ByteBuffer在JNI層中的簽名:Ljava/nio/ByteBuffer;
2. 示例(C++):
1
2
3
4
5
|
jclass cls = env->GetObjectClass(obj); jfieldID fid = env->GetFieldID(cls, "data" , "Ljava/nio/ByteBuffer;" ); jobject bar = env->GetObjectField(obj, fid); pImageData->data= (MByte*)env->GetDirectBufferAddress(bar); //data是結(jié)構(gòu)體pImageData中的byte[]; |
希望本文所述對大家的Android程序設(shè)計有所幫助。