【Java IO】字节流,以及自己实现数据拷贝

字节(byte)流:InputStream、OutputStream 原生操作,不需要处理
字符(char)流:Reader、Writer通过转换来的,需要中间处理
所有流在使用后一定要关闭。(不然会占用白白内存)一般出现在finally代码块中关闭流,保证流无论是否产生异常一定会被关闭。
应用场景:
字符流用于文字处理,尤其是处理中文的时候处理较好,除此之外所有的流处理均使用字节流(磁盘数据存储、网络传输)

流操作模式:

  1. 取得终端对象
  2. 取得输入输出流
  3. 进行数据的输入与输出
  4. 关闭流

1.字节输出流

OutputStream 类的定义结构:
public abstract class OutputStream implements Closeable, Flushable
OutputStream类实现了Closeable,Flushable两个接口,这两个接口中的方法:
1.Closeable:
public void close() throws IOException;
2. Flushable:
public void flush() throws IOException;
OutputStream类中的其他方法:
3. 将给定的字节数组内容全部输出:
public void write(byte b[]) throws IOException
4. 将部分字节数组内容输出:
public void write(byte b[], int off, int len) throws IOException
5. 输出单个字节:
public abstract void write(int b) throws IOException;
由于OutputStream是一个抽象类,所以要想为父类实例化,就必须要使用子类。如果要进行文件的操作,可以使用FileOutputStream类来处理,这个类的构造方法如下:

  1. 接收File类(覆盖):
    public FileOutputStream(File file) throws FileNotFoundException
  2. 接收File类(追加):
    public FileOutputStream(File file, boolean append)
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class OutputStreamTest {
    public static void main(String[] args) throws IOException {
        //1. 取得终端对象
        File file = new File(File.separator +  "F" + File.separator +
       					"Users" +  File.separator+ "FWB" + File.separator
       					 + "Desktop" + File.separator + "OutputStreamTest.txt");					 		
        //有输出流以后不需要手动创建文件,只要路径正确会自动创建
        //虽然文件可以自动创建,但是文件夹不行,需要手动创建
        //2. 取得相应终端的输出流,
        OutputStream out = new FileOutputStream(file);//覆盖模式
        //当再次执行此方法会默认覆盖,只需将 FileOutputStream默认值设置为true就改成在后面增加的模式
       	//OutputStream out = new FileOutputStream(file,true);追加模式
        //3. 将数据通过输出流输出
        //getBytes(),将字符串以字节数组的形式返回
        out.write("hello world".getBytes());
        //4. 关闭流
        out.close();
    }
}
字节输出流优化:

由于write方法只支持字符数组,所以使用起来有些不方便,我们可以将OutputStream这个类做一个简单的二次封装。
思路:通过valueOf()方法将其他类型转换为String类,String类再通过getBytes()将字符串转换为字符数组。

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

class MyPrint{
    private OutputStream out;

    public MyPrint(OutputStream out){
        this.out = out;
    }

    public void print(String str) throws IOException {
        this.out.write(str.getBytes());
    }

    public void println(String str) throws IOException {
        this.print(str + "\n");
    }
    public void print(double data) throws IOException {
        this.print(String.valueOf(data));
    }

    public void println(double data) throws IOException {
        this.print(data + "\n");
    }

    public void close() throws IOException {
        this.out.close();
    }

}
public class betterOut {
    public static void main(String[] args) throws IOException {
        //1. 取得终端对象
        File file = new File(File.separator + "F" + File.separator + "Users" + File.separator
                + "fwb" + File.separator + "Desktop" + File.separator + "betterOut.txt");
        MyPrint myPrint = new MyPrint(new FileOutputStream(file));
        myPrint.print("乔奶奶好");
        myPrint.println(10.2322);
        myPrint.close();
    }
}

在JDK1.7后追加了AutoCloseable接口,自动调用close方法
AutoCloseable接口必须处在try代码块才会自动调用close()

package fwb.inAndOut;

class Myclass implements AutoCloseable{
    @Override
    public void close() throws Exception {
        System.out.println("自动");
    }
    public void print(){
        System.out.println("显示调用");
    }
}

public class AutoCloseableTest {
    public static void main(String[] args) {
        Myclass myclass = new Myclass();
        //写在外面并不会自动追加
        myclass.print();
        System.out.println("---------------------");
        //必须写在在try代码块中
        try( Myclass myclass1 = new Myclass();) {
            myclass1.print();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果:
在这里插入图片描述

2. 字节输入流

int read():读取一个字节
int read(byte b[]):一次读取多个字节并将数据存放到字节数组中,返回此次读取的长度。(可以理解为用勺子吃饭,勺子就是缓冲区,碗中的饭就是总大小)

  1. 返回b.length:此时要读取的数据大小大于缓冲区字节数组的大小(碗中剩余食物大于勺子容量)
  2. 返回读取个数:此时要读取的的数据小于缓冲区字节数组大小
    (剩下的饭一勺子舀不完)
  3. 返回 -1 :此时数据已经全部读取完毕
import java.io.*;

public class InputStreamTest {
    public static void main(String[] args) {
        //1. 取得终端对象
        File file = new File(File.separator + "F" + File.separator + "Users" + File.separator
                + "FWB" + File.separator + "Desktop" + File.separator + "OutputStreamTest.txt");
        //2. 取得输入流
        InputStream in = null;
        try {
            in = new FileInputStream(file);
            // 3.读取数据
            int len = 0;
            byte[] data = new byte[1024];//缓冲区
            try {
                len = in.read(data);//将读入的数据存放在data中
                System.out.println("文件内容为:" + new String(data,0,len));//从0到有长度的地方即可
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}
数据拷贝:
import java.io.*;

/**
 * @program: Io
 * @description: 使用字节输入输出流进行文件拷贝
 * @author: fwb
 * @create: 2019-07-31 19:27
 **/
public class copyTest {
    public static void main(String[] args) throws IOException {
        //传进来的的文件必须是2个,一个输入一个输出
        if (args.length != 2){
            System.out.println("参数非法");
        }
        //源文件
        File sourceFile  = new File(args[0]);
        //目标文件
        File destFile = new File(args[1]);
        InputStream in = new FileInputStream(sourceFile);
        OutputStream out = new FileOutputStream(destFile);
        //文件拷贝
        copyFile(in,out);
    }

    //选择接受最顶底层的抽象类(InputStream in,OutputStream out),而不是具体的文件输入输出流这个类的原因是:如果以后有从网络、内存而来的都可以使用,而不是只能接收从文件来的
    private static void copyFile(InputStream in,OutputStream out) throws IOException {
        System.out.println("文件拷贝开始");
        long start = System.currentTimeMillis();//开始拷贝时间
        int len = 0;
//      //边读边写,当被读取的文件长度不等于 -1就代表还有数据读,这种方法默认一次一个字节的文件,会非常慢
//        while((len = in.read() )!= -1){
//            out.write(len);
//        }
        //开一个缓冲区可以快一点,但是并不是说缓冲区越大越快
        byte[] data = new byte[1024];
        while((len = in.read(data))!= -1){
            out.write(data,0,len);
        }
        long end = System.currentTimeMillis();//结束拷贝时间
        System.out.println("文件拷贝结束,共耗时" + (end - start) + "ms");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我顶得了

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

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

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

打赏作者

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

抵扣说明:

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

余额充值