Android JNI文件操作常用函数

1.概述

在Android开发中,对于JNI读写文件也是常用的功能,jni操作常用函数讲解就来简单分析方便
更快了解jni读写文件功能

2.JNI文件操作常用函数

file.h 常用函数:
fopen()函数

函数原型为:FILE *fopen(const char *filename, const char *mode);

fopen(文件路径,文件使用方式);

fopen函数打开filename指定的文件,返回一个指向FILE类型的指针,无论使用哪种方式,当打开文件时出现了错误,fopen函数都将返回NULL

常见的文件使用方式:

“r”----以只读的方式打开文件(该文件必须已经存在,若文件不存在,则会出错)

“w”----以只写的方式打开文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件

“a”----以只写的方式打开文本文件,位置指针移到文件末尾,向文件尾部添加数据,原文件数据保留,若文件不存在则会出错

“+”----与上面的字符串组合,表示以读写的方式打开文本文件,既可向文件中写入数据,也可从文件中读出数据

“b”----与上面的字符串组合,表示打开二进制文件

读写权限和读写方式可以组合使用,但是必须将读写方式放在读写权限的中间或者尾部(换句话说,不能将读写方式放在读写权限的开头)。例如:

将读写方式放在读写权限的末尾:"rb"、"wt"、"ab"、"r+b"、"w+t"、"a+t"
将读写方式放在读写权限的中间:"rb+"、"wt+"、"ab+"

(因为操作系统对于同时打开的文件数目是有限制的,所以在文件使用结束后必须使用fclose关闭文件,否则会出现意想不到的错误)

1 err = fopen_s(&fp, “E:\ww.txt”, “w”);

或者

1 err = fopen_s(&fp, “E:\ww.txt”, “w+”);

上述两条语句打开文件后文件内容自动清除,无论是否存在读/写文件操作,都会自动清除

fclose()函数

fclose(文件指针);

若文件关闭成功则返回0,否则返回非0

文件的读写

fread()函数

函数原型:unsigned int fread(void *buffer, unsigned int size, unsigned int count, FILE *fp);

函数功能:从fp所指的文件中读取数据块并存储到buffer所指向的内存中,buffer是待读入数据块存储的起始地址,size是每个数据块的大小(待读入的每个数据块的字节数),

count是最多允许读取的数据块个数(每个数据块size个字节),函数返回的是实际读到的数据块个数

fwrite()函数

函数原型:unsigned int fwrite(const void *buffer, unsigned int size, unsigned int count, FILE *fp);

函数功能:将buffer指向的内存中的数据块写入fp所指的文件,buffer是待输出数据块的起始地址,size是每个数据块的大小(待输出的每个数据块的字节数),

count是最多允许写入的数据块个数(每个数据块size个字节),函数返回的是实际写入的数据块个数

(tips:用户指定的内存块大小,最小为1字节,最大为整个文件)

fread()函数和fwrite()函数是按数据块的长度来处理输入/输出的,在用文本编辑器打开文本文件时可能因发生字符转换而出现莫名其妙的结果,所以这两个函数通常用于二进制文件的输入/输出

fscanf()函数

函数原型:int fscanf (FILE *fp, const char *format, ……);

fscanf(文件指针, 格式字符, 输入列表);

第一个参数为文件指针,第二个参数为格式控制符,第三个参数为地址参数表列,后两个参数与函数scanf()的参数相同

fprintf()函数

函数原型:int fprintf (FILE *fp, onst char *format, ……);

fprintf(文件指针, 格式字符, 输出列表);

第一个参数为文件指针,第二个参数为格式控制参数,第三个参数为输出参数列表,后两个参数和返回值与函数printf()相同

(用函数fscanf()和fprintf()进行文件的格式化读写,读写方便容易理解,但输入时要将ASCII字符转换成二进制数,输出时要将二进制数转换为ASCII字符,耗时较多)

fgets()函数

函数原型:char *fgets(char *s,int n,FILE *fp);

函数功能:该函数从fp所指的文件中读取字符串并在字符串末尾添加‘\0’,然后存入s,最多读n-1个字符,当读到回车换行符、到达文件尾或读满n-1个字符时,就停止读取

函数返回该字符串的首地址,即指针s的值,读取失败返回空指针NULL

(与gets()不同的是,fgets()从指定的流读取字符串,读到换行符时将换行符也作为字符串的一部分读到字符串中来)

fputs()函数

函数原型:fputs(In_z const char * _Str, Inout FILE * _File);

str是要输出的字符串,fp是文件指针,字符串末尾’\0’不输出

函数功能:将字符串输出到指针fp所指的文件中

(与puts()不同的是,fputs()不会在写入文件的字符串末尾加上换行符’\n’)

fgetc()函数

函数原型:int fgetc (FILE *fp);

函数功能:用于从一个以只读或读写方式打开的文件上读字符,从fp所值的文件中读取一个字符,并将位置指针指向下一个字符,若读取成功,则返回该字符,

若读取不成功则返回EOF(EOF是一个符号常量,stdio.h中定义为-1)

fputc()函数

函数原型:int fputc(int c, FILE *fp);

fp是由函数fopen()返回的文件指针,c是要输出的字符(尽管C定义为int型,但只写入低字节)

函数功能:该函数的功能是将字符c写到文件指针fp所指的文件上中,若写入错误返回EOF,否则返回字符c

文件的定位

文件的随机读写:文件的随机访问允许在文件中随机定位,并在文件的任何位置直接读写数据,为了实现文件的定位,在每一个打开的文件中,都有一个文件位置指针,

也称为文件位置标记,用来指向当前读写文件的位置,它保存了文件中的位置信息,当文件进行顺序读写时,每读完一个字节后,该位置指针自动移到下一个字节的位置,

当需要随机读写文件数据时,则需强制移动文件位置指针指向特定的位置

fseek()函数

函数原型:int fseek(FILE *fp,long offset,int fromwhere);

函数功能:将fp的文件位置指针从fromwhere开始移动offset个字节指示下一个要读取的数据的位置

offset是一个偏移量,它告诉文件位置指针要跳过多少字节,offset为正时,向后移动,为负时,向前移动,ANSIC要求位移量offset是长整型数据(常量数据后要加L),

这样当文件的长度大于64k时不至于出问题

fromwhere用于确定偏移量计算的起始位置,它的可能取值有3种,SEEK_SET或0,代表文件开始处,SEEK_CUR或1,代表文件当前位置,SEEK_END或2,代表文件结尾处,

通过指定fromwork和offset的值,可使位置指针移动到文件的任意位置,从而实现文件的随机读取,如果函数fseek()调用成功,则返回0值,否则返回非0值

两种特殊使用方式:

将读写位置移动到文件开头:fseek(FILE *stream,0,SEEK_SET);
  将读写位置移动到文件尾:fseek(FILE *stream,0,0SEEK_END);

(fseek() 一般用于二进制文件,在文本文件中由于要进行转换,计算的位置有时会出错)

rewind()函数

函数原型:void rewind(FILE *fp);

函数功能:将文件位置指针指向文件首字节,即重置位置指针到文件首部

ftell()函数

函数原型:long ftell(FILE *fp);

函数功能:读取当前文件指针的位置,若函数调用成功,则返回文件的当前读写位置,否则返回-1L,函数ftell()用于相对于文件起始位置的字节偏移量来表示返回的当前位置指针

(需要注意的是,当用err = fopen_s(&fp, “E:\ww.txt”, “a+”);打开文件后文件指针移到文件末尾,此时文件起始位置还是为文件头部并不是文件末尾)

文件检测
  ferror()函数

函数原型:int ferror(FILE *stream);

函数功能:它的一般调用形式为 ferror(fp);如果ferror返回值为0(假),表示未出错。如果返回一个非零值,表示出错。应该注意,对同一个文件 每一次调用输入输出函数,

均产生一个新的ferror函数值,因此,应当在调用一个输入输出函数后立即检 查ferror函数的值,否则信息会丢失。在执行fopen函数时,ferror函数的初始值自动置为0

feof()函数

函数原型:int feof(FILE *fp);

函数功能:检测流上的文件结束符,如果文件结束,则返回非0值,否则返回0,文件结束符只能被clearerr()函数清除

(函数feof()总是在读完文件所有内容后再执行一次读文件操作(将文件结束符读走,但不显示)才能返回真(非0)值)

C语言为了提高数据的输入/输出的速度,在缓冲型文件系统中,给打开的每一个文件建立一个缓冲区,文件内容先被批量地读入缓冲区,程序进行读操作时,实际上是从缓冲区中读取数据,

写入操作也是如此,首先将数据写入缓冲区,然后在适当的时候(例如关闭时)再批量写入磁盘,这样虽然可以提高I/O的性能,但也有一些副作用,例如在缓冲区内容还未写入磁盘时,

计算机突然死机或掉电,数据就会丢失,永远也找不回来,再如缓冲区被写入无用的数据时,如果不清除,其后的文件读操作都首先要读取这些无用的数据

为了解决这个问题C语言提供了fflush()函数
  
  fflush()函数

函数原型:int fflush(FILE *fp);

函数功能:清除缓冲区的内容,对于输出流来说,fflush函数将已经写到缓冲区但尚未写入文件的所有数据写到文件中,对输入流来说,其结果是未定义的,

如果在写的过程中发生错误,则返回EOF,否则返回0,(函数功能的另一种描述:无条件的将缓冲区的所有数据写入物理设备,这样程序员可自己决定何时清除缓冲区中的数据,以确保输出缓冲区的内容写入文件)

ftell()函数

函数原型:long ftell(FILE *fp);

函数功能:读取当前文件指针位置,若函数调用成功,则返回文件的当前读写位置,否则返回-1L

(函数ftell()用于相对于文件起始位置的字节偏移量来表示返回的当前位置指针)

fflush(stdin);刷新标准输入缓冲区,把输入缓冲区里的东西丢弃[非标准]
  fflush(stdout);刷新标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上
  fflush(NULL);将清洗所有的输出流

3.关于app中具体操作

1.设置读取权限

<!--添加读写权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

2.jni文件的读写

//头文件
#include <jni.h>
#include <string>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "android/log.h"
#define  LOG    "JNILOG"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG,__VA_ARGS__)

//打开文件
extern "C"
JNIEXPORT jint JNICALL
Java_com_pne_jnitest_MainActivity_file_open(JNIEnv *env, jobject thiz, jstring filename,jint flags)
{
    const char *dirPath = env->GetStringUTFChars(filename, nullptr);
    int fd = open(dirPath, flags, 0666);

    //若所有欲核查的权限都通过了检查则返回 0值,表示成功,
    //只要有一个权限被禁止则返回-1。
    if (fd == -1){
        return -1;
    }
    return fd;
}

//读取文件
int file_read(int fd, unsigned char *buf, int size)
{
    return read(fd, buf, size);
}

//指针指向0,否则会在当前位置,读不出写入数据
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);
}
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安卓兼职framework应用工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值