Java#IO流(Input,Output)

目录

1、什么是IO流

2、IO流重点字节流和字符流

2.1 字节流

 2.2 字节输入流

2.3 字符流

3、IO流的总体结构图

4、IO流的索引头 (File)

5、解决编码乱码的问题

6、IO流的操作步骤

7、文件字节流

8、文件流

9、文件字符输出流

10、数组流

11、缓冲流

12、转换流

13、数据流

14、对象流和序列化


1、什么是IO流

io流是程序对文件进行的输入输出的操作,Input,Output。

简单的说:输入流Reader,InputStream。输出流Writer,OutputStream。是程序与外部设备之间的数据传递过程。而输入流/输出流都是抽象的基类,无法直接创建实列。

2、IO流重点字节流和字符流

2.1 字节流

字节流就是InoutStream, OutputStream,在输入输出的基础上加上了Stream“流”。

字节流、字符流处理数据的单位:

  • 字节流:一次读或写1字节的数据,也就是8位二进制,常见的有:视频、音频、图片、PDF、Excel
  • 字符流:一次读或写1个字符,也就是至少1字节的数据(因为汉字是有占2-3字节的),也就是大于8位的二进制。常见的有文本.txt
  • 图片

字节流、字符流改变过程:

在进行网络数据传输、硬盘数据保存所支持的数据类型只有:字节。

而所有磁盘中的数据必须先读取到内存后才能进行操作,这时候内存会帮助我们把字节变成字符。而字符更容易处理中文。

两者的区别:

  • 字节流和字符流操作的本质区别只有一个:字节流是原生的操作,字符流是经过处理后的操作。
  • 字节流和字符流的区别在于数据处理单位的不同。一个是1字节一个2字节。

按照流向方向划分为:输入流、输出流。 

  • 输入流:硬盘数据读入程序中。相对程序而言的,外部传入数据给程序需要借助输入流。
  • 输出流:程序写出到硬盘上,相对程序而言的,程序把数据传输到外部需要借助输出流。

 2.2 字节输入流

思路:InputStream这个类是表示输入字节流的所有类的超类,掌握这个就基本掌握其他类了。

按找功能不同。

输入流可划分为

节点流和包装流。

节点流:我可以向某一个特定的地方(也称作为节点)读取内部数据。

包装流也叫做(处理流),简单的说,包装流就是用来包装节点流的。

它的作用就是对节点流进行包装处理,然后也增加了一些功能,是一种典型的装饰器设计模式。

处理流:它也叫做高级流或包装流,处理流对一个已存在的流进行连接,通过封装后的流来进行读写。

图片:

节点流直接通过程序操作数据源

        包装流通过包装后,在通过节点流操作数据

图片参考:JAVA IO流 - 屌丝迷途 - 博客园 (cnblogs.com)

节点流的常用类:

FileInputStream、ByteArrayInputStream基本都是父类的方法,只是某些使用场景略有不同。

文件:FileInputStream,读取文件内容的适合使用。

字节数组:ByteArrayInputStream,读取字节数组的时候使用。

包装流的常用类:

SequenceInputStream:序列流。

ObjectInputStream:对象反序列化流。

什么是序列化、反序列化?

序列化:将Java对象保存到硬盘上。

反序列化:从硬盘上转化成Java对象。

参考:java IO笔记(序列化与ObjectInputStream、ObjectOutputStream) - moonfish - 博客园 (cnblogs.com)

BufferedInputStream:缓冲输入流。

这个缓冲流为另一个输入流添加了功能,即缓冲输入和支持mark和reset方法的功能。

DataInoutStream:数据流。

它提供了可以直接传输功能,基本数据类型的功能,不需要提前转换,可以直接读取到数据内容。

使用数据输入流“包装”“文件输入流”获取数据,可以直接读取到指定的类型数据。

2.3 字符流

和上面的字节流差不多,但是它使用的常见不太一样。

输入流(Reader)

节点流:

在字符流中,需要注意的是,没有字节数组流(ByteArrayInputStream)只有字符数组流(CharArrayReader)

FileReader是节点流,但是它的父类InputStreamReader是包装流

InputStreamReader:字符输入流(字节流到字符流的桥梁)

FileReader;文件流:在文件字符输入读取时使用。

CharArrayReader:字符数组流;用于字符数组的读取。

包装流:

StringReader:字符串流;读取字符串时使用。

InputStreamReader:字符输入流(字节流到字符流的桥梁)

输出流(Writer)

FileWriter是节点流,父类OutputStreamWriter是包装流。

BufferedWriter:将对象的格式表示打印到文本输出流。(缓冲流)

PrintWriter:将对象的格式表示打印到文本输出流。和PrintStream类似,但是他不会自动刷新

StringWriter:在字符串缓冲区中收集其输出的字符流,然后可以用于构造字符串。(读取字符串使用)

OutputStreamWriter:字符输出流(字节流到字符流的桥梁)

FileWriter:文件字符输写出。

3、IO流的总体结构图

操作的是字节:InputStream,OutputStream。

操作的是文本:Reader,Writer。

 图上:

4、IO流的索引头 (File)

File文件类,因为io的引介都是围绕着文件的,所有File文件类就是必不可少的了。

常用的三个File类的构造方法。

Constructor and Description File(File parent, String child) // 从父抽象路径名和子路径名字符串创建新的 File实例。

File(String pathname) // 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。

File(String parent, String child) // 从父路径名字符串和子路径名字符串创建新的 File实例。

File文件类-从文件出发,到文件结束,而文件创建的意义就是;不存在才创建,存在后才创建成功。

File src = new File("C:/Users/lei/IdeaProjects/项目名/文件存放的位置/包名/类名");

boolean flag = src.createNewFile(); System.out.println(flag); src.delete(); // 删除已创建的相关文件

boolean createNewFile() //当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。 bollean delete(); //删除已创建的相关文件。

文件的长度计算,是通过字节数来计算的。

File src = new File("C:/Users/lei/IdeaProjects/IO多网/src/io流/PathIo.java");
System.out.println("长度:"+src.length());  // length 文件的字节数
 src = new File("C:/Users/lei/IdeaProjects/IO多网/");
System.out.println("长度:"+src.length());

long length();返回由此抽象路径名表示的文件的长度。

File的使用:

  1. exists();是否存在

  2. isFile();是否是文件

  3. isDirectory();是否是文件夹

    File src = new File("src/io流/PathIo.java");
           System.out.println("是否存在:"+src.exists());
           System.out.println("是否文件:"+src.isFile());
           System.out.println("是否文件夹:"+src.isDirectory());

  4. getName(); 返回名称

  5. getPath(); 返回一个相对路径

  6. getAbsolutePath(); 返回一个绝对路径

  7. getParent(); 返回他的上一级

    File src = new File("C:/Users/lei/IdeaProjects/IO多网/src/io流/PathIo.java");
    System.out.println("名称:"+src.getName()); // 返回名称
    System.out.println("路径:"+src.getPath());  // 返回一个相对路径
    System.out.println("绝对路径:"+src.getAbsolutePath()); // 返回一个绝对路径
    System.out.println("父路径:"+src.getParent());   // 返回他的上一级

5、解决编码乱码的问题

常用的编码有(ASKLL ,GBK ,UTF-8等)

如何解决编码乱码的问题呢,首先我们要知道编码乱的原因。

乱码产生的原因分两种,一是字数不够了,这样程序运行的时候就会出现少一个字节问题,从而产生乱码的问题,二是字符集不同,比如JVM要的是UTF-8的编码,你给了GBK的编码,也会产生乱码问题。

// 乱码 字数不够
msg = new String(datas, 0, datas.length - 1, "UTF8");
System.out.println(msg)**;
msg = new String(datas, 0, datas.length - 2, "UTF8");
System.out.println(msg);
// 字符集不统一。产生乱码
msg = new String(datas, 0, datas.length - 2, "gbk");

6、IO流的操作步骤

Reader和InputStream输入流,Writer和OutputStream输出流都是类的模板,知道了操作步骤,剩下的流就容易理解了:

  1. 创建源。
  2. 选择要使用的流。
  3. 操作或(读取字节的数组)。
  4. 释放资源。

1)使用方法

int read(); //从该输入流读取一个字节的数据。

void close(); //关闭此文件输入流并释放与流相关联的任何系统资源。

public static void main(String[] args) {
        File src = new File("abc.txt"); // 创建源
        InputStream is = null;  // 选择流
        try {
            is = new FileInputStream(src);  // 操作(读取字节的数据)
            int a;
            while ((a = is.read()) != -1) {
                System.out.print((char) a);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();  // 释放资源
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

7、文件字节流

FileInputStream (通过字节的方式读取文件,适合读取所有类型的文件(图像,视频等)全字符考虑FileReader)。

构造方法:

protected FilterInputStream(InputStream in) 通过将参数 in到字段 this.in创建一个 FilterInputStream ,以便将其记住以供以后使用。

FileoutputStream (通过字节的方式写出或追加数据到文件,适合所有类型的文件(图像,视频等),全字符考虑FileWriter)。

构造方法

  1. FileOutputStream(File file); 创建文件输出流以写入由指定的 File对象表示的文件。
  2. FileOutputStream(File file, boolean append); 创建文件输出流以写入由指定的 File对象表示的文件。
  3. FileOutputStream(FileDescriptor fdObj); 创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。
  4. FileOutputStream(String name); 创建文件输出流以指定的名称写入文件。
  5. FileOutputStream(String name, boolean append);创建文件输出流以指定的名称写入文件。

使用方法

void flush(); // 刷新此输出流,并强制将任何缓冲的输出字节写入流。

void write(byte[] b); // 将 b.length个字节写入此输出流。

File dest = new File("cbc.txt"); 
        OutputStream os = null;  
        try {
            os = new FileOutputStream(dest, true);            
            String msg = "I have a wantPeople\r\n";  // 通过字节的方式写出或追加数据到文件
            byte[] flush = msg.getBytes();
            os.write(flush, 0, flush.length);
            os.flush();

8、文件流

文件字符输入流;

构造方法

  1. FileReader(File file); 创建一个新的 FileReader ,给出 File读取。 FileReader(FileDescriptor fd); 创建一个新的 FileReader ,给定 FileDescriptor读取。 FileReader(String fileName); 创建一个新的 FileReader ,给定要读取的文件的名称。
    File src = new File("cbc.txt");
            Reader reader = null;
            try {
                reader = new FileReader(src);
                char[] car = new char[2];  // 缓冲容器
                int len = -1; //接收长度
                int temp;
                while ((len = reader.read(car)) != -1) {
                // 字符数组--->字符串              
                    String ctr = new String(car, 0, len);
                    System.out.println(ctr);
  2. 用Reader把文件中的信息读取出来。要注意读取的长度。

9、文件字符输出流

构造方法:

FileWriter(File file); 给一个File对象构造一个FileWriter对象。
FileWriter(File file, boolean append); 给一个File对象构造一个FileWriter对象。
FileWriter(FileDescriptor fd); 构造与文件描述符关联的FileWriter对象。
FileWriter(String fileName); 构造一个给定文件名的FileWriter对象。
FileWriter(String fileName, boolean append); 构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据
。
File src = new File("cbc.txt");
       Writer writer = null;
       try {
           writer = new FileWriter(src, true);
           String msg = "IO so easy\r\n掌握自己的命运";
           char[] srcs = msg.toCharArray();
           writer.write(srcs, 0, srcs.length);
           writer.flush(); // 刷新

用Writer把字符内容写入到文件中,其中可加入\r\n进行换行处理。在这边还可以使用一个append方法,简约代码。

writer.append("IO so easy").append("\n掌握自己的命运");
            writer.flush();

writer写出 . append方法写入字符内容 . append方法 ; 结尾。最后刷新一下一下程序就可以了。

10、数组流

数组可以看成另外的一种内存,它可以不用向之前的那种流一样,需要关闭资源。

  1. 代码,数组输入

构造方法:

ByteArrayInputStream(byte[] buf)   // 创建一个 ByteArrayInputStream ,使其使用 buf作为其缓冲区数组。
ByteArrayInputStream(byte[] buf, int offset, int length) // 创建 ByteArrayInputStream使用 buf作为其缓冲器阵列。
byte[] src = "io is so easy".getBytes();  // 使用平台的默认字符集将该String编码为字节序列,并将结果储存到一个新的字节数组中
       InputStream is = null;
       try {
           is = new ByteArrayInputStream(src);
           byte[] flush = new byte[5];
           int len = -1;
           while ((len = is.read(flush)) != -1) {
               String str = new String(flush, 0, len);
               System.out.println(str);
           }
       } catch (IOException e) {
           e.printStackTrace();
       }

 2. 代码,数组输出

构造方法

ByteArrayOutputStream()   // 创建一个新的字节数组输出流。
ByteArrayOutputStream(int size)   // 创建一个新的字节数组输出流,具有指定大小的缓冲区容量(以字节为单位)。
byte[] dest = null;
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            String str = "io is so easy";
            byte[] datas = str.getBytes();
            baos.write(datas, 0, datas.length);
            baos.flush();
            //获取数据
            dest = baos.toByteArray();
            System.out.println(dest.length+"--->"+new String(dest,0, baos.size()));
        } catch (IOException e) {
            e.printStackTrace();
        }

11、缓冲流

BufferadReader&BufferedWriter(字节缓冲流)

      // 使用缓冲输入流“包装”“文件输入流”提升读取效率。
is = new BufferedInputStream(new FileInputStream(src));
os = new BufferedInputStream(new FileOnputStream(src));

12、转换流

以字符流的形式操作字节流。

1)使用方法。

String readLine(); 读一行文字。

void newLine(); 写一行行分隔符
// 字符流转换为字节流
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
     BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));) {
    // 循环获取键盘的输入(exit退出),输出此内容
    String msg = "";
    while (!msg.equals("exit")) {
        msg = reader.readLine(); // 循环读取
        writer.write(msg);   // 循环写出
        writer.newLine();
        writer.flush();   // 强制刷新
    }
} catch (IOException e) {
    System.out.println("操作异常");
}

 2) InputStreamReadder&OutputStreamWriter:是字节流与字符流之间的桥梁,能将字节流转化为字符流,并且能为字节流指定字符集,可处理一个个的字符。

13、数据流

数据流是方便处理基本类型和八大基本类型,以及字符串的。

// 写出
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(bos));
        // 操作数据类型+数据
        dos.writeUTF("一二三四五六");
        dos.writeInt(18);
        dos.writeBoolean(false);
        dos.writeChar('a');
        dos.flush();
        byte[] datas = bos.toByteArray();
        // 读取
        DataInputStream dis = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
        // 顺序与写出一致
        String msg = dis.readUTF();
        int age = dis.readInt();
        boolean flag = dis.readBoolean();
        char ch = dis.readChar();
        System.out.println(age);

14、对象流和序列化

 ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(bos));
        // 操作数据类型+数据
        oos.writeUTF("一二三四五");
        oos.writeInt(18);

将对象数据存储到数组中

序列化==文件的Copy

一个对象要想满足序列化就必须实现Serializable接口。

还有该类的属性必须是可序列化的。

还原序列化对象

// 对象的数据还原
        Object str = ois.readObject();
        Object date = ois.readObject();
        Object Employee = ois.readObject();

 读取 —反序列化

 ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));

 顺序写出一致

        String msg = ois.readUTF();
        int age = ois.readInt();

 对象数据的还原

        Object str = ois.readObject();
        Object date = ois.readObject();
        Object Employee = ois.readObject();

参考;Java 8 中文版 - 在线API中文手册 - 码工具 (matools.com)

图片参考;JAVA IO流 - 屌丝迷途 - 博客园 (cnblogs.com)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值