关于file文件存储

Java file文件的写入和读取及下载

File文件的写入

  一、FileWriter 和BufferedWriter 结合写入文件

  FileWriter是字符流写入字符到文件。默认情况下,它会使用新的内容代替文件原有的所有内容,但是,当指定一个true值作为FileWriter构造函数的第二个参数,它会保留现有的内容,并追加新内容在文件的末尾。

  BufferedWriter:缓冲字符,是一个字符流类来处理字符数据。不同于字节流(数据转换成字节FileOutPutStream),可以直接写字符串、数组或字符数据保存到文件。

1

2

3

默认情况,替换原有内容:   new FileWriter(file);

 

保留原来的文件内容:      new FileWriter(file,true

  具体例子如下:

复制代码

public static void writeInFileByfb() {
        File f=new File("E:\\Java\\jmoa\\TestDiff\\src\\test\\resource\\test_fb.txt");
        String content="要写入文件的新内容";
        FileWriter fw=null;
        BufferedWriter bw=null;
        try{
            if(!f.exists()){
                f.createNewFile();
            }
             fw=new FileWriter(f.getAbsoluteFile(),true);  //true表示可以追加新内容  
                         //fw=new FileWriter(f.getAbsoluteFile()); //表示不追加
             bw=new BufferedWriter(fw);
             bw.write(content);
             bw.close();
        }catch(Exception e){
           e.printStackTrace();
        }
        
    }

复制代码

 

  二、FileOutPutStream 字节流写入文件

  文件输出流是一种用于处理原始二进制数据的字节流泪。 为了将数据写入到文件中,必须将数据转换为字节,并保存到文件。具体例子如下:

复制代码

package com.joyplus.test;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutPutTest {
    public static void main(String[] args) {
        FileOutPutTest.writeInFileByfi();
    }
    
    
    public static void writeInFileByfi(){
        File f=new File("E:\\Java\\jmoa\\TestDiff\\src\\test\\resource\\test_fi.txt");
        FileOutputStream fos=null;
        try {
            if(!f.exists()){
                f.createNewFile();
            }
             fos=new FileOutputStream(f);
            String content="要写入的新内容!";
            fos.write(content.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fos!=null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
    }
}

复制代码

  三、RandomAccessFile 写入文件

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

   如下例子是RandomAccessFile如何进行写入文件的例子:

复制代码

public static void writeInFileByRdA(){
        String content="randowAccessFile";
        try{
              // 打开一个随机访问文件流,按读写方式
            RandomAccessFile randomFile = new RandomAccessFile("E:\\Java\\jmoa\\TestDiff\\src\\test\\resource\\test_fb.txt", "rw");
            // 文件长度,字节数
            long fileLength = randomFile.length();
            //将写文件指针移到文件尾。
            randomFile.seek(fileLength);
            randomFile.writeBytes(content);
            randomFile.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

复制代码

文件的读取

  一、FileInputStream 字节流读取文件 【注意:读取中文的时候会乱码】

具体代码如下:

复制代码

    //按照字节读取文件内容
    public static String readFileByByte(){
        String s="";
        File f=new File("E:\\Java\\jmoa\\TestDiff\\src\\test\\resource\\test_fb.txt");
        InputStream in=null;
        try{
            in=new FileInputStream(f);
            int tempByte;
            while((tempByte=in.read())!=-1){
                System.out.println(tempByte);
                s+=tempByte;
            }
            in.close();
        }catch(Exception e){
            e.printStackTrace();
        }
        System.out.println("content:"+s);
        return s;
    }

复制代码

  二、InputStreamReader 字符流读取文件内容

复制代码

//按照字符读取文件内容
    public static String readFileByChar(){
        String s="";
        File f=new File("E:\\Java\\jmoa\\TestDiff\\src\\test\\resource\\test_fb.txt");
        Reader rdr=null;
        try{
            rdr=new InputStreamReader(new FileInputStream(f));
            int temp;
            while((temp=rdr.read())!=-1){
                //对于window下,\r\n这两个字符在一起时,表示一个换行。   
                //但是如果这两个字符分开显示时,会换两行。
                //因此,屏蔽掉\r,或者屏蔽掉\n。否则,将会出现很多空行
                if(((char)temp)!='\r'){
                    s+=(char)temp;
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try {
                rdr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println(s);
        return s;
    }

复制代码

  三、BufferedReader 以行为单位读取文件内容

复制代码

//按照行读取文件
    public static String readFileByLine(){
        String s="";
        File f=new File("E:\\Java\\jmoa\\TestDiff\\src\\test\\resource\\test_fb.txt");
        BufferedReader br=null;
        try{
            System.out.println("按照行读取文件内容");
            br=new BufferedReader(new FileReader(f));
            String temp;
            while((temp=br.readLine())!=null){
                s+=temp;
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("file content:"+s);
        return s;
    }

复制代码

  四、随机读取文件中的部分内容: RandomAccessFile

复制代码

//随机行读取文件
    public static String readFileByRand(){
        String s="";
        File f=new File("E:\\Java\\jmoa\\TestDiff\\src\\test\\resource\\test_fb.txt");
        RandomAccessFile raf=null;
        try{
            //打开一个文件流, 按只读方式
            raf=new RandomAccessFile(f.getName(), "r");
            //文件长度,字节数
            long fileLength=raf.length();
            //读文件的起始位置
            int beginIndex=(fileLength>4)?4:0;
            //将读文件的开始位置移到beginIndex位置
            raf.seek(beginIndex);
            byte[] bytes=new byte[10];
            int byteread=0;
            //一次读10个字节,如果文件内容不足10个字节,则读剩下的文字。
            //将一次读取的字节数赋给byteread
            while((byteread=raf.read(bytes))!=-1){
                System.out.write(bytes,0,byteread);
            }
            
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(raf!=null){
                try {
                    raf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //System.out.println("文件内容:"+s);
        return s;
    }

复制代码

补充的文件知识:

复制代码

    /**
     * 显示输入流中还剩的字节数
     */
    private static void showAvailableBytes(InputStream in) {
        try {
            System.out.println("当前字节输入流中的字节数为:" + in.available());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

复制代码

 

文件的下载

复制代码

  // 在线打开方式 下载
    public void downLoad(String filePath, HttpServletResponse response,String fileNewName) throws Exception {
        File f = new File(filePath);
        OutputStream out = response.getOutputStream();
        if (!f.exists()) {
            response.setCharacterEncoding("UTF-8");
            String notFileHtml=getNotFileHtml(filePath,"文件找不到");
            out.write(notFileHtml.getBytes("UTF-8"));
            out.flush();
            return;
        }
        BufferedInputStream br = new BufferedInputStream(new FileInputStream(f));
        byte[] buf = new byte[1024];
        int len = 0;

        response.reset(); // 非常重要
        response.setContentType("application/x-msdownload");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileNewName);

        while ((len = br.read(buf)) > 0)
            out.write(buf, 0, len);
        br.close();
        out.close();
    }

 

 

Android中的File存储

       关于Android的File存储,这里先说下Java中的File类,根据面向对象的思想,Java中对文件的操作也进行了对象的封装,这个操作文件的类就是File类,File提供了丰富的api来进行文件的操作,比如常见的createNewFile(),mkdir(),mkdirs(),exists(),isFile(),isDictory(),renameto(),delete(),getName(),getPath()....方法比较多,读者可以自行通过api文档查看,同样这一套的文件操作在Android中也适用。

下面对几个常用的api进行说明举例。

File构造函数

/**
*这里通过将给定路径名字符串转换为抽象路径名来创建一个新File实例。
*然后执行file.createNewFile();如果该文件存在,则创建失败,不存在则创建,返回一个boolean值
*/
File file=new File(String pathname);

 

/**
*这里根据parent抽象路径名和child路径名字符串创建一个新File实例。
*执行file.createNewFile();如果parent抽象路径名不存在,或者文件已经创建过,依然不能创建成功。
*/
File file=new File(File parent,String child);

 

/**
*根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
*执行file.createNewFile();如果parent抽象路径名不存在,或者文件已经创建过,依然不能创建成功。
*/
File file=new File(String parentpath,String child);

File常用方法

  • createNewFile();如果文件已经存在,则创建失败,否则成功创建,还有其他可能
  • mkdir();创建文件夹,注意:如果创建目标文件夹的父级目录不存在,就会创建失败
  • mkdirs();创建多级目录,父级文件目录不存在的话,会自动创建父级目录。
  • isFile();判断是否是一个文件
  • isDictory();判断是否是一个文件夹
  • delete();删除文件或者文件夹,注意要是删除文件夹的时候,文件夹里还有文件或者文件夹,则不能删除,意思是只能删除一个空文件夹。
  • exists();判断文件或者文件夹是否存在
  • getName();获取文件或者文件夹的名称
  • getPath();获取相对路径
  • getAbsolutePath();获取绝对路径
  • length();获取文件或者文件夹的长度

Android中的File存储

  • 在介绍如何在Android平台下进行文件的读取之前,有必要了解Android平台下的数据存储规则。在其他的操作系统如Windows 平台下,应用程序可以自由地或者在特定的访问权限基础上访问或修改其他应用程序名下的文件等资源,而在Android平台下,一个应用程序中所有的数据都是私有的。
  • 当应用程序被安装到系统中后,其所在的包会有一个文件夹用于存放自己的数据,只有这个应用程序才有对这个文件夹的写入权限,这个私有的文件夹位于Android系统的/data/data/<应用程序包名>目录下,其他的应用程序都无法再这个文件夹中写入数据。除了存放私有的数据文件夹外,应用程序也具有SD卡的写入权限。
  • 使用文件I/O 方法可以直接往手机中存储数据,默认情况下这些文件不可以被其他的应用程序访问。Android平台支持 java平台下的 文件I/O操作, 主要使用FileInputStream 和 FileOutputStream 这两个类来实现文件的存储与读取。获取这两个类对象的方式有两种。
  1. 第一种方式就是像Java平台下的实现方式一样通过构造器直接创建,如果需要向打开的文件末尾写入数据,可以通过使用构造器FileOutputStream(File file, boolean append)将 append设置为true来实现。不过需要注意的是采用这种方式获得FileOutputStream 对象时如果文件不存在或不可写入时,会抛出 FileNotFoundException 异常。
  2. 第二种获取 FileInputStream 和 FileOutputStream 对象的方式是调用 Context.openFileInput 和 Context.openFileOutput两个方法来创建。

方法说明

    1. openFileInput(String filename)  打开应用程序私有目录下的的指定私有文件以读入数据,返回一个FileInputStream 对象,如果该文件不存在,依然会发生异常,FileNotFoundException
    2. openFileOutput(String fileName,int mode) 打开应用程序私有目录下的的指定私有文件以写入数据,返回一个FileOutputStream 对象,如果文件不存在就创建这个文件。

除了这两个方法外,Context对象还提供了其他几个用于对文件操作的方法,如下所示

  • fileList() 搜索应用程序私有文件夹下的私有文件,返回所有文件名的String数组
  • deleteFile(String fileName) 删除指定文件名的文件,成功返回true,失败返回false

在使用openFileOutput方法打开文件以写入数据时,需要指定打开模式。默认为零,即MODE_PRIVATE。不同的模式对应的的含义如下:
常量 含义 
MODE_PRIVATE 
默认模式,文件只可以被调用该方法的应用程序访问
MODE_APPEND 
如果文件已存在就向该文件的末尾继续写入数据,而不是覆盖原来的数据。
MODE_WORLD_READABLE 
赋予所有的应用程序对该文件读的权限。
MODE_WORLD_WRITEABLE 
赋予所有的应用程序对该文件写的权限。
但是Android 4.2开始,Android不推荐使用,MODE_WORLD_READABLE ,MODE_WORLD_WRITEABLE 这两种模式。 

App在手机上保存文件或者缓存数据时,应该遵守以下几点:

  • 不要随意占用用户的内置存储。
  • 不要随意在SD卡上新建目录,应该放置自己应用包名对应的扩展存储目录下,卸载App时可以被自动清除。
  • 对占用的磁盘空间有上限,并按照一定的策略进行清除。

 Android下有哪些文件目录

 应用私有存储(内置存储)

        获取方式:
               Context.getFileDir():获取内置存储下的文件目录,可以用来保存不能公开给其他应用的一些敏感数据如用户个人信息
               Context.getCacheDir():获取内置存储下的缓存目录,可以用来保存一些缓存文件如图片,当内置存储的空间不足时将系统自动被清除
        绝对路径:
              Context.getFileDir():/data/data/应用包名/files/
              Context.getCacheDir():/data/data/应用包名/cache/
         写权限:不需要申请

这是手机的内置存储,没有root的过的手机是无法用文件管理器之类的工具查看的。而且这些数据也会随着用户卸载App而被一起删除。这两个目录其实就对应着设置->应用->你的App->存储空间下面的清除数据和清楚如下图所示

应用扩展存储(SD卡)

       获取方式:
              Context.getExternalFilesDir():获取SD卡上的文件目录
              Context.getExternalCacheDir():获取SD卡上的缓存目录
       绝对路径:
             Context.getExternalFilesDir():SDCard/Android/data/应用包名/files/
             Context.getExternalCacheDir():SDCard/Android/data/应用包名/cache/
       写权限:
           API < 19:需要申请
           API >= 19:不需要申请
既然是SD卡上的目录,那么是可以被其他的应用读取到的,所以这个目录下,不应该存放用户的敏感信息。同上面一样的,这里的文件会随着App卸载而被删除,也可以由用户手动在设置界面里面清除。

公共存储(SD卡)

     获取方式:Environment.getExternalStorageDirectory()
     绝对路径:SDCard/你设置的文件夹名字/
     写权限:需要申请

如果我们的App需要存储一些公共的文件,甚至希望下载下来的文件即使在我们的App被删除之后,还可以被其他App使用,那么就可以使用这个目录。这个目录是始终需要申请SD写入权限的。
Android6.0下应该把文件放到哪里?

          根据最开始提到的规则,其实如果仅仅是做了简单的图片缓存工作,那么我们应该把图片缓存放到/data/data/应用包名/cache/或者SDCard/Android/data/应用包名/cache/,因为在6.0系统(API23)时,不需要申请权限就可以向这两个目录写入文件。而且/data/data/应用包名/cache/目录,是内置存储的应用私有缓存目录,在系统空间不够时还会被自动清除,对于图片缓存来讲也是一个不错的管理策略,不过谷歌建议我们最好还是自己实现缓存清除管理,例如用DiskLruCache。

参考文章:http://unclechen.github.io/2016/03/06/Android6.0%E6%9D%83%E9%99%90%E9%80%82%E9%85%8D%E4%B9%8BSD%E5%8D%A1%E5%86%99%E5%85%A5/

 

 

 

Android file类使用详解

2018年07月16日 10:32:11 长眠于心 阅读数:600

一.Android file类

    在开发Android应用时免不了会跟文件打交道,本篇文章记录总结自己常用到的文件操作,数据的存储有多种方式,比如数据库存储、SharedPreferences存储、文件存储等;这里我们将要介绍最简单的文件存储方式;文件存储简单的来说就是一般的JAVASE中的IO流,只是把他应用于Android手机中而已。

二.Android file类使用

    File文件的存储需要在程序中使用sdcard进行数据的存储,需要在AndroidMainfset.xml文件中进行权限的配置:

1.SDCard中创建与删除文件权限:

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

2.SDCard写入数据权限

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

代码如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.cxy.file">
    <uses-permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

 

    File类语法

1.File(String pathname)

File file = new File ("/mnt/sdcard/test.txt");

2.File(String dir, String subpath)

File file = new File("/mnt/sdcard/temp", "test.txt");

         File类常用方法

boolean exists() 测试文件是否存在

boolean delete() 删除此对象指定的文件
boolean createNewFile() 创建新的空文件
boolean isDirectory() 测试此File对象表示的文件是否是目录
boolean mkdir() 创建由该File对象表示的目录
boolean mkdirs() 创建包括父目录的目录

String getAbsolutePath() 返回此对象表示的文件的绝对路径名
String getName() 返回此对象表示的文件的名称
String getParent() 返回此File对象的路径名的上一级,若路径名没有上一级,则返回null

 

使用mkdir创建由该File对象表示的目录

package com.example.cxy.file;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    private void initView(){
        btn= (Button) findViewById(R.id.button);
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //先实例化一个file对象,参数为路径名
        File file = new File("/mnt/sdcard/Tenect/chenxiaoyang.txt");
        //File file = new File("/mnt/sdcard/Tenect","chenxiaoyang.txt");
        try {
            //判断文件是否存在
            if (file.exists()){
                //文件如果存在删除这个文件
                file.delete();

                Toast.makeText(MainActivity.this, "删除成功了", Toast.LENGTH_SHORT).show();
            }else{
                //创建一个新的文件
                file=new File("/mnt/sdcard/Tenect");
                //先创建文件夹
                file.mkdir();
                //创建这个文件
                file = new File("/mnt/sdcard/Tenect/chenxiaoyang.txt");
                file.createNewFile();
                Toast.makeText(MainActivity.this, "创建成功了", Toast.LENGTH_SHORT).show();
            }
            //获取当前file文件的绝对路径
            Log.i("$$$",file.getAbsolutePath());
            //获取当前file文件的名字,包括后缀名
            Log.i("$$$",file.getName());
            //获取当前file文件的以上所有级的目录
            Log.i("$$$",file.getParent());
            //测试此file文件是否是一个目录
            boolean directory=file.isDirectory();
            Log.i("$$$",String.valueOf(directory));
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(MainActivity.this, "失败了", Toast.LENGTH_SHORT).show();
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.cxy.file.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="写入"
        android:id="@+id/button"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"/>
</RelativeLayout>

 

 

 

 

使用mkdirs创建包括父目录的目录

package com.example.cxy.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        inintView();
    }

    private void inintView() {
        btn= (Button) findViewById(R.id.button);
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //先实例化一个file对象,参数为路径名
        File file=new File("/mnt/sdcard/tmp/one/two/three","test.txt");
        try {
            //判断文件是否存在
            if(file.exists()){
                //文件如果存在删除这个文件
                file.delete();
                Toast.makeText(MainActivity.this,"删除成功", Toast.LENGTH_SHORT).show();
            }else{
                //创建一个新的文件
                file=new File("/mnt/sdcard/tmp/one/tow/three");
                //先创建文件夹,mkdirds可直接创建多级文件夹
                file.mkdirs();
                //创建这个文件
                file=new File("/mnt/sdcard/tmp/one/tow/three/test.txt");
                file.createNewFile();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.cxy.myapplication.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="写入"
        android:id="@+id/button"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="56dp"/>
</RelativeLayout>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值