Android JNI層實現檔案的read、write與seek操作
轉自:http://blog.csdn.net/conowen/article/details/7525837
/********************************************************************************************
* author:[email protected]大鐘
* E-mail:
* http://blog.csdn.net/conowen
* 注:本文為原創,僅作為學習交流使用,轉載請標明作者及出處。
********************************************************************************************/
1、
在JNI層實現檔案的讀寫操作的話,就要使用到linux的讀寫函數了。
2、開啟檔案
- int open( constchar *pathname,int flags, int mode);
返回值:為一個檔案控制代碼(fd),供read、write等操作。
引數:
pathname: 開啟的檔案所在路徑字串。如
- String filename = "/sdcard/test.txt"
flags: 檔案開啟的方式
flag之間可以作“與”運算,如
- open(filename, O_CREAT | O_RDWR,mode);
常用flags:
O_RDONLY 以只讀方式開啟檔案
O_WRONLY 以只寫方式開啟檔案
O_RDWR 以可讀寫方式開啟檔案。上述三種旗標是互斥的,也就是不可同時使用,但可與下列的旗標利用OR(|)運算子組合。
O_CREAT 若欲開啟的檔案不存在則自動建立該檔案。
O_TRUNC 若檔案存在並且以可寫的方式開啟時,此標誌位會令檔案長度重新清為0,也就是說檔案內容清空。
O_APPEND 當讀寫檔案時會從檔案尾開始移動,也就是所寫入的資料會以附加的方式加入到檔案後面。
O_NONBLOCK 以不可阻斷的方式開啟檔案,也就是無論有無資料讀取或等待,都會立即返回程序之中。
O_SYNC 以同步的方式開啟檔案。
O_NOFOLLOW 如果引數pathname所指的檔案為一符號連線,則會令開啟檔案失敗。
O_DIRECTORY 如果引數pathname所指的檔案並非為一目錄,則會令開啟檔案失敗。
mode: 檔案儲存許可權
S_IRWXU00700 許可權,代表該檔案所有者具有可讀、可寫及可執行的許可權。
S_IRUSR 或S_IREAD,00400許可權,代表該檔案所有者具有可讀取的許可權。
S_IWUSR 或S_IWRITE,00200 許可權,代表該檔案所有者具有可寫入的許可權。
S_IXUSR 或S_IEXEC,00100 許可權,代表該檔案所有者具有可執行的許可權。
S_IRWXG 00070許可權,代表該檔案使用者組具有可讀、可寫及可執行的許可權。
S_IRGRP 00040 許可權,代表該檔案使用者組具有可讀的許可權。
S_IWGRP 00020許可權,代表該檔案使用者組具有可寫入的許可權。
S_IXGRP 00010 許可權,代表該檔案使用者組具有可執行的許可權。
S_IRWXO 00007許可權,代表其他使用者具有可讀、可寫及可執行的許可權。
S_IROTH 00004 許可權,代表其他使用者具有可讀的許可權
S_IWOTH 00002許可權,代表其他使用者具有可寫入的許可權。
S_IXOTH 00001 許可權,代表其他使用者具有可執行的許可權。
3、檔案的讀(read)操作
- int read(int fd, unsigned char *buf, int size);
返回值:返回實際讀取到的位元組數,如果返回0,表示已到達檔案尾或是無可讀取的資料,此外檔案讀寫位置會隨讀取到的位元組移動。
引數:
fd:表示檔案控制代碼,是由open函式得到
buf:read()函式會把fd 所指的檔案傳送count個位元組到buf指標所指的記憶體中
size:要讀取的位元組數
4、寫入操作
- int write (int fd, const unsigned char *buf, int size);
返回值 :如果成功write(),就會返回實際寫入的位元組數。當有錯誤發生時則返回-1
引數:
fd:同上
buf:將要寫入到檔案裡面的內容。
size:要寫入的位元組數
5、跳轉操作
- int64_t seek(int fd, int64_t pos, int whence)
返回值:成功時則返回目前的讀寫位置,也就是距離檔案開頭多少個位元組,若有錯誤則返回-1。
引數:
fd:同上
pos:跳轉的相對量,可正可負,表示相對位置的前後關係
whence:跳轉的方向,whence取值如下所示
- int SEEK_SET = 0;//將讀寫位置指向檔案頭後再增加offset個位移量。
- int SEEK_CUR = 1;//以目前的讀寫位置往後增加offset個位移量。
- int EEK_END = 2;//將讀寫位置指向檔案尾後再增加offset個位移量。
注:當size引數=0;whence = SEEK_END;時返回值即為檔案大小。
6、關閉操作
- int close(int fd)
7、簡單示例
效果圖:
7.1、JNI程式碼:(有JNI_onLoad函式)
- //fs.c
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <stdlib.h>
- #include <fcntl.h>
- int file_open(constchar *filename, int flags)
- {
- int fd;
- fd = open(filename, flags, 0666);
- if (fd == -1)
- return -1;
- return fd;
- }
- int file_read(int fd, unsigned char *buf, int size)
- {
- return read(fd, buf, size);
- }
- int file_write(int fd, const unsigned char *buf, int size)
- {
- return write(fd, buf, size);
- }
- int64_t file_seek(int fd, int64_t pos, int whence)
- {
- if (whence == 0x10000) {
- struct stat st;
- int ret = fstat(fd, &st);
- return ret < 0 ? -1 : st.st_size;
- }
- return lseek(fd, pos, whence);
- }
- int file_close(int fd)
- {
- return close(fd);
- }
- //jni.c
- #define TAG "fs_jni"
- #include <android/log.h>
- #include "jniUtils.h"
- staticconstchar* const kClassPathName = "com/conowen/fs/FsActivity";
- jint
- Java_com_conowen_fs_FsActivity_NativeFileOpen( JNIEnv* env, jobject thiz,jstring filename,jint flags ){
- constchar *filename_char = (*env)->GetStringUTFChars(env,filename, NULL);
- return file_open(filename_char, flags);
- }
- jint
- Java_com_conowen_fs_FsActivity_NativeFileRead(JNIEnv* env, jobject thiz,int fd,jbyteArray buf,jint size){
- unsigned char *buf_char = (char*)((*env)->GetByteArrayElements(env,buf, NULL));
- return file_read(fd, buf_char, size);
- }
- jint
- Java_com_conowen_fs_FsActivity_NativeFileWrite(JNIEnv* env, jobject thiz,int fd,jbyteArray buf,jint size){
- unsigned char *buf_char = (char*)((*env)->GetByteArrayElements(env,buf, NULL));
- return file_write(fd, buf_char, size);
- }
- jlong
- Java_com_conowen_fs_FsActivity_NativeFileSeek(JNIEnv* env, jobject thiz,int fd,jlong Offset,jint whence){
- return file_seek(fd, Offset, whence);
- }
- jint
- Java_com_conowen_fs_FsActivity_NativeFileClose(JNIEnv* env, jobject thiz,int fd){
- return file_close(fd);
- }
- /******************************JNI registration.************************************/
- static JNINativeMethod gMethods[] = {
- {"NativeFileOpen", "(Ljava/lang/String;I)I", (void *)Java_com_conowen_fs_FsActivity_NativeFileOpen},
- {"NativeFileRead", "(I[BI)I", (void *)Java_com_conowen_fs_FsActivity_NativeFileRead},
- {"NativeFileWrite", "(I[BI)I", (void *)Java_com_conowen_fs_FsActivity_NativeFileWrite},
- {"NativeFileSeek", "(IJI)J", (void *)Java_com_conowen_fs_FsActivity_NativeFileSeek},
- {"NativeFileClose", "(I)I", (void *)Java_com_conowen_fs_FsActivity_NativeFileClose},
- };
- int register_com_conowen_fs_FsActivity(JNIEnv *env) {
- return jniRegisterNativeMethods(env, kClassPathName, gMethods, sizeof(gMethods) / sizeof(gMethods[0]));
- }
- //jniUtils.h
- #ifndef _JNI_UTILS_H_
- #define _JNI_UTILS_H_
- #include <stdlib.h>
- #include <jni.h>
- #ifdef __cplusplus
- extern"C"
- {
- #endif
- int jniThrowException(JNIEnv* env, constchar* className, constchar* msg);
- JNIEnv* getJNIEnv();
- int jniRegisterNativeMethods(JNIEnv* env,
- constchar* className,
- const JNINativeMethod* gMethods,
- int numMethods);
- #ifdef __cplusplus
- }
- #endif
- #endif /* _JNI_UTILS_H_ */
- //onLoad.cpp
- #define TAG "fs_onLoad"
- #include <android/log.h>
- #include "jniUtils.h"
- extern"C" {
- externint register_com_conowen_fs_FsActivity(JNIEnv *env);
- }
- static JavaVM *sVm;
- /*
- * Throw an exception with the specified class and an optional message.
- */
- int jniThrowException(JNIEnv* env, constchar* className, constchar* msg) {
- jclass exceptionClass = env->FindClass(className);
- if (exceptionClass == NULL) {
- __android_log_print(ANDROID_LOG_ERROR,
- TAG,
- "Unable to find exception class %s",
- className);
- return -1;
- }
- if (env->ThrowNew(exceptionClass, msg) != JNI_OK) {
- __android_log_print(ANDROID_LOG_ERROR,
- TAG,
- "Failed throwing '%s' '%s'",
- className, msg);
- }
- return 0;
- }
- JNIEnv* getJNIEnv() {
- JNIEnv* env = NULL;
- if (sVm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
- __android_log_print(ANDROID_LOG_ERROR,
- TAG,
- "Failed to obtain JNIEnv");
- return NULL;
- }
- return env;
- }
- /*
- * Register native JNI-callable methods.
- *
- * "className" looks like "java/lang/String".
- */
- int jniRegisterNativeMethods(JNIEnv* env,
- constchar* className,
- const JNINativeMethod* gMethods,
- int numMethods)
- {
- jclass clazz;
- __android_log_print(ANDROID_LOG_INFO, TAG, "Registering %s natives\n", className);
- clazz = env->FindClass(className);
- if (clazz == NULL) {
- __android_log_print(ANDROID_LOG_ERROR, TAG, "Native registration unable to find class '%s'\n", className);
- return -1;
- }
- if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
- __android_log_print(ANDROID_LOG_ERROR, TAG, "RegisterNatives failed for '%s'\n", className);
- return -1;
- }
- return 0;
- }
- //Dalvik虛擬機器載入C庫時,第一件事是呼叫JNI_OnLoad()函式
- jint JNI_OnLoad(JavaVM* vm, void* reserved) {
- JNIEnv* env = NULL;
- jint result = JNI_ERR;
- sVm = vm;
- if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
- __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv failed!");
- return result;
- }
- __android_log_print(ANDROID_LOG_INFO, TAG, "loading . . .");
- if(register_com_conowen_fs_FsActivity(env) != JNI_OK) {
- __android_log_print(ANDROID_LOG_ERROR, TAG, "can't load register_com_conowen_fs_FsActivity");
- goto end;
- }
- __android_log_print(ANDROID_LOG_INFO, TAG, "loaded");
- result = JNI_VERSION_1_4;
- end:
- return result;
- }
7.2、Android.mk檔案
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_MODULE := fs
- LOCAL_SRC_FILES := fs.c jni.c onLoad.cpp
- LOCAL_LDLIBS += -llog
- include $(BUILD_SHARED_LIBRARY)
7.3、java層程式碼
- /* author:conowen
- * data:2012.5.1
- * e-mail:[email protected]
- */
- package com.conowen.fs;
- import java.io.UnsupportedEncodingException;
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.TextView;
- publicclass FsActivity extends Activity {
- String filename = "/sdcard/test.txt";
- EditText writestrET;
- Button writeBT;
- Button readBT;
- Button seekBT;
- TextView readTV;
- String writeStr;
- byte[] buf_write;
- byte[] buf_read;
- int fd;
- int O_ACCMODE = 0003;
- int O_RDONLY = 00;
- int O_WRONLY = 01;
- int O_RDWR = 02;
- int O_CREAT = 0100; /* not fcntl */
- int O_EXCL = 0200; /* not fcntl */
- int O_NOCTTY = 0400; /* not fcntl */
- int O_TRUNC = 01000; /* not fcntl */
- int O_APPEND = 02000;
- int O_NONBLOCK = 04000;
- int O_NDELAY = O_NONBLOCK;
- int O_SYNC = 010000;
- int O_FSYNC = O_SYNC;
- int O_ASYNC = 020000;
- int SEEK_SET = 0;//將讀寫位置指向檔案頭後再增加offset個位移量。
- int SEEK_CUR = 1;//以目前的讀寫位置往後增加offset個位移量。
- int EEK_END = 2;//將讀寫位置指向檔案尾後再增加offset個位移量。
- /** Called when the activity is first created. */
- @Override
- publicvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- writestrET = (EditText) findViewById(R.id.writeET);
- writeBT = (Button) findViewById(R.id.writeBT);
- readBT = (Button) findViewById(R.id.readBT);
- seekBT = (Button) findViewById(R.id.seekBT);
- readTV = (TextView) findViewById(R.id.readTV);
- writeBT.setOnClickListener(new OnClickListener() {
- @Override
- publicvoid onClick(View v) {
- // TODO Auto-generated method stub
- fd = NativeFileOpen(filename, O_CREAT | O_RDWR);
- System.out.println("fd_write---->" + fd);
- writeStr = writestrET.getText().toString();
- buf_write = writeStr.getBytes();
- int ret_write = NativeFileWrite(fd, buf_write, buf_write.length);
- System.out.println("寫入返回結果" + ret_write);
- NativeFileClose(fd);
- }
- });
- readBT.setOnClickListener(new OnClickListener() {
- @Override
- publicvoid onClick(View v) {
- // TODO Auto-generated method stub
- fd = NativeFileOpen(filename, O_CREAT | O_RDWR);
- System.out.println("fd_read---->" + fd);
- buf_read = newbyte[buf_write.length];
- int ret_read = NativeFileRead(fd, buf_read, buf_write.length);
- System.out.println("讀出返回結果" + ret_read);
- try {
- readTV.setText( new String(buf_read, "GB2312") + "");
- } catch (UnsupportedEncodingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- NativeFileClose(fd);
- }
- });
- seekBT.setOnClickListener(new OnClickListener() {
- @Override
- publicvoid onClick(View v) {
- // TODO Auto-generated method stub
- fd = NativeFileOpen(filename, O_CREAT | O_RDWR);
- long Offset=20;
- long ret_seek =NativeFileSeek(fd, Offset, SEEK_CUR);
- System.out.println("seek返回結果" + ret_seek);
- NativeFileClose(fd);
- /* 1) 欲將讀寫位置移到檔案開頭時:
- lseek(int fildes,0,SEEK_SET);
- 2) 欲將讀寫位置移到檔案尾時:
- lseek(int fildes,0,SEEK_END);
- 3) 想要取得目前檔案位置時:
- lseek(int fildes,0,SEEK_CUR);
- 返回值:當呼叫成功時則返回目前的讀寫位置,也就是距離檔案開頭多少個位元組。若有錯誤則返回-1,errno 會存放錯誤程式碼。
- * */
- }
- });
- }
- publicnativeint NativeFileOpen(String filename, int flags);
- publicnativeint NativeFileRead(int fd, byte[] buf, int sizes);
- publicnativeint NativeFileWrite(int fd, byte[] buf, int sizes);
- publicnativelong NativeFileSeek(int fd, long Offset, int whence);
- //Offset:偏移量,每一讀寫操作所需要移動的距離,單位是位元組的數量,可正可負(向前移,向後移)。
- publicnativeint NativeFileClose(int fd);
- static {
- System.loadLibrary("fs");
- }
- }
最後記得在manifest.xml裡面加上SD卡操作許可權
- <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
相關推薦
Android JNI層實現檔案的read、write與seek操作
轉自:http://blog.csdn.net/conowen/article/details/7525837 /*******************************************************************************
Android的NDK開發(5)————Android JNI層實現檔案的read、write與seek操作
/******************************************************************************************** * author:conowen@大鐘
【Linux】使用read、write、lseek函式實現檔案讀寫操作
本文章主要講述Linux環境下檔案的讀寫操作,使用到的函式有open、read、write、lseek。 open:用於開啟或者建立檔案。 read:從檔案中讀指定位元組的資料到記憶體中。 write:講記憶體中資料寫入到檔案中。 lseek:可以改變當前檔案偏移量。 #
封裝read、write、accept、connect函式,實現超時操作。
學習linux網路程式設計的時候,看視訊學習,封裝了一些可以直接拿來用的函式,方便以後查詢。 /** * read_timeout - 讀超時檢測函式,不含讀操作 *@fd: 檔案描述符 *@wait_seconds: 等待超時秒數,如果為0表示不檢測超時 * 成功
檔案操作程式設計一(open、close、read、write、lseek函式的使用)
一、open()函式用於開啟或建立檔案,在開啟或建立檔案時可以指定檔案的屬性及使用者的許可權等各種引數 所需標頭檔案:#include <sys/types.h> /* 提供型別pid_t 的定義 */ #include <sys/stat.h> #
檔案 I/O操作open、lseek、read、write、close詳解
一,檔案描述符、套接字和管道 對於核心而言,所有開啟的開啟的檔案都通過檔案描述符引用。檔案描述符是一個非負整數。 核心為每個程序維護一個結構體struct task_struct,可稱為程序控制塊(PCB: Process Control Bloc
讀寫檔案節點---echo與read、write均可
#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/device.h> #include <as
Nginx事件處理中的connection和read、write事件的關聯
ase handle inux cycle ngx auth eof conn ont /********************************************************************* * Author : Samson
Android Jni層 創建 linux socket 出錯問題解決
res html true bsp 失敗 ica ins moni name 問題: 想在Jni層創建 udp socket 與服務端通信,可是沒有成功。最後發現居然是創建socket失敗(代碼例如以下) // create socket g_sd = soc
Android ScrollView滾動實現大眾點評、網易雲音樂評論懸停效果
ins schema bar 音樂 layout mage for bin andro 今天聽著網易雲音樂,寫著代碼,真是爽翻了。 http://blog.csdn.net/linshijun33/article/details/47910833 網
android懸浮球實現各種功能、快速開發框架、單詞、筆記本、應用市場應用等源碼
jpeg 源碼 新聞 thread 並不是 類型 and 所有 大小 Android精選源碼 懸浮球,實現一鍵靜音,一鍵鎖頻,一鍵截屏等功能 一個Android快速開發框架,MVP架構 Android QQ小紅點的實現源碼 android一款單詞應用完整app源碼
4. read()、write() 相關函數解析
也有 工作 不為 作用 自己 這也 struct ioc 應用 我們在前面講到了file_operations,其是一個函數指針的集合,用於存放我們定義的用於操作設備的函數的指針,如果我們不定義,它默認保留為NULL。其中有最重要的幾個函數,分別是open()、read()
android java層實現hook替換method
reflect 過程 ren pic [] hotfix mru andro bsp Android上的熱修復框架 AndFix 大家都很熟悉了,它的原理實際上很簡單: 方法替換——Java層的每一個方法在虛擬機實現裏面都對應著一個ArtMethod的結構體,只要把
Android渠道打包實現打包logo、名稱、applicationId等
一、app下build.gradle配置 下面這裡就是設定了logo 和名稱要是需要設定application 新加一個 其他的照貓畫虎 如果你有特殊的處理在這個渠道包下那麼你就可以使用 {BuildConfig.FLAVOR} 獲取到
函式read、write、lseek
函式原型: #include<unistd.h> ssize_t read(int fd, void *buf, size_t count);
python使用pandas模組實現檔案讀取、字串處理、去重排序、excel生成
最近學習python,用python實現一個小需求,最後寫入excel使用到pandas模組: 某中學學生在500米短跑訓練比賽中的資料,體育老師把學生成績結果記錄在檔案中(studentdata.txt),記錄格式如下: 卡納瓦, 2001-11-8,2:27,2:33,
js-xlsx實現檔案匯出、下載(excel)
記錄一下近期使用js-xlsx的一些經驗 真正的.xls\.xlsx檔案,就算是空白的其實是包含了一些內容的 所以並不能直接像寫入txt一樣直接搞一個file往裡面把資料寫入就完了 現在網上查得到匯出excel的一些方法: 1、在IE上使用ActiveXObject匯出檔案 由於我們客戶端是基於
Android Retrofit2.0實現檔案上傳和下載
這篇主要介紹retrofit框架的上傳檔案到伺服器和從伺服器下載功能的實現 上傳檔案到伺服器 首先 retrofit2.0之前上傳檔案到伺服器需要一個叫TypedFile這個類,但是在2.0版本,這個類被取消了,因為2.0以後,retrofit內部集成了okhttp
shell指令碼實現檔案移動、複製等操作
如題。 在此做一記錄,方便查閱。 #!/bin/bash #將一個目錄下的一些檔案移動到另一個目錄下 raw_dir="/home/liuyi/evt_test" #可修改絕對路徑; mkdir /home/liuyi/evt_bp #建立新的檔案目錄; for
Android利用HttpURLConnection實現檔案上傳
普通Java應用 瀏覽器在上傳的過程中是將檔案以流的形式提交到伺服器端的,如果直接使用Servlet獲取上傳檔案的輸入流然後再解析裡面的請求引數是比較麻煩,所以Java中Web端可以用的上傳元件有兩種: FileUpload【操作比較複雜】struts上傳的功能就是基於這個實現的。