第十一章:IO流

第十一章:IO流

第十一章

课文

第十一章:IO流

 

 

 

1.流的概念

流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以"流"的方式进行。设备可以是文件,网络,内存等

 

流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序为参考,如果数据的流向是程序至设备,我们成为输出流,如果数据的流向是设备至程序称为输入流。

 

数据以二进制的形式在程序与设备之间流动传输,就想水在管道里流动一样,所以就把这种数据传输的方式称之为输入流输出流

 

思考:代码程序中要读取文件中的内容,需要使用什么流?代码程序中要向文件中写内容,又需要使用什么流?

 

2.流的分类

1)按照流的方向分为输入流和输出流

2)按照处理数据的单位不同分为字节流和字符流

字节流读取的最小单位是一个字节(1byte=8bit),而字符流一次可以读取一个字符(1char = 2byte = 16bit)

3)按照功能的不同分为节点流和处理流

节点流是可以"直接"从一个数据源中读写数据的流。

处理流也可以称为功能流或者包装流,它是可以对节点流进行封装的一种流,封装后可以增加节点流的功能。

例如:FileInputStream是一个节点流,可以直接从文件读取数据,而BufferedInputStream可以包装 FileInputStream,使得其有缓冲数据的功能。

 

4)除了以上三种分类外,还有其他的一些类型的:对象流、缓冲流、压缩流、文件流等等,其实这些都是节点流或者处理流的子分类。当然还可以分出来其他的流类型,如果有这样需要的话。

 

5)不管流的分类是多么的丰富和复杂,其根源来自于四个基本的父类

字节输入流:InputStream 

字节输出流:OutputStream 

 

字符输入流:Reader 

字符输出流:Writer

 

注:这四个父类都是抽象类

 

3.字节流中的常用节点流

注:java中常用的io流都在java.io包中

1)InputStream

//从输入流中读取数据的下一个字节

//如果到达流的末尾则返回 -1

public abstract int read();

//把读到的字节存到字节数组b中,并返回本次读到了多少个字节

public int read(byte[] b){..}

//把读到的字节存到字节数组b中,同时指定开始存的位置以及最大字节数,并返回本次读到了多少个字节

public int read(byte[] b,int off,int len){..}

 

//返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数

public int available(){..}

 

//跳过此输入流中数据的 n 个字节

public long skip(long n){..}

 

//关闭此输入流并释放与该流关联的所有系统资源

public void close(){..}

 

//测试此输入流是否支持 mark 和 reset 方法

public boolean markSupported(){..}

//在此输入流中标记当前的位置

public void mark(int readlimit){..}

//将此流重新定位到最后一次对此输入流调用mark方法时的位置

public void reset(){..}

 

2)OutputStream

//将指定的字节写入此输出流

public abstract void write(int b);

//将字节数组b中的所有字节写入此输出流

public void write(byte[] b){..}

//将字节数组b中的字节写入此输出流,指定开始位置及最大字节数

public void write(byte[] b,int off,int len){..}

 

//刷新此输出流并强制写出所有缓冲的输出字节

public void flush(){..}

 

//关闭此输出流并释放与此流有关的所有系统资源

public void close(){..}

 

3)InputStream的子类和OutputStream的子类几乎都是成对出现的,一个负责读数据的工作,一个负责写数据的工作

 

4)System.out和System.in

System类的部分源码:

public final class System{

//标准输入流

public final static InputStream in = null;

//标准输出流。

public final static PrintStream out = null;

//标准错误输出流

public final static PrintStream err = null;

 

public static void setIn(InputStream in){..}

public static void setOut(PrintStream out){..}

public static void setErr(PrintStream err){..}

}

 

标准输入流会默认从控制台读取数据

标准输出流会默认把数据输出到控制台

 

System.out.println(System.in.getClass());

System.out.println(System.out.getClass());

输出结果为:

class java.io.BufferedInputStream

class java.io.PrintStream

 

5)ByteArrayInputStream和ByteArrayOutputStream

ByteArrayInputStream可以从数组中读取字节

        数据流向:开辟数组内存------>开辟IO流对象内存

ByteArrayOutputStream可以把字节写到对象中的缓冲区里面,其实就是一个字节数组

        数据流向:开辟IO流对象内存 ------>开辟数组内存

 

6)FileInputStream和FileOutputStream

FileInputStream可以读取文件中的字节

        数据流向 : 文件---程序内存

FileOutputStream可以向文件中写进去字节

        数据流向 :程序内存---文件

        扩展流向: a文件----程序----b文件

                   a文件----输入流---输出流---b文件

7)PipedInputStream和PipedOutputStream(学习多线程章节后使用该类)

PipedInputStream管道字节输入流

PipedOutputStream管道字节输出流

 

注:使用时需要把俩个管道进行对接

 

8)ObjectInputStream和ObjectOutputStream

在序列化中要使用的对象输入流和对象输出流,之后再来使用测试

 

9)java.io.File类

File类型对象可以表示一个文件也可以表示一个目录.

 

4.字节流中的常用处理流

也可以称为功能流或者包装流,因为它是对节点流进行包装的一种流,包装后可以增加节点流的功能。但是处理流本身并不能直接读写数据

 

1)BufferedInputStream和BufferedOutputStream

可以给字节流中的节点流提供代码缓冲区的输入/输出流

2)DataInputStream和DataOutputStream

可以给字节流中的节点流提供输入/输出java中不同类型的数据

3)PrintStream

PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式

 

5.字符流

1)Reader

public int read(){..}

public int read(char[] cbuf){..}

public abstract int read(char[] cbuf, int off,int len){..}

//指定缓冲区

//@since 1.5

public int read(CharBuffer target){..}

 

abstract public void close();

public long skip(long n){..}

 

public boolean markSupported(){..}

public void mark(int readAheadLimit){..}

public void reset(){..}

 

//Tells whether this stream is ready to be read

public boolean ready(){..}

 

2)Writer

public void write(int c){..}

public void write(char cbuf[]){..}

abstract public void write(char cbuf[], int off, int len);

public void write(String str){..}

public void write(String str, int off, int len){..}

 

abstract public void flush();

abstract public void close();

 

//@since 1.5

//和out.write(c)的效果一样

public Writer append(char c){..}

public Writer append(CharSequence csq){..}

public Writer append(CharSequence csq, int start, int end){..}

 

3)CharArrayReader和CharArrayWriter

CharArrayReader可以读取字符数组中的内容

CharArrayWriter可以向字符数组中写内容

 

4)FileReader和FileWriter

FileReader读取文件内容的便捷类,InputStreamReader的子类

FileWriter写入文件内容的便捷类,OutputStreamWriter的子类

 

5)PipedReader和PipedWriter

PipedReader管道字符输入流

PipedWriter管道字符输出流

 

6)BufferedReader和BufferedWriter

这个俩个流属于处理流/包装流,它们本身并不能读取数据,它们的作用是包装在其他节点流上面,为其提供额外的功能

 

7)PrintWriter

一般会把BufferedReader和PrintWriter配合在一起使用,因为BufferedReader可以一次读一行字符串,而PrintWriter可以一次写一行字符串(自动换行)。

 

6.转换流

InputStreamReader和OutputStreamWriter是一对名字中既有Stream,又有Reader或Writer的流,因为它们是转换流,负责把一个字节流转换为字符流。所以它们是字节流和字符串之间的桥梁.

注:在把字节流转换为字符流的过程中,还可以指定字符编码,避免乱码的出现。

 

7.对象流

1)序列化和反序列化

Java中的序列化是指把Java对象转换为字节序列的过程

对象---序列化--->01010101

Java中的反序列化是指把字节序列恢复为Java对象的过程

01010101---反序列化--->对象

 

思考:为什么需要序列化和反序列化?

 

 

2)如何实现序列化和反序列化

使用对象流即可实现对象的序列化和反序列化

ObjectOutputStream类中的方法可以完成对象的序列化:

public final void writeObject(Object obj){..}

 

ObjectInputStream类中的方法可以完成对象的反序列化:

public final Object readObject(){..}

 

 

注:这俩个对象流都属于字节流

 

3)序列化的要求

只有实现了java.io.Serializable接口的类的对象才可以被序列化,否则序列化时会报错

 

思考:测试序列化版本号的作用是什么?

 

4)transient关键字

在对象序列化的时候,被transient修饰的属性的值,在序列化过程中是会被忽略掉的。

 

9.随机访问流

java.io.RandomAccessFile类

public class RandomAccessFile extends Object{..}

这是个特殊的流,它不属于之前那些流的体系。

 

这个流的既可以用来读文件,也可以用来给文件中写内容,并且该类中的方法可以用来定位文件中的位置:

public native void seek(long pos);

 

 

构造器中需要设置该流的操作模式:

//对文件只读

RandomAccessFile r = new RandomAccessFile(filePath,"r");

//对文件即可读又可写

//但是一旦确定了读或者写,那么就不能在变

RandomAccessFile rw = new RandomAccessFile(filePath,"rw");

 

1.流的概念

流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以"流"的方式进行。设备可以是文件,网络,内存等

 

流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序为参考,如果数据的流向是程序至设备,我们成为输出流,如果数据的流向是设备至程序称为输入流。

 

数据以二进制的形式在程序与设备之间流动传输,就想水在管道里流动一样,所以就把这种数据传输的方式称之为输入流输出流

 

思考:代码程序中要读取文件中的内容,需要使用什么流?代码程序中要向文件中写内容,又需要使用什么流?

 

2.流的分类

1)按照流的方向分为输入流和输出流

2)按照处理数据的单位不同分为字节流和字符流

字节流读取的最小单位是一个字节(1byte=8bit),而字符流一次可以读取一个字符(1char = 2byte = 16bit)

3)按照功能的不同分为节点流和处理流

节点流是可以"直接"从一个数据源中读写数据的流。

处理流也可以称为功能流或者包装流,它是可以对节点流进行封装的一种流,封装后可以增加节点流的功能。

例如:FileInputStream是一个节点流,可以直接从文件读取数据,而BufferedInputStream可以包装 FileInputStream,使得其有缓冲数据的功能。

 

4)除了以上三种分类外,还有其他的一些类型的:对象流、缓冲流、压缩流、文件流等等,其实这些都是节点流或者处理流的子分类。当然还可以分出来其他的流类型,如果有这样需要的话。

 

5)不管流的分类是多么的丰富和复杂,其根源来自于四个基本的父类

字节输入流:InputStream 

字节输出流:OutputStream 

 

字符输入流:Reader 

字符输出流:Writer

 

注:这四个父类都是抽象类

 

3.字节流中的常用节点流

注:java中常用的io流都在java.io包中

1)InputStream

//从输入流中读取数据的下一个字节

//如果到达流的末尾则返回 -1

public abstract int read();

//把读到的字节存到字节数组b中,并返回本次读到了多少个字节

public int read(byte[] b){..}

//把读到的字节存到字节数组b中,同时指定开始存的位置以及最大字节数,并返回本次读到了多少个字节

public int read(byte[] b,int off,int len){..}

 

//返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数

public int available(){..}

 

//跳过此输入流中数据的 n 个字节

public long skip(long n){..}

 

//关闭此输入流并释放与该流关联的所有系统资源

public void close(){..}

 

//测试此输入流是否支持 mark 和 reset 方法

public boolean markSupported(){..}

//在此输入流中标记当前的位置

public void mark(int readlimit){..}

//将此流重新定位到最后一次对此输入流调用mark方法时的位置

public void reset(){..}

 

2)OutputStream

//将指定的字节写入此输出流

public abstract void write(int b);

//将字节数组b中的所有字节写入此输出流

public void write(byte[] b){..}

//将字节数组b中的字节写入此输出流,指定开始位置及最大字节数

public void write(byte[] b,int off,int len){..}

 

//刷新此输出流并强制写出所有缓冲的输出字节

public void flush(){..}

 

//关闭此输出流并释放与此流有关的所有系统资源

public void close(){..}

 

3)InputStream的子类和OutputStream的子类几乎都是成对出现的,一个负责读数据的工作,一个负责写数据的工作

 

4)System.out和System.in

System类的部分源码:

public final class System{

//标准输入流

public final static InputStream in = null;

//标准输出流。

public final static PrintStream out = null;

//标准错误输出流

public final static PrintStream err = null;

 

public static void setIn(InputStream in){..}

public static void setOut(PrintStream out){..}

public static void setErr(PrintStream err){..}

}

 

标准输入流会默认从控制台读取数据

标准输出流会默认把数据输出到控制台

 

System.out.println(System.in.getClass());

System.out.println(System.out.getClass());

输出结果为:

class java.io.BufferedInputStream

class java.io.PrintStream

 

5)ByteArrayInputStream和ByteArrayOutputStream

ByteArrayInputStream可以从数组中读取字节

        数据流向:开辟数组内存------>开辟IO流对象内存

ByteArrayOutputStream可以把字节写到对象中的缓冲区里面,其实就是一个字节数组

        数据流向:开辟IO流对象内存 ------>开辟数组内存

 

6)FileInputStream和FileOutputStream

FileInputStream可以读取文件中的字节

        数据流向 : 文件---程序内存

FileOutputStream可以向文件中写进去字节

        数据流向 :程序内存---文件

        扩展流向: a文件----程序----b文件

                   a文件----输入流---输出流---b文件

7)PipedInputStream和PipedOutputStream(学习多线程章节后使用该类)

PipedInputStream管道字节输入流

PipedOutputStream管道字节输出流

 

注:使用时需要把俩个管道进行对接

 

8)ObjectInputStream和ObjectOutputStream

在序列化中要使用的对象输入流和对象输出流,之后再来使用测试

 

9)java.io.File类

File类型对象可以表示一个文件也可以表示一个目录.

 

4.字节流中的常用处理流

也可以称为功能流或者包装流,因为它是对节点流进行包装的一种流,包装后可以增加节点流的功能。但是处理流本身并不能直接读写数据

 

1)BufferedInputStream和BufferedOutputStream

可以给字节流中的节点流提供代码缓冲区的输入/输出流

2)DataInputStream和DataOutputStream

可以给字节流中的节点流提供输入/输出java中不同类型的数据

3)PrintStream

PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式

 

5.字符流

1)Reader

public int read(){..}

public int read(char[] cbuf){..}

public abstract int read(char[] cbuf, int off,int len){..}

//指定缓冲区

//@since 1.5

public int read(CharBuffer target){..}

 

abstract public void close();

public long skip(long n){..}

 

public boolean markSupported(){..}

public void mark(int readAheadLimit){..}

public void reset(){..}

 

//Tells whether this stream is ready to be read

public boolean ready(){..}

 

2)Writer

public void write(int c){..}

public void write(char cbuf[]){..}

abstract public void write(char cbuf[], int off, int len);

public void write(String str){..}

public void write(String str, int off, int len){..}

 

abstract public void flush();

abstract public void close();

 

//@since 1.5

//和out.write(c)的效果一样

public Writer append(char c){..}

public Writer append(CharSequence csq){..}

public Writer append(CharSequence csq, int start, int end){..}

 

3)CharArrayReader和CharArrayWriter

CharArrayReader可以读取字符数组中的内容

CharArrayWriter可以向字符数组中写内容

 

4)FileReader和FileWriter

FileReader读取文件内容的便捷类,InputStreamReader的子类

FileWriter写入文件内容的便捷类,OutputStreamWriter的子类

 

5)PipedReader和PipedWriter

PipedReader管道字符输入流

PipedWriter管道字符输出流

 

6)BufferedReader和BufferedWriter

这个俩个流属于处理流/包装流,它们本身并不能读取数据,它们的作用是包装在其他节点流上面,为其提供额外的功能

 

7)PrintWriter

一般会把BufferedReader和PrintWriter配合在一起使用,因为BufferedReader可以一次读一行字符串,而PrintWriter可以一次写一行字符串(自动换行)。

 

6.转换流

InputStreamReader和OutputStreamWriter是一对名字中既有Stream,又有Reader或Writer的流,因为它们是转换流,负责把一个字节流转换为字符流。所以它们是字节流和字符串之间的桥梁.

注:在把字节流转换为字符流的过程中,还可以指定字符编码,避免乱码的出现。

 

7.对象流

1)序列化和反序列化

Java中的序列化是指把Java对象转换为字节序列的过程

对象---序列化--->01010101

Java中的反序列化是指把字节序列恢复为Java对象的过程

01010101---反序列化--->对象

 

思考:为什么需要序列化和反序列化?

 

 

2)如何实现序列化和反序列化

使用对象流即可实现对象的序列化和反序列化

ObjectOutputStream类中的方法可以完成对象的序列化:

public final void writeObject(Object obj){..}

 

ObjectInputStream类中的方法可以完成对象的反序列化:

public final Object readObject(){..}

 

 

注:这俩个对象流都属于字节流

 

3)序列化的要求

只有实现了java.io.Serializable接口的类的对象才可以被序列化,否则序列化时会报错

 

思考:测试序列化版本号的作用是什么?

 

4)transient关键字

在对象序列化的时候,被transient修饰的属性的值,在序列化过程中是会被忽略掉的。

 

9.随机访问流

java.io.RandomAccessFile类

public class RandomAccessFile extends Object{..}

这是个特殊的流,它不属于之前那些流的体系。

 

这个流的既可以用来读文件,也可以用来给文件中写内容,并且该类中的方法可以用来定位文件中的位置:

public native void seek(long pos);

 

 

构造器中需要设置该流的操作模式:

//对文件只读

RandomAccessFile r = new RandomAccessFile(filePath,"r");

//对文件即可读又可写

//但是一旦确定了读或者写,那么就不能在变

RandomAccessFile rw = new RandomAccessFile(filePath,"rw");

 

 

 

 

  1. 字节流继承inputStream和OutputStream
  2. 字符流继承自InputSteamReader和OutputStreamWriter

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值