I/O流

I/O流

I/O流概述

IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的对象都在IO包中
流按流向划分: 输入流,输出流
流按读写数据类型划分: 字节流,字符流


字节流:

可以读写任意类型的文件

输出流

例:创建并写入一个数据的文件

public class Mydemo3 {
    public static void main(String[] args) throws IOException {
        // 1)创建一个向指定 File 对象表示的文件中写入数据的文件输出流
        File file = new File("a.txt");
        FileOutputStream out1 = new FileOutputStream(file);
        // 2)直接传入一个文件路径,如果该文件不存在则创建
        FileOutputStream out2 = new FileOutputStream("D:\\b.txt");
        //若下次写入时数据不被覆盖,则添加参数true
        FileOutputStream out3 = new FileOutputStream("D:\\c.txt",true);

        out1.write(98);
        out1.write("Hello World!".getBytes());
        //注意:一个汉字占三个字节(平台默认UTF-8编码)
        out1.write("爱生活,爱Java".getBytes(),0,9);
        out1.close();
    }
}

不同系统下换行注意:

        out1.write("\r\n".getBytes()); //Windows系统换行
        out1.write("\n".getBytes());   //Linux系统换行
        out1.write("\r".getBytes());   //Mac系统换行

例:流的异常处理
方式一:捕获处理异常

public class MyDemo4 {
    public static void main(String[] args) {
        FileOutputStream out = null;
        try {
            out = new FileOutputStream("a.txt");
            out.write("java".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(out!=null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

方式一:向上抛出异常

public class MyDemo5 {
    public static void main(String[] args) throws IOException {
        FileOutputStream out = new FileOutputStream("a.txt");
        out.write("java".getBytes());
        out.close();
    }
}
输入流

从文件系统中的某个文件中获得输入字节

public class MyDemo6 {
    public static void main(String[] args) throws IOException {
        FileInputStream in = new FileInputStream("a.txt");
        //读取数据方式一: 一次读一个字节,如果读超了则返回-1
        in.read();
        //读取数据方式二: 一次读一个字节数组 字节数组相当于一个缓冲区
        byte[] bytes = new byte[1024];
        int len=in.read(bytes);//len返回有效读取长度

        //遍历读出的数据
        String s = new String(bytes, 0, len);
        System.out.println(s);
    }
}

例:复制文件

public class MyDemo7 {
    public static void main(String[] args) throws IOException {
        //方式一:一次读取一个字节,写一个字节来复制,效率低
        //方式二:一次读取一个字节数组,写一个字节数组(以下代码采用此种方式)
        FileInputStream in = new FileInputStream("a.txt");
        FileOutputStream out = new FileOutputStream("b.txt");
        //创建一个字节缓冲区
        byte[] bytes = new byte[1024];
        int len=0;
        while ((len=in.read(bytes))!=-1){
            out.write(bytes,0,len);
            out.flush();
        }
        in.close();
        out.close();
    }
}

例:高效的输入、出流

BufferedInputStream与BufferedOutputStream

public class MyDemo8 {
    public static void main(String[] args) throws IOException {
        BufferedInputStream in = new BufferedInputStream(new FileInputStream("a.txt"));
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("c.txt"));
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = in.read(bytes)) != -1) {
            out.write(bytes, 0, len);
            out.flush();
        }
        in.close();
        out.close();
    }
}

对时间效率差异的解释:
  BufferedInputStream比FileInputStream多了一个缓冲区,执行read时先从缓冲区读取,当缓冲区数据读完时再把缓冲区填满。
  因此,当每次读取的数据量很小时,FileInputStream每次都是从硬盘读入,而BufferedInputStream大部分是从缓冲区读入。读取内存速度比读取硬盘速度快得多,因此BufferedInputStream效率高。
  BufferedInputStream的默认缓冲区大小是8192字节。当每次读取数据量接近或远超这个值时,两者效率就没有明显差别了


字符流:

Writer与Reader

只能读写文本文件
字符流=字节流+编码表

编码:文本=》字节
解码:字节=》文本

public class MyDemo9 {
    public static void main(String[] args) {
        //编码:
        byte[] bytes = "爱生活,爱Java".getBytes();//平台默认编码
        for (byte aByte : bytes) {
            System.out.println(aByte);
        }
        //解码:
        String str = new String(bytes);
        System.out.println(str);
    }
}
public class MyDemo9 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        //指定编码形式,注意编解码要一致
        byte[] bytes = "爱生活,爱Java".getBytes("gbk");
        String str = new String(bytes, "gbk");
        System.out.println(str);
    }
}

例:字符流的文件复制

public class MyDemo1 {
    public static void main(String[] args) throws IOException {
        //字符流复制
        InputStreamReader in = new InputStreamReader(new FileInputStream("a.txt"));
        OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("d.txt"));
        char[] chars = new char[100];
        int len = 0;
        while ((len = in.read(chars)) != -1) {
            out.write(chars, 0, len);
            out.flush();
        }
        in.close();
        out.close();
    }
}

例:高效的字符流
BufferedReader与BufferedWriter

public class MyDemo2 {
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new FileReader("a.txt"));
        BufferedWriter out = new BufferedWriter(new FileWriter("e.txt"));
        String line=null;//记录每次读取一行文本
        while ((line=in.readLine())!=null){
            out.write(line);
            out.newLine();//换行
            out.flush();
        }
        in.close();
        out.close();
    }
}

注意
父类:InputStreamReader 与OutputStreamWriter
||
子类(不能指定编码):FileReader与FileWriter