【狂神说笔记—— Java基础09-IO流】

一、JAVA流式输入/输出原理

在这里插入图片描述

在Java程序中,对于数据的输入/输出操作以“流”(Stream)方式进行;J2SDK提供了各种各样的“流” 类,用以获取不同种类的数据:程序中通过标准的方法输入或输出数据。

读入写出

流是用来读写数据的,java有一个类叫File,它封装的是文件的文件名,只是内存里面的一个对象,真 正的文件是在硬盘上的一块空间,在这个文件里面存放着各种各样的数据,我们想读文件里面的数据怎 么办呢?是通过一个流的方式来读,咱们要想从程序读数据,对于计算机来说,无论读什么类型的数据 都是以010101101010这样的形式读取的。怎么把文件里面的数据读出来呢?你可以把文件想象成一个 小桶,文件就是一个桶,文件里面的数据就相当于是这个桶里面的水,那么我们怎么从这个桶里面取水 呢,也就是怎么从这个文件读取数据呢。

常见的取水的办法是我们用一根管道插到桶上面,然后在管道的另一边打开水龙头,桶里面的水就开始 哗啦哗啦地从水龙头里流出来了,桶里面的水是通过这根管道流出来的,因此这根管道就叫流,JAVA里 面的流式输入/输出跟水流的原理一模一样,当你要从文件读取数据的时候,一根管道插到文件里面去, 然后文件里面的数据就顺着管道流出来,这时你在管道的另一头就可以读取到从文件流出来的各种各样 的数据了。当你要往文件写入数据时,也是通过一根管道,让要写入的数据通过这根管道哗啦哗啦地流 进文件里面去。除了从文件去取数据以外,还可以通过网络,比如用一根管道把我和你的机子连接起

来,我说一句话,通过这个管道流进你的机子里面,你马上就可以看得到,而你说一句话,通过这根管 道流到我的机子里面,我也马上就可以看到。有的时候,一根管道不够用,比方说这根管道流过来的水 有一些杂质,我们就可以在这个根管道的外面再包一层管道,把杂质给过滤掉。从程序的角度来讲,从 计算机读取到的原始数据肯定都是010101这种形式的,一个字节一个字节地往外读,当你这样读的时候 你觉得这样的方法不合适,没关系,你再在这根管道的外面再包一层比较强大的管道,这个管道可以把010101帮你转换成字符串。这样你使用程序读取数据时读到的就不再是010101这种形式的数据了,而 是一些可以看得懂的字符串了。

二、输入输出流分类

Java.io 包中定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同的角度对其进行分类:

  • 按数据流的方向不同可以分为输入流和输出流
  • 按照处理数据单位不同可以分为字节流和字符流
  • 按照功能不同可以分为节点流和处理流

我们来理解两个概念:

  • 字节流:最原始的一个流,读出来的数据就是010101这种最底层的数据表示形式,只不过它是按 照字节来读的,一个字节(Byte)是8位(bit)读的时候不是一个位一个位的来读,而是一个字节 一个字节来读。

  • 字符流:字符流是一个字符一个字符地往外读取数据。一个字符是2个字节

J2SDK所提供的所有流类型位于包 Java.io内,都分别继承自以下四种抽象流类型。

输入流:InputStream(字节流),Reader(字符流)

输出流:OutPutStream(字节流),Writer(字符流)

这四个类都是抽象类,可以把这四个类想象成四根不同的管道。一端接着你的程序,另一端接着数据 源,你可以通过输出管道从数据源里面往外读数据,也可以通过输入管道往数据源里面输入数据,总 之,通过这四根管道可以让数据流进来和流出去。

io包里面定义了所有的流,所以一说流指的就是io包里面的

什么叫输入流?什么叫输出流?

用一根管道一端插进文件里,一端插进程序里面,然后开始读数据,那么这是输入还是输出呢? 如果站在文件的角度上,这叫输出。

如果站在程序的角度上,这叫输入。

记住,以后说输入流和输出流都是站在程序的角度上来说。

三、节点流和处理流

在这里插入图片描述

你要是对原始的流不满意,你可以在这根管道外面再套其它的管道,套在其它管道之上的流叫处理流。 为什么需要处理流呢?这就跟水流里面有杂质,你要过滤它,你可以再套一层管道过滤这些杂质一样。

3.1. 节点流类型

类型 字符流 字节流
File(文件) FileReader、FileWriter FileInputStream、FileOutputStream
Memory Array CharArrayReader、CharArrayWriter ByteArrayInputStream、ByteArrayOutputStream
Memory String StringReader、StringWriter -
Pipe(管道) PipedReader、PipedWriter PipedInputStream、PipedOutputStream

节点流就是一根管道直接插到数据源上面,直接读数据源里面的数据,或者是直接往数据源里面写入数 据。典型的节点流是文件流:文件的字节输入流(FileInputStream),文件的字节输出流

(FileOutputStream),文件的字符输入流(FileReader),文件的字符输出流(FileWriter)。

3.2. 处理流类型

处理类型 字符流 字节流
Buffering BufferedReader、BufferedWriter BufferedInputStream、BufferedOutputStream
Filtering FilterReader、FilterWriter FilterInputStream, FilterOutputStream
Converting between bytes and chaacter InputStreamReader、OutputStreamWriter -
Object Serialization - ObjectInputStream、ObjectOutputStream
Data conversion - DataInputStream、DataOutputStream
Counting LineNumberReader LineNumberInputStream
Peeking ahead PusbackReader PushbackInputStream
Printing PrintWriter PrintStream

处理流是包在别的流上面的流,相当于是包到别的管道上面的管道。

四、InputStream(输入流)

我们看到的具体的某一些管道,凡是以InputStream结尾的管道,都是以字节的形式向我们的程序输入 数据。

继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8bit);下图中深色为节点 流,浅色为处理流。

在这里插入图片描述

4.1.InputStream的基本方法

//读取一个字节并以整数的形式返回(0~255)
//如果返回-1就说明已经到了输入流的末尾
int read() throws IOException

//读取一系列字节并存储到一个数组buffer
//返回实际读取的字节数,如果读取前已到输入流的末尾,则返回-1
int read(byte[] buffer) throws IOException

//读取length个字节
//并存储到一个字节数组buffer,从length位置开始
//返回实际读取的字节数,如果读取前以到输入流的末尾返回-1.
int read(byte[] buffer,int offset,int length) throws IOException

//关闭流释放内存资源
void close() throws IOException

//跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException

read()方法是一个字节一个字节地往外读,每读取一个字节,就处理一个字节。read(byte[] buffer)方法读取数据时,先把读取到的数据填满这个byte[]类型的数组buffer(buffer是内存里面的一块缓冲区),然 后再处理数组里面的数据。这就跟我们取水一样,先用一个桶去接,等桶接满水后再处理桶里面的水。 如果是每读取一个字节就处理一个字节,这样子读取也太累了。

4.2 案例

以File(文件)这个类型作为讲解节点流的典型代表

【源码查看,分析结构】

【演示:使用FileInputStream流来读取FileInputStream.java文件的内容】

package com.kuang.chapter;

import java.io.*;

public class TestFileInputStream {
   
   public static void main(String args[]) {
   
       int b = 0;// 使用变量b来装调用read()方法时返回的整数
       FileInputStream in = null;
       // 使用FileInputStream流来读取有中文的内容时,读出来的是乱码,因为使用InputStream流里面的read()方法读取内容时是一个字节一个字节地读取的,而一个汉字是占用两个字节的,所以读取出来的汉字无法正确显示。
       // FileReader in = null;
       // 使用FileReader流来读取内容时,中英文都可以正确显示,因为Reader流里面的read()方法是一个字符一个字符地读取的,这样每次读取出来的都是一个完整的汉字,这样就可以正确显示了。
       try {
   
           in = new FileInputStream("E:\\教学\\班级\\Test\\Lesson2\\src\\com\\kuang\\chapter\\Student.java");
                   // in = new FileReader("E:\\教学\\班级\\Test\\Lesson2\\src\\com\\kuang\\chapter\\Student.java");
       } catch (FileNotFoundException e) {
   
           System.out.println("系统找不到指定文件!");
           System.exit(-1);// 系统非正常退出
       }

       long num = 0;// 使用变量num来记录读取到的字符数

       // 调用read()方法时会抛异常,所以需要捕获异常
       try {
   
           while ((b = in.read()) != -1) {
   
               // 调用int read() throws Exception方法时,返回的是一个int类型的整数
               // 循环结束的条件就是返回一个值-1,表示此时已经读取到文件的末尾了。
               // System.out.print(b+"\t");//如果没有使用“(char)b”进行转换,那么直接打印出来的b就是数字,而不是英文和中文了
               System.out.print((char) b);
               // “char(b)”把使用数字表示的汉字和英文字母转换成字符输入
               num++;
           }
           in.close();// 关闭输入流
           System.out.println();
           System.out.println("总共读取了" + num + "个字节的文件");
       } catch (IOException e1) {
   
           System.out.println("文件读取错误!");
       }
   }
}

五、OutputStream(输出流)

继承自OutputStream的流是用于程序中输出数据,且数据的单位为字节(8bit):下图中深色的为节点 流,浅色为处理流。

在这里插入图片描述

5.1.OutputStream的基本方法

//向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException

//将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException

//将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
void write(byte[] b,int off,int len) throws IOException

//关闭流释放内存资源
void close() throws IOException

//将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException

5.2 案例

【使用FileOutputSt

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值