android 数据存储-文件存储

之前项目用到了文件存储相关的功能,功能基本都实现了,也满足了性能要求,在这里总结一下。


1.1. 读写应用程序目录下文件

Android ContextWrapper提供了openFileOutput和openFIleInput两个方法,可以读写

/data/data/应用程序包名 目录下的文件。

public FileOutputStreamopenFileOutput(String name, int mode)

name:文件名,不能包含路径分隔符“/”

mode:文件操作模式,有以下值:

MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问。

MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。

MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;

MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。

openFileOutput()如果文件不存在,Android 会自动创建它。创建的文件保存在/data/data/应用程序包名/files目录下

public FileInputStream openFileInput(Stringname)

name:读取文件名

除此之外,Context还提供了如下几个重要的方法:

getDir(Stringname , int mode):在应用程序的数据文件夹下获取或者创建name对应的子目录

FilegetFilesDir():获取该应用程序的数据文件夹得绝对路径

String[]fileList():返回该应用数据文件夹的全部文件              

 

   private voidwrite1(String str, String fileName) {
        try {
            FileOutputStream out =openFileOutput(fileName, MODE_PRIVATE);
            out.write(str.getBytes());
            out.close();
            Toast.makeText(MainActivity.this, "保存成功",Toast.LENGTH_SHORT).show();
        } catch(Exception e) {
            // TODOAuto-generated catch block
            e.printStackTrace();
        }
    }
   
    privateString read1(String fileName) {
        try {
            FileInputStream in =openFileInput(fileName);
            int len= in.available();
            byte[]temp = new byte[len];
            in.read(temp);
            String str = EncodingUtils.getString(temp,"UTF-8");
            in.close();
            return str;
        } catch(Exception e) {
            // TODOAuto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

1.2. 读写sdcard上的文件

其中读写步骤按如下进行:

必须在AndroidManifest.xml上配置读写SD卡的权限

<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

 

1、调用Environment的getExternalStorageState()方法判断手机上是否插了sd卡,且应用程序具有读写SD卡的权限,如下代码将返回true

Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)

2、调用Environment.getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录,或者使用"/mnt/sdcard/"目录

3、使用IO流操作SD卡上的文件

注意点:手机应该已插入SD卡,对于模拟器而言,可通过mksdcard命令来创建虚拟存储卡

案例代码:

private voidwrite2(String str, String fileName) {
        String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
        File file = newFile(filePath + File.separator +fileName); // 定义File类对象
        if(!file.getParentFile().exists()) { // 父文件夹不存在
            file.getParentFile().mkdirs(); // 创建文件夹
        }
        try {
            FileOutputStream out = newFileOutputStream(filePath + File.separator +fileName);
            out.write(str.getBytes());
            out.close();
            Toast.makeText(MainActivity.this, "保存成功",Toast.LENGTH_SHORT).show();
        } catch(Exception e) {
            // TODOAuto-generated catch block
            e.printStackTrace();
        }
    }
   
    privateString read2(String fileName) {
        String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
        File file = newFile(filePath + File.separator +fileName); // 定义File类对象
        try {
            FileInputStream in = newFileInputStream(filePath + File.separator +fileName);
            int len= in.available();
            byte[]temp = new byte[len];
            in.read(temp);
            String str = EncodingUtils.getString(temp,"UTF-8");
            in.close();
            return str;
        } catch(Exception e) {
            // TODOAuto-generated catch block
            e.printStackTrace();
            return null;
        }
    }




 

1.3. Raw目录下文件读取

Android raw目录下的文件读取使用Context提供getResources()函数,获取当前应用资源实例,然后使用openRawResource读取文件,openRawResource的参数是资源的Id标识。

代码例子:

    privateString read3(int file) {
        String str = "";
        try{
           InputStream in = getResources().openRawResource(file);    
           byte[] temp = new byte[in.available()];      
           //读取数据
           in.read(temp);        
           //依test.txt的编码类型选择合适的编码,如果不调整会乱码
           str = EncodingUtils.getString(temp, "BIG5");
           //关闭   
           in.close();  
           return str;
        } catch(Exceptione) {
            e.printStackTrace();  
            return null;
        }
    }


 

1.4. Assets目录下文件读取

Assets目录保存的都是保持原始格式的文件,android在编译的时候并不会去编译它们,所以我们不能通过资源Id访问它们,android为我们提供了一个AssetManager类,专门用于应用程序的原始资源文件,在Activity中,可以通过getResources().getAssets()获取AssetManager实例,使用AssetManager的open函数操作文件。

代码例子:

    privateString read4(String fileName) {
        String str="";
        try{
            InputStream in =getResources().getAssets().open(fileName);       
            byte []temp = new byte[in.available()];       
            in.read(temp);           
            in.close();
            str = EncodingUtils.getString(temp,"UTF-8");
            return str;
        }catch(Exceptione){
            e.printStackTrace();    
            return null;
        }
    }


 

1.5. 使用File类操作文件

File类可以直接处理文件和文件系统,并没有指定信息怎样从文件读取或向文件存储,它主要是完成了文件相关的管理工作,一个File类典型的例子代码:

private void write5(String str,String fileName) {
        String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
        File file = newFile(filePath + File.separator +fileName); // 定义File类对象
        if(!file.getParentFile().exists()) { // 父文件夹不存在
            file.getParentFile().mkdirs(); // 创建文件夹
        }
        try {
            FileOutputStream out = newFileOutputStream(file);
            out.write(str.getBytes());
            out.close();
            Toast.makeText(MainActivity.this, "保存成功",Toast.LENGTH_SHORT).show();
        } catch(Exception e) {
            // TODOAuto-generated catch block
            e.printStackTrace();
        }
    }
   
    privateString read5(String fileName) {
        String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
        File file = newFile(filePath + File.separator +fileName); // 定义File类对象
        if(!file.getParentFile().exists()) { // 父文件夹不存在
            file.getParentFile().mkdirs(); // 创建文件夹
        }
        try {
            FileInputStream in = newFileInputStream(file);
            int len= in.available();
            byte[]temp = new byte[len];
            in.read(temp);
            String str = EncodingUtils.getString(temp,"UTF-8");
            in.close();
            return str;
        } catch(Exception e) {
            // TODOAuto-generated catch block
            e.printStackTrace();
            return null;
        }
    }


下面列举一些File类常用的操作

public boolean delete():删除文件。 

public boolean exists():判断文件是否存在。 

public String getAbsolutePath():获取文件的绝对路径。 

public String getName():获取文件名称。 

public String getParent():获取文件所在目录路径。 

public String getPath():获取文件的相对路径。 

public File getParentFile():获取文件所在目录路径File实例。 

public boolean isDirectory():判断该路径指示的是否是文件。 

public boolean isFile():判断该路径指示的是否是文件。 

public boolean isFile():返回文件长度。 

public boolean mkdir():生成指定的目录。 

 

1.6. 使用RandomAccessFile类操作文件

RandomAccessFile的唯一父类是Object,与其他流父类不同。是用来访问那些保存数据记录的文件的,这样你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。

RandomAccessFile是不属于InputStream和OutputStream类系的。实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),它和这两个类系毫不相干,甚至都没有用InputStream和OutputStream已经准备好的功能;它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写的。这可能是因为RandomAccessFile能在文件里面前后移动,所以它的行为与其它的I/O类有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类。

代码例子:

private voidwrite6(String str, String fileName) {
        String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
        File file = newFile(filePath + File.separator +fileName); // 定义File类对象
        if(!file.getParentFile().exists()) { // 父文件夹不存在
            file.getParentFile().mkdirs(); // 创建文件夹
        }
        file.mkdir();
        RandomAccessFile randomFile;
        try {
            randomFile = newRandomAccessFile(filePath + File.separator +fileName,"rw");
            randomFile.write(str.getBytes());
            randomFile.close();
            Toast.makeText(MainActivity.this, "保存成功",Toast.LENGTH_SHORT).show();
        } catch(Exception e) {
            // TODOAuto-generated catch block
            e.printStackTrace();
        }
       
    }
   
    privateString read6(String fileName) {
        String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
        File file = newFile(filePath + File.separator +fileName); // 定义File类对象
        if(!file.getParentFile().exists()) { // 父文件夹不存在
            file.getParentFile().mkdirs(); // 创建文件夹
        }
        try {
            RandomAccessFile randomFile = newRandomAccessFile(filePath + File.separator +fileName,"rw");
            int len= (int)randomFile.length();//取得文件长度(字节数)
            byte[]temp = new byte[len];
            randomFile.read(temp);
            String str = EncodingUtils.getString(temp,"UTF-8");
            randomFile.close();
            return str;
        } catch(Exception e) {
            // TODOAuto-generated catch block
            e.printStackTrace();
            return null;
        }
    }


 

1.7. 读取文件时实现类似seek的方式

使用FileInputStream和InputStream可以实现文件的随机读取,FileInputStream提供了一下两个函数

public long skip (long byteCount); //跳过byteCount个字节

public int read (byte[] buffer, int offset,int length); //从数据流中读取length数据存,offset代表buffer的偏移位置。

使用这两个函数来实现文件的随机读取,类似于seek的操作。注意skip和read函数始终是相对于当前位置的。

测试代码:

private voidwriteSeek(String str, String fileName) {
        String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
        File file = newFile(filePath + File.separator +fileName); // 定义File类对象
        System.out.println("--------->parent path: " + file.getParent());
        if(!file.getParentFile().exists()) { // 父文件夹不存在
            file.getParentFile().mkdirs(); // 创建文件夹
        }
        try {
            FileOutputStream out = newFileOutputStream(filePath + File.separator +fileName);
            out.write(str.getBytes());
            out.close();
            Toast.makeText(MainActivity.this, "保存成功",Toast.LENGTH_SHORT).show();
        } catch(Exception e) {
            // TODOAuto-generated catch block
            e.printStackTrace();
        }
    }
   
    privateString readSeek(String fileName) {
        String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
        File file = newFile(filePath + File.separator +fileName); // 定义File类对象
        if(!file.getParentFile().exists()) { // 父文件夹不存在
            file.getParentFile().mkdirs(); // 创建文件夹
        }
        try {
            FileInputStream in = newFileInputStream(filePath + File.separator +fileName);
            int len= in.available();
            byte[]temp = new byte[len];
            in.skip(3);
            in.read(temp, 0, 3);
            String str = EncodingUtils.getString(temp,"UTF-8");
            in.close();
            return str;
        } catch(Exception e) {
            // TODOAuto-generated catch block
            e.printStackTrace();
            return null;
        }
    }


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值