前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >IO 流最全讲解

IO 流最全讲解

作者头像
帅飞
发布2019-01-22 16:13:58
4620
发布2019-01-22 16:13:58
举报
文章被收录于专栏:Java知其所以然Java知其所以然

原理与基本概念

一、概念

流 : 流动 、流向 从一端移动到另一端(源头与目的地) 程序 与 文件|数组|网络连接|数据库,以程序为中心

二、IO流分类

1、流向: 输入流与输出流

2、数据:

字节流:二进制,可以一切文件 包括 纯文本 doc 音频、视频等等 字符流:文本文件,只能处理纯文本

3、功能:

节点:包裹源头 处理:增强功能,提供性能

注意:我们这里学习的是传统 IO 流,并且是阻塞式 IO。

三、字符流与字节流 (重点) 与文件

1、字节流

输入流: InputStream read(byte[] b) 、read(byte[] b, int off, int len) +close() FileInputStream()

输出流: OutputStream write(byte[] b) write(byte[] b, int off, int len) +flush() +close() FileOutputStream

2、字符流

输入流:

Reader read(char[] cbuf) read(char[] cbuf, int off, int len) +close() FileReader()

输出流:

Writer write(char[] cbuf) write(char[] cbuf, int off, int len) +flush() +close() write(String str, int off, int len) FileWriter()

四、操作

1、举例:搬家 -->读取文件

1)、关联房子 --->建立与文件联系

2)、选择搬家 -->选择对应流

3)、搬家 -->读取|写出

  • a)、卡车大小 --->数组大小
  • b)、运输 -->读取、写出

4)、打发over -->释放资源

2、操作

1)建立联系

2)选择流

3)操作 数组大小+read 、write

4)释放资源

字节流

字节流:可以处理一切文件,包括二进制 音频、视频 、doc等 节点流: InputStream FileInputStream OutputStream FileOutputStream

一、读取文件

1、建立联系 File对象 源头

2、选择流 文件输入流 InputStream FileInputStream

3、操作 : byte[] car =new byte[1024]; +read+读取大小 输出

4、释放资源 :关闭

二、写出文件

1、建立联系 File对象 目的地

2、选择流 文件输出流 OutputStream FileOutputStream

3、操作 : write() +flush

4、释放资源 :关闭

三、文件拷贝(程序为桥梁)

1、建立联系 File对象 源头 目的地

2、选择流

文件输入流 InputStream FileInputStream

文件输出流 OutputStream FileOutputStream

3、操作 : 拷贝

     byte[] flush =new byte[1024]; 
     int len =0;
      while(-1!=(len=输入流.read(flush))){  
         输出流.write(flush,0,len)
      }
     输出流.flush();

4、释放资源 :关闭 两个流

代码如下:
public class CopyFileDemo {

    public static void main(String[] args) {
        String srcPath = "E:/others/helloWorld.java";
        String destPath = "E:/others/myCopy.java";
        try {
            copyFile(srcPath,destPath);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("拷贝文件失败");
        }
    }

    /**
     * 文件的拷贝
     * @param srcPath   源文件路径
     * @param destPath  目录文件路径
     * @throws IOException
     */
    public static void copyFile(String srcPath,String destPath) throws IOException {
        //1、建立联系源(存在且为文件)+ 目的地(文件可以不存在)
        File src = new File(srcPath);
        File dest = new File(destPath);
        copyFile(src,dest);
    }

    /**
     * 文件的拷贝
     * @param src   源文件路径
     * @param dest  目录文件路径
     * @throws IOException
     */
    public static void copyFile(File src,File dest) throws IOException {
        if (!src.isFile()){
            throw new IOException("只能拷贝文件");
        }
        if (dest.isDirectory()){
            throw new IOException(dest.getAbsolutePath()+"不能建立与文件夹同名的文件");
        }
        //2、选择流
        InputStream is = new FileInputStream(src);
        OutputStream os = new FileOutputStream(dest);
        //3、文件拷贝   循环+读取+写出
        byte[] flush = new byte[1024];
        int len = 0;
        //读取
        while (-1!=(len=is.read(flush))){
            //写出
            os.write(flush,0,len);
        }
        //强制刷出
        os.flush();
        //先打开的流后关闭
        os.close();
        is.close();
    }
}
四、文件夹拷贝

1、递归查找子孙级文件|文件夹,并创建文件夹

2、文件复制(IO流复制)

3、分析将 A 文件夹 拷贝到 AA 文件夹中 A / \ a.txt b | b.txt

AA

|

A / \ a.txt b | b.txt

4、不能将父目录拷贝到子目录中

代码如下:
/**
 * 文件夹的拷贝
 * 1、文件 赋值 copyFile
 * 2、文件夹 创建 mkdirs()
 * 3、递归 查找子孙级
 */
public class CopyDir {
    public static void main(String[] args) {
        //源目录
        String srcPath = "e:/others/study";
        //目标目录
        String destPath = "e:/others/test";
        copyDir(srcPath,destPath);
    }

    public static void copyDir(String srcPath,String destPath){
        File src = new File(srcPath);
        File dest = new File(destPath);
        copyDir(src,dest);
    }

    public static void copyDir(File src,File dest){
        if (src.isDirectory()){
            dest = new File(dest,src.getName());
        }
        copyDirDetail(src,dest);
    }

    public static void copyDirDetail(File src,File dest){
        if (src.isFile()){
            try {
                copyFile(src,dest);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else if (src.isDirectory()){
            //确保目标文件夹存在
            dest.mkdirs();
            //获取下一级目录|文件
            for (File sub:src.listFiles()){
                copyDirDetail(sub,new File(dest,sub.getName()));
            }
        }
    }
}

字符流

字符流 : 只能处理纯文本,全部为可见字符 .txt .html 节点流 :

  • Reader FileReader
  • Writer FileWriter
一、纯文本读取

1、建立联系

2、选择流 Reader FileReader

3、读取 char[] flush =new char[1024];

4、关闭

代码如下:
/**
 * 纯文本读取
 * @author Administrator
 *
 */
public class Demo01 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //创建源
        File src =new File("E:/xp/test/a.txt");
        //选择流
        Reader reader =null;
        try {
            reader =new FileReader(src);
            //读取操作
            char[] flush =new char[1024];
            int len =0;
            while(-1!=(len=reader.read(flush))){
                //字符数组转成 字符串
                String str =new String(flush,0,len);
                System.out.println(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("源文件不存在");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("文件读取失败");
        }finally{
            try {
                if (null != reader) {
                    reader.close();
                }
            } catch (Exception e2) {
            }
        }
    }

}
二、纯文本写出

1、建立联系

2、选择流 Writer FileWriter

3、读取 write(字符数组,0,长度)+flush

  • write(字符串)
  • append(字符|字符串)

4、关闭

代码如下:
/**
 * 写出文件
 * @author Administrator
 *
 */
public class Demo02 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //创建源
        File dest =new File("e:/xp/test/char.txt");
        //选择流
        Writer wr =null;
        try {
            //默认 false 为覆盖文件。当指定为 true 时,追加文件,而不是覆盖文件。
            wr =new FileWriter(dest,true);
            //写出
            String msg ="追加...锄禾日当午\r\n码农真辛苦\r\n一本小破书\r\n一读一上午";
            wr.write(msg);
            wr.append("看电视剧 ");
            wr.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if (null != wr) {
                    wr.close();
                }
            } catch (Exception e2) {
            }
        }
    }
}

处理流

处理流:增强功能、提供性能,节点流之上

一、缓冲流

1、字节缓冲流

BufferedInputStream

BufferedOutputStream

2、字符缓冲流

BufferedReader readLine()

BufferedWriter newLine()

二、转换流: 字节流 转为字符流 处理乱码(编码集、解码集)

1、编码与解码概念

编码 : 字符 ---编码字符集>二进制

解码 : 二进制 ---解码字符集->字符

2、乱码:

1)、编码与解码的字符集不统一

2)、字节缺少,长度丢失

3、文件乱码 InputStreamReader(字节输入流,"解码集") OutputStreamWriter(字符输出流,"编码集")

代码如下:
/**
 * 产生乱码的原因
 */
public class ConvertDemo01 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        reason01();
        reason02();
    }

    public static void reason02() throws UnsupportedEncodingException {
        //如果编码解码过程中不指定的话,默认使用平台的字符集,我这里使用的 IDEA,默认字符集为 utf-8
        //解码 byte --> char
        String str = "中国";
        //编码 char --> byte
        byte[] data = str.getBytes();
        System.out.println(new String(data));

        //设定编码字符集
        data = str.getBytes("gbk");
        //编码解码字符集不统一出现乱码
        System.out.println(new String(data));

        //编码
        byte[] data2 = "中国".getBytes("utf-8");
        //解码
        str = new String(data2,"utf-8");
        System.out.println(str);
    }

    public static void reason01() {
        String str = "中国";
        byte[] data = str.getBytes();
        //字节数不完整
        System.out.println(new String(data,0,4));
    }
}

其他流

一、节点流

1、字节数组 字节 节点流

输入流:

ByteArrayInputStream read(byte[] b, int off, int len) + close()

输出流:

ByteArrayOutputStream write(byte[] b, int off, int len) +toByteArray() 不要使用多态

代码如下:
/**
 * 字节数组 节点流
 * 数组的长度有限,数据量不会很大
 */
public class ByteArrayDemo01 {

    public static void main(String[] args) throws IOException {
        read(write());
    }

    /**
     * 输入流 操作与 文件输入流操作一致
     * 读取字节数组
     */
    public static void read(byte[] src) throws IOException {
        //选择流
        InputStream is = new BufferedInputStream(
                new ByteArrayInputStream(src)
        );
        //操作
        byte[] flush = new byte[1024];
        int len = 0;
        while (-1 != (len = is.read(flush))){
            System.out.println(new String(flush,0,len));
        }
    }

    public static byte[] write() throws IOException {
        //目的地
        byte[] dest;
        //选择流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //操作写出
        String msg = "我是啦啦啦啦";
        byte[] info = msg.getBytes();
        bos.write(info,0,info.length);
        //获取数据
        dest = bos.toByteArray();
        //释放资源
        bos.close();
        return dest;
    }
}
二、处理流

1、基本类型+String 保留数据+类型

输入流:DataInputStream readXxx

输出流:DataOutputStream writeXxx

2、引用类型 (对象) 保留数据+类型

反序列化 输入流:ObjectInputStream readObject()

序列化 输出流:ObjectOutputStream writeObject()

注意: 1)、先序列化后反序列化;反序列化顺序必须与序列化一致

2)、不是所有的对象都可以序列化,实现了 java.io.Serializable 这个接口的类才可以被序列化

3)、不是所有的属性都需要序列化,有 transient 关键字的属性就不会被序列化。

3、打印流 PrintStream println() print()

4、三个常量 :

System.in |out|err

System.setIn() |setOut() |setErr()

关闭方法

编写工具类,实现关闭流的功能。

public class FileUtil {

    //基于多态实现关闭流的功能
    public static void close(Closeable ... io){
        for (Closeable temp:io){
            try {
                if (temp != null) {
                    temp.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //基于泛型方法实现关闭流的功能
    public static <T extends Closeable> void closeAll(T ... io){
        for (T temp:io){
            try {
                if (temp != null) {
                    temp.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

总结

一、步骤: 创建源 选择流 操作(读取|写出) 释放
二、流

节点流:离数据源|程序最近的流 1、字节流:可以处理一切(纯文本、音频、视频等) 1)、输入流 InputStream FileInputStream ByteArrayInputStream 操作:read(字节数组) a)、中间容器 byte[] flush=new byte[长度] b)、接收长度 int len =0; c)、循环读取 while(-1!=(len=流.read(flush))){} d)、操作:输出、拷贝 2)、输出流 OutputStream FileOutputStream ByteArrayOutputStream 操作:write(字节数组,0,长度) 输出 2、字符流:只能处理纯文本 1)、输入流:Reader FileReader 操作:read(字符数组) a)、中间容器 char[] flush=new char[长度] b)、接收长度 int len =0; c)、循环读取 while(-1!=(len=流.read(flush))){} d)、操作:输出、拷贝 2)、输出流:Writer FileWriter 操作:write(字符数组,0,长度) 输出 处理流: 装饰模式 提高性能增强功能 1、转换流:解码与编码字符集问题 1)、输入流:InputStreamReader ->解码 2)、输出流:OutputStreamWriter ->编码 2、缓冲流:提高性能 1)、输入流:BufferedInputStream BufferedReader 2)、输出流:BufferedOutputStream BufferedWriter 3、处理数据+类型 1)、基本数据类型 + 字符串:必须存在才能读取,读取与写出顺序必须一致 a)、输入流:DataInputStream readXxx b)、输出流:DataOutputStream writeXxx 2)、引用类型:Serializable transient a)、反序列化:ObjectInputStream readObject b)、序列化:ObjectOutputStream writeObject 4、打印流: PrintStream 5、System.in out err setIn setOut 以下流使用新增方法时不能发生多态 ByteArrayOutputStream: toByteArray() BufferedReader: readLine() BufferedWriter:newLine() DataInputStream DataOutputStream ObjectInputStream ObjectOutputStream PrintStream

三、重点
四、操作

0、打印文件|目录

1、文件拷贝

2、关闭流方法

3、文件分割与合并

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java知其所以然 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原理与基本概念
    • 一、概念
      • 二、IO流分类
        • 三、字符流与字节流 (重点) 与文件
          • 四、操作
            • 一、读取文件
        • 字节流
          • 二、写出文件
            • 三、文件拷贝(程序为桥梁)
              • 代码如下:
                • 四、文件夹拷贝
                  • 代码如下:
                  • 字符流
                    • 一、纯文本读取
                      • 代码如下:
                        • 二、纯文本写出
                          • 代码如下:
                          • 处理流
                            • 一、缓冲流
                              • 二、转换流: 字节流 转为字符流 处理乱码(编码集、解码集)
                                • 代码如下:
                                • 其他流
                                  • 一、节点流
                                    • 代码如下:
                                      • 二、处理流
                                      • 关闭方法
                                      • 总结
                                        • 一、步骤: 创建源 选择流 操作(读取|写出) 释放
                                          • 二、流
                                            • 三、重点
                                            • 四、操作
                                        相关产品与服务
                                        容器服务
                                        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                                        领券
                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档