流是一种抽象概念,它代表了数据的无结构化传递。用来进行输入输出操作的流就称为IO流。

一、IO流结构

1、流的分类方式

按流向分

从文件/网络/内存等(数据源)到程序是输入流;从程序到文件/网络/内存等(数据源)是输出流

按数据处理单位分

以字节为单位传输数据的流,以Stream结尾的是字节流;以字符为单位传输数据的流,以Reader结尾的是输入字符流,以Writer结尾的都是输出字符流。

按功能(层次)分

用于直接操作目标设备的流是节点流;处理流(也叫过滤流)是对一个已存在的流的连接和封装,通过对数据的处理为程序提供更为强大、灵活的读写功能。

2、IO流的结构

如下图所示:

注意:

所有的字节输入流类都是InputStream的子类;所有的字节符输入流类都是Reader的子类;所有的字节节输出流类都是OutputStream的子类;所有的字节符输出流类都是Writer的子类,且他们都为抽象类。

3、IO流四大抽象类

InputStream的基本方法:

 public abstract int read() throws IOException {}//从输入流中读取数据的下一个字节, 返回读到的字节值.若遇到流的末尾,返回-1
public int read(byte[] b) throws IOException {}//从输入流中读取 b.length 个字节的数据并存储到缓冲区数组b中.返回的是实际读到的字节总数
public int read(byte[] b, int off, int len) throws IOException {}//读取 len 个字节的数据,并从数组b的off位置开始写入到这个数组中
public void close() throws IOException {}//关闭此输入流并释放与此流关联的所有系统资源
public int available() throws IOException {}//返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数
public long skip(long n) throws IOException {}//跳过和丢弃此输入流中数据的 n 个字节,返回实现路过的字节数。

OutputStream的基本方法:

public abstract void write(int b) throws IOException {}//将指定的字节写入此输出流。
public void write(byte[] b) throws IOException {}// 将 b.length 个字节从指定的 byte 数组写入此输出流。
public void write(byte[] b, int off, int len) throws IOException {}//将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
public void flush() throws IOException {}//刷新此输出流并强制写出所有缓冲的输出字节。
pulbic void close() throws IOException {}//关闭此输出流并释放与此流有关的所有系统资源。

Reader的基本方法:

public int read() throws IOException {}//读取单个字符,返回作为整数读取的字符,如果已到达流的末尾返回-1
public int read(char[] cbuf) throws IOException {}//将字符读入数组,返回读取的字符数
public abstract int read(char[] cbuf, int off, int len) throws IOException {}//读取 len 个字符的数据,并从数组cbuf的off位置开始写入到这个数组中
public abstract void close() throws IOException {}//关闭该流并释放与之关联的所有资源
public long skip(long n) throws IOException {}//跳过n个字符。
public int available() //还可以有多少能读到的字节数

Writer的基本方法:

public void write(int c) throws IOException {} //写入单个字符
public void write(char[] cbuf) throws IOException {} //写入字符数组
public abstract void write(char[] cbuf, int off, int len) throws IOException {} //写入字符数组的某一部分
public void write(String str) throws IOException {} //写入字符串
public void write(String str, int off, int len) throws IOException {}//写字符串的某一部分
public abstract void close() throws IOException {} //关闭此流,但要先刷新它
public abstract void flush() throws IOException {} //刷新该流的缓冲,将缓冲的数据全写到目的地

二、IO流的具体使用

1、FileInputStream 和 FileOutputStream

public static void fileInputStreamTest() {
File f1 = new File("D:\\in.txt");
File f2 = new File("D:\\out.txt");
try {
FileInputStream fi = new FileInputStream(f1);
FileOutputStream fo = new FileOutputStream(f2);
byte[] buf = new byte[521];
int len = 0;
while((len = fi.read(buf)) != -1){
fo.write(buf, 0, len);
}
fo.flush();
fo.close();
fi.close();
} catch (Exception e) {
e.printStackTrace();
}
}

2、PipedOutputStream和PipedintputStream

Java里的管道输入流PipedInputStream与管道输出流PipedOutputStream实现了类似管道的功能,用于不同线程之间的相互通信。

Java的管道输入与输出实际上使用的是一个循环缓冲数组来实现,这个数组默认大小为1024字节。输入流PipedInputStream从这个循环缓冲数组中读数据,输出流PipedOutputStream往这个循环缓冲数组中写入数据。当这个缓冲数组已满的时候,输出流PipedOutputStream所在的线程将阻塞;当这个缓冲数组首次为空的时候,输入流PipedInputStream所在的线程将阻塞。Java在它的jdk文档中提到不要在一个线程中同时使用PipeInpuStream和PipeOutputStream,这会造成死锁。

public class WriteThread implements Runnable{
private PipedOutputStream pout; WriteThread(PipedOutputStream pout){
this.pout= pout;
} @Override
public void run() {
try {
System.out.println("W:开始将数据写入:但等个5秒让我们观察...");
Thread.sleep(5000); //释放cpu执行权5秒
pout.write("writePiped 数据...".getBytes()); //管道输出流
pout.close();
} catch(Exception e) {
throw new RuntimeException("W:WriteThread写入失败...");
}
}
} public class ReadThread implements Runnable{
private PipedInputStream pin; ReadThread(PipedInputStream pin) {
this.pin=pin;
} @Override
public void run() { //由于必须要覆盖run方法,所以这里不能抛,只能try
try {
System.out.println("R:读取前没有数据,阻塞中...等待数据传过来再输出到控制台...");
byte[] buf = new byte[1024];
int len = pin.read(buf); //read阻塞
System.out.println("R:读取数据成功,阻塞解除...");
String s= new String(buf,0,len);
System.out.println(s); //将读取的数据流用字符串以字符串打印出来
pin.close();
} catch(Exception e) {
throw new RuntimeException("R:管道读取流失败!");
}
}
} public class Test {
public static void main(String[] args) throws IOException {
PipedInputStream pin = new PipedInputStream();
PipedOutputStream pout = new PipedOutputStream();
pin.connect(pout); //输入流与输出流连接 ReadThread readTh = new ReadThread(pin);
WriteThread writeTh = new WriteThread(pout);
new Thread(readTh).start();
new Thread(writeTh).start();
}
}

3、BufferedInputStream和BufferedOutputStream

FileInputStream和FileOutputStream 在使用时,我们介绍了可以用byte数组作为数据读入的缓存区,以读文件为列,读取硬盘的速度远远低于读取内存的数据,为了减少对硬盘的读取,通常从文件中一次读取一定长度的数据,把数据存入缓存中,在写入的时候也是一次写入一定长度的数据,这样可以增加文件的读取效率。我们在使用FileInputStream的时候是用byte数组来做了缓存,而BufferedInputStream and BufferedOutputStream已经为我们增加了这个缓存功能。

public static void fileBufferTest() {
File f1 = new File("D:\\in.txt");
File f2 = new File("D:\\out.txt");
try {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(f1));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(f2));
byte[] data = new byte[1];
while(bufferedInputStream.read(data)!=-1) {
bufferedOutputStream.write(data);
}
//将缓冲区中的数据全部写出
bufferedOutputStream.flush();
bufferedInputStream.close();
bufferedOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}

4、读写对象ObjectInputStream和ObjectOutputStream

public class ObjectStream {
public static void main(String[] args) {
ObjectStream.objectStreamTest();
} public static void objectStreamTest() {
Demo newObject;
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("D:/123.obj")));
oos.writeObject(new Demo());
oos.flush();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("D:/123.obj")));
newObject = (Demo)ois.readObject();
System.out.println(newObject.num);
ois.close();
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
} class Demo implements Serializable{
private static final long serialVersionUID = 1L;
int num = 30;
}

5、SequenceInputStream

合并流,将与之相连接的流集组合成一个输入流并从第一个输入流开始读取, 直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。 合并流的作用是将多个源合并合一个源。可接收枚举类所封闭的多个字节流对象。

public class Test {
public static void main(String[] args) {
doSequence();
} private static void doSequence() {
SequenceInputStream sis = null; // 创建一个合并流的对象
BufferedOutputStream bos = null; // 创建输出流。
try {
// 构建流集合
Vector<InputStream> vector = new Vector<InputStream>();
vector.addElement(new FileInputStream("D:/in.txt"));
vector.addElement(new FileInputStream("D:/out.txt"));
Enumeration<InputStream> e = vector.elements();
sis = new SequenceInputStream(e);
bos = new BufferedOutputStream(new FileOutputStream("/Users/zhengchao/cctv/File_OUT.txt"));
// 读写数据
byte[] buf = new byte[1024];
int len = 0;
while ((len = sis.read(buf)) != -1) {
bos.write(buf, 0, len);
bos.flush();
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
try {
if (sis != null)
sis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bos != null)
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

6、FileReader与FileWriter

public static void fileReaderTest() {
File f1 = new File("D:\\in.txt");
File f2 = new File("D:\\out.txt");
try {
FileReader fr = new FileReader(f1);
FileWriter fw = new FileWriter(f2);
char[] ch = new char[512];
int len = 0;
while((len = fr.read(ch)) != -1){
fw.write(ch, 0, ch.length);
}
fw.flush();
fw.close();
fr.close();
} catch (Exception e) {
e.printStackTrace();
}
}

7、BufferedReader和BufferedWriter

public static void fileBufferReaderWriteTest() {
File f1 = new File("D:\\in.txt");
File f2 = new File("D:\\out.txt");
try {
BufferedReader br=new BufferedReader(new FileReader(f1));
BufferedWriter bw=new BufferedWriter(new FileWriter(f2)); String s=br.readLine();
while(null!=s) {
bw.write(s);
//由于BufferedReader的readLine()是不读入换行符的,所以写入换行时须用newLine()方法
bw.newLine();
s=br.readLine();
}
br.close();
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}

注:在使用过程中应注意将编码格式设置为UTF-8,否则文件写入会乱码。

以上只是IO流的部分类,用于对IO流相关知识进行查阅,后面再实际的工作中也会根据实际需求不断添加。

参考自:

https://blog.csdn.net/zhengchao1991/article/details/53033137

https://blog.csdn.net/SilenceOO/article/details/50995062

https://blog.csdn.net/Yue_Chen/article/details/72772445

理解Java之IO流的更多相关文章

  1. 第15章-输入/输出 --- 理解Java的IO流

    (一)理解Java的IO流 JAVA的IO流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作,在Java中把不同的输入/输出(键盘.文件.网络连接等)抽象表述为"流"( ...

  2. java的IO流

    java的IO流继承四大抽象类分别是字节流 inputStream outputStream与字符流 read write.怎么理解记忆很重要. 直接连接读写对象的是结点流,例如对文件读取字节类的名字 ...

  3. Java基础-IO流对象之压缩流(ZipOutputStream)与解压缩流(ZipInputStream)

    Java基础-IO流对象之压缩流(ZipOutputStream)与解压缩流(ZipInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 之前我已经分享过很多的J ...

  4. Java基础——IO流

    今天刚刚看完java的io流操作,把主要的脉络看了一遍,不能保证以后使用时都能得心应手,但是最起码用到时知道有这么一个功能可以实现,下面对学习进行一下简单的总结: IO流主要用于硬板.内存.键盘等处理 ...

  5. 【Java】IO流简单分辨

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827509.html Java的IO流体系十分庞大,并且体系层次稍复杂,很容易记混或记错.在此,我把平时经常用 ...

  6. Java - 文件(IO流)

    Java - 文件 (IO)   流的分类:     > 文件流:FileInputStream | FileOutputStream | FileReader | FileWriter     ...

  7. Java中IO流的总结

    有关Java中IO流总结图 流分类 按方向分 输入流 输出流 按单位分 字节流 字符流 按功能分 节点流 处理流(过滤流) 其他 所有的流继承与这四类流:InputSteam.OutputStream ...

  8. JAVA中IO流总结

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42119261 我想你对JAVA的IO流有所了解,平时使用的 ...

  9. Java基础IO流(二)字节流小案例

    JAVA基础IO流(一)https://www.cnblogs.com/deepSleeping/p/9693601.html ①读取指定文件内容,按照16进制输出到控制台 其中,Integer.to ...

随机推荐

  1. vue.js 常用组件库

    vux github ui demo:https://github.com/airyland/vux Mint UI 项目主页:http://mint-ui.github.io/#!/zh-cndem ...

  2. 《Linux-基础篇笔记》 Vim编辑器(二)

    Linux图形化界面下的文本编辑器 gedit . libre office . evince PDF阅读器 ①gedit是一个GNOME桌面环境下兼容UTF-8的文本编辑器.它使用GTK+编写而成, ...

  3. 12_python_生成器

    一.生成器 python中有三种方式获取生成器 (1)通过生成器函数 (2)通过各种推导式来实现生成器 (3)通过数据的转换也可以获取生成器   1.只要函数中存在了yield,那么这个函数就是一个生 ...

  4. mysql创建账号及管理权限

    mysql创建账号及管理权限 0.mysql版本8.0.15,服务器版本:RHEL 6.5 1.创建用户名密码 mysql> use mysql; mysql> create user ' ...

  5. 连接企业的人、事、物、知识--企业IM的第三类生存方式

    企业IM现状:尴尬 传统的企业IM在完成聊天.群组.文件传输.音频会话等传统IM功能后,发现自己陷入了尴尬的境地,因为功能的“同质化”,这些功能微信.QQ也有啊,其他IM厂商也有.于是IM厂商开始思考 ...

  6. cytoscape.js在vue项目中的安装及案例

    1. 安装: npm i cytoscape --save 2. 引入:main.js import cytoscape from 'cytoscape'; Vue.prototype.$cytosc ...

  7. django admin编辑被外键关联的主表时支持显示字表记录

    假设有模型 class A(models.Model): name = models.CharField() class B(models.Model): name = models.CharFiel ...

  8. 课程一(Neural Networks and Deep Learning),第四周(Deep Neural Networks) —— 3.Programming Assignments: Deep Neural Network - Application

    Deep Neural Network - Application Congratulations! Welcome to the fourth programming exercise of the ...

  9. (转)MVC 与三层架构

    原文:https://juejin.im/post/5929259b44d90400642194f3 MVC 与三层架构 一.简述 在软件开发中,MVC与三层架构这两个专业词汇经常耳闻,同时总有很多人 ...

  10. Git使用(3)

    1.查看本地和远程分支 git branch -a 删除本地分支 git branch -D branchName(D要大写) 删除远程分支 git push origin :branchName 2 ...