Java IO常见用法

初始IO流

I/O流(Input/Output)流,通常用于处理设备间的数据传输,如读写文件,网路通讯等,如下图演示文件读写:
在这里插入图片描述
简单来说就是Java程序将磁盘上的文件通过流读到内存层面称为Input流(输入流);Java程序将内存层面的数据通过流持久化到磁盘文件称为Output流(输出流)

流的分类

按操作数据单位:字节流、字符流
按数据的流向:输入流、输出流
按流的角色:节点流、处理流

流的体系结构

在这里插入图片描述
节点流以及处理流都继承抽象基类,只需实例化节点流或处理流即可对文件进行操作,除开抽象基类,节点流和处理流使用步骤基本一致。而节点流也是最基础的流处理类,处理流则是包裹在节点流外层,提升读写的效率。所以在开发中,多使用缓冲流(处理流)

文件操作

  • 文件读入
    /**
     * 文件读入
     * @throws Exception
     */
    @Test
    public void  myTest()  throws  Exception {

        File file=new File("test.txt");
        //字符读入流
        FileReader reader=new FileReader(file);

        char[]data=new char[5];
        //返回每次读到char[]中的字符个数,如果读到文件末尾,则返回-1
        int len ;
        while ((len=reader.read(data))!=-1){
            String str=new String(data,0,len);//这里的len是指读到char[]中的字符个数,而不是char[]的长度
            System.out.println(str);
        }
    }
  • 文件写出
/**
     * 文件写出
     * @throws IOException
     */
    @Test
    public void testWriter()throws  IOException{

        //如果文件不存在,在流写入时会自动创建
        File file=new File("my.txt");

        //写出流:append:默认为false,对原有文件进行覆盖;若为true,对原有文件进行追加
        FileWriter writer=new FileWriter(file,false);

        writer.write("helloworld\n");
        writer.write("helloxf");

        writer.close();
    }
  • 文件数据读写
/**
     * 文件数据读写
     */
    @Test
    public  void  testWriteAndRead(){

        File  srcFile=new File("test.txt");
        File  destFile=new File("my.txt");
        FileReader reader=null;
        FileWriter writer=null;
        try {
            //读入流
             reader=new FileReader(srcFile);
            //写出流
            writer=new FileWriter(destFile,true);

            //数据的读入和输出
            char[]data=new char[5]; //记录每次读入到数组的字符个数
            int len;
            while ((len=reader.read(data))!=-1){

                writer.write(data,0,len);  //输出len个数据
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer!=null)
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (reader!=null)
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  • 图片复制
 @Test
    public void  transferImg(){
        File  srcImg =new File("xf.png");
        File  destImg =new File("xf2.png");
        FileInputStream inputStream=null;
        FileOutputStream outputStream=null;
        try {
            inputStream=new FileInputStream(srcImg);

             outputStream=new FileOutputStream(destImg);

            byte[]data=new byte[100];
            int len;
            while ((len=inputStream.read(data))!=-1){

                outputStream.write(data,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream!=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

对于文本文件(.txt,.c++,.js),用字符流处理(FileReader/FileWriter);对于非文本文件(.jpg,.jar),用字节流处理(FileInputStream/FileOutputStream)

缓冲流的使用

/**
 * 缓冲流的使用:提升读写的效率
 * BufferInputStream
 */
public class BufferTest {

    /**
     * 缓冲流处理
     * @param file1
     * @param file2
     */
    public void copyBufferedStream(String file1,String file2){
        FileInputStream inputStream=null;
        FileOutputStream outputStream=null;

        BufferedInputStream bufferedInputStream=null;

        BufferedOutputStream bufferedOutputStream=null;
        try {
            File srcFile=new File(file1);
            File destFile=new File(file2);
            inputStream=new FileInputStream(srcFile);
            outputStream=new FileOutputStream(destFile);

            //包装缓冲流
            bufferedInputStream=new BufferedInputStream(inputStream);
            bufferedOutputStream=new BufferedOutputStream(outputStream);
            byte[]data=new byte[1024];
            int len;
            while ((len=bufferedInputStream.read(data))!=-1){
                bufferedOutputStream.write(data,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bufferedInputStream!=null){
                try {
                    bufferedInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedOutputStream!=null){
                try {
                    bufferedOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    }
    /**
     * 字节流处理
     * @param file1
     * @param file2
     */
    public void copyStream(String file1,String file2){

        FileInputStream inputStream=null;
        FileOutputStream outputStream=null;

        try {
            File srcFile=new File(file1);
            File destFile=new File(file2);
            inputStream=new FileInputStream(srcFile);
            outputStream=new FileOutputStream(destFile);


            byte[]data=new byte[1024];
            int len;
            while ((len=inputStream.read(data))!=-1){
                outputStream.write(data,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //字节流测试
            if (inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream!=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    @Test
    public void  testStream(){

        long startTime=System.currentTimeMillis();
        String str1="E:\\xf\\resQuality.jar";
        String str2="E:\\xf\\resQuality1.jar";
        copyBufferedStream(str1,str2);
	    //copyStream(str1,str2);
        long endTime=System.currentTimeMillis();

        System.out.println("复制文件花费:"+(endTime-startTime)+"ms");
    }

}

经过测试发现,加上缓冲流文件操作的效率提升近3倍,所以在开发中,一般多选择缓冲流(处理流的一种)居多

处理流

前面提到缓冲流,也是处理流的一种,除此之外,处理流也还有其他

  • 转换流
    属于字符流,提供字符与字节的转换
    InputStreamReader:将一个字节的输入流转为字符的输入流
    OutputStreamWriter:将一个字符的输出路转为字节的输出流
    接着我们尝试实现用转换流实现文件的读写
    在这里插入图片描述
@Test
    public void  convertFileContent()throws  IOException{
        //1.造流,造文件
        File srcFile=new File("utf-8.txt");
        File destFile=new File("gbk.txt");

        FileInputStream inputStream=new FileInputStream(srcFile);

        FileOutputStream outputStream=new FileOutputStream(destFile);

        InputStreamReader inputStreamReader=new InputStreamReader(inputStream,"utf-8");

        OutputStreamWriter outputStreamWriter=new OutputStreamWriter(outputStream,"gbk");

        //2.数据读写
        char[]data=new char[20];

        int len;
        while ((len=inputStreamReader.read(data))!=-1){
            outputStreamWriter.write(data,0,len);
        }

        //3.资源关闭
        inputStreamReader.close();
        outputStreamWriter.close(); 
    }

实现将utf-8文件转为gbk格式文件后,我们用IDEA打开,会出现乱码,这就实现了上述需求
在这里插入图片描述

对象流

ObjectInputStream和ObjectOutputStream;用于存储和读取基本数据类型或对象的处理流,并且实现对象序列化和反序列化的过程。
序列化:将Java对象转化为与平台无关的二进制流保存到磁盘或通过网络进行传输,使用ObjectOutputStream实现
反序列化:通过读取文件或网络获取对象二进制流并还原为Java对象的过程;使用ObjectInputStrea实现
注:要能实现对象序列化和反序列化的前提就是该对象支持序列化机制,具体做法就是使该Java对象实现Serializable接口,并提供一个全局序列化版本号,类的各个属性也支持序列化机制(默认情况下,基本数据类型支持序列化机制)。例如下面的Java对象:

/**
 * User类支持序列化机制
 */
public class User implements Serializable {

    public  static final long serialVersionUID = 21321312312L; //序列版本号
    private  int id;
    private  String username;
    private  String password;

    public User() {
    }

    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

第三方Jar包支持文件操作

上面我们都是自己通过流来对文件进行操作,步骤都代替都基本一致:获取文件->创建流->数据的读写->关闭资源。但实际开发中,我们可以直接借用第三方提供的Jar包实现对文件的操作,底层封装了文件的操作的以上步骤,我们只需调用相应的方法即可。

  • 导入依赖
  <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>
  • 文件复制
 /**
     * FileUtils操作文件
     * @param args
     */
    public static void main(String[] args) {
        //通过工具类获取File对象
        File file1 = FileUtils.getFile("my.txt");

        File file2 = FileUtils.getFile("my2.txt");

        //文件复制

        try {
            FileUtils.copyFile(file1,file2);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
  • copyFile源码
private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException {
        if (destFile.exists() && destFile.isDirectory()) {
            throw new IOException("Destination '" + destFile + "' exists but is a directory");
        } else {
            FileInputStream fis = null;
            FileOutputStream fos = null;
            FileChannel input = null;
            FileChannel output = null;

            try {
                fis = new FileInputStream(srcFile);
                fos = new FileOutputStream(destFile);
                input = fis.getChannel();
                output = fos.getChannel();
                long size = input.size();
                long pos = 0L;

                for(long count = 0L; pos < size; pos += output.transferFrom(input, pos, count)) {
                    count = size - pos > 31457280L ? 31457280L : size - pos;
                }
            } finally {
                IOUtils.closeQuietly(output);
                IOUtils.closeQuietly(fos);
                IOUtils.closeQuietly(input);
                IOUtils.closeQuietly(fis);
            }

            if (srcFile.length() != destFile.length()) {
                throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'");
            } else {
                if (preserveFileDate) {
                    destFile.setLastModified(srcFile.lastModified());
                }

            }
        }
    }

通过源码我们看到,底层封装了前面的文件操作的步骤,并在该基础上,提供了更多新的特性,封装许多方法,第三方提供的API更强大,推荐在项目中使用。
在这里插入图片描述

总结

了解流的概念,熟练使用jdk提供的API来操作文件的读写。熟悉流的分类,并通过导入第三方工具包,实现对文件的操作

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值