Java流概念:

Java把所有的有序数据都抽象成流模型,简化了输入输出,理解了流模型就理解了Java IO。可以把流想象成水流,里面的水滴有序的朝某一方向流动。水滴就是数据,且代表着最小的数据流动单位,在字节流中,水滴就是一字节(byte),在字符流中,水滴就是一字符(char)。

Java流的分类方法大致分为以下几种:

1、按流向划分,分为输入流、输出流

请注意,这里的流向是以程序的运行时内存为参照的。 
输入流类名中包含关键字InputStream或Reader,输出流类名中包含关键字OutputStream或Writer。

2、按操作的数据单元类型划分,分为字节流、字符流

字节流操作的数据单元是8位的字节(byte),字符流操作的是16位的字符。 
字节流类名中包含关键字InputStream或OutputStream,字符流类名中包含关键字Reader或Writer。 
请注意,系统输入输出(System.in与System.out)都为字节流。

3、按流的角色来划分,分为节点流与处理流

节点流是指程序可以向一个特定的节点读写数据,直接连接数据源; 
这个节点最常见的是文件,类名中包含关键字File;还可以是数组、管道、字符串,关键字分别为ByteArray/CharArray,Piped,String。

处理流并不直接连接数据源,它大多情况是对已存在的节点流进行包装,是一种典型的装饰器设计模式。使用处理流主要是为了更方便的执行输入输出工作,如PrintStream,输出功能很强大,推荐输出时都使用处理流包装。

注意:一个IO流可以即是输入流又是字节流又或是以其他方式分类的流类型,是不冲突的。比如FileInputStream,它既是输入流又是字节流还是文件节点流。

4、一些特别的的流类型

转换流,转换流只有字节流转换为字符流,因为字符流使用起来更方便,我们只会向更方便使用的方向转化。如:InputStreamReader与OutputStreamWriter。

缓冲流,有关键字Buffered,也是一种处理流,为其包装的流增加了缓存功能,提高了输入输出的效率,增加缓冲功能后需要使用flush()才能将缓冲区中内容写入到实际的物理节点。但是,在现在版本的Java中,只需记得关闭输出流(调用close()方法),就会自动执行输出流的flush()方法,可以保证将缓冲区中内容写入。

对象流,有关键字Object,主要用于将目标对象保存到磁盘中或允许在网络中直接传输对象时使用(对象序列化),具体可参看博客Java序列化与反序列化

推回输入流,有关键字PushBack,当程序调用推回输入流的unread()方法时,系统回把指定数组内容的内容推回到一个推回缓冲区中,在调用read()方法读入内容时,就先从推回缓冲区中读取,直到读完推回缓冲区中内容后才会从原输入流中读取。

必须要掌握的流用法实例: 
1、FileInputStream\FileOutputStream\FileReader\FileWriter(使用方法类似)

//文件字节输入流FileInputStream用法
public class TestFileIO1 {
public static void main(String[] args)throws IOException{
//此处路径可以使用相对路径与绝对路径
FileInputStream fileInputStream = new FileInputStream("D:\\Git\\TCCP\\IO\\src\\package1\\TestFileIO1.java");
//一个字节数组作为缓冲,意为每次读取1024个字节,提高效率
byte[] buffer = new byte[1024];
//记录读取的字节数
int hasRead = 0;
//调用read()方法,返回实际读取的字节数
while((hasRead = fileInputStream.read(buffer)) > 0){
System.out.print(new String(buffer, 0, hasRead));
}
//关闭流
fileInputStream.close();
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
//文件字符输入流FileReader用法
public class TestFileIO2 {
public static void main(String[] args)throws IOException{
FileReader fileReader = new FileReader("D:\\Git\\TCCP\\IO\\src\\package1\\TestFileIO2.java");
char[] buffer = new char[32];
int hasRead = 0;
while((hasRead = fileReader.read(buffer)) > 0){
System.out.print(new String(buffer, 0, hasRead));
}
fileReader.close();
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
//文件字节输入流FileInputStream与文件字节输出流FileOutputStream结合
public class TestFileIO3 {
public static void main(String[] args)throws IOException{
File result = new File("output.txt");
FileInputStream fileInputStream = new FileInputStream("D:\\Git\\TCCP\\IO\\src\\package1\\TestFileIO3.java");
FileOutputStream fileOutputStream = new FileOutputStream(result);
byte[] buffer = new byte[1024];
int hasRead = 0;
while((hasRead = fileInputStream.read(buffer)) > 0){
fileOutputStream.write(buffer, 0, hasRead);
}
System.out.println(result.getAbsolutePath());
fileInputStream.close();
fileOutputStream.close();
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
//文件字符输出流FileWriter用法
public class TestFileIO4 {
public static void main(String[] args)throws IOException{
File result = new File("output.txt");
FileWriter fileWriter = new FileWriter(result);
fileWriter.write("飞流直下三千尺,\r\n");
fileWriter.write("疑是银河落九天.\r\n");
fileWriter.close();
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2、输出处理流PrintStream用法

public class TestFileIO5 {
public static void main(String[] args)throws IOException{
File result = new File("output.txt");
FileOutputStream fileOutputStream = new FileOutputStream(result);
//PrintStream处理流功能极其强大,所有字节输出流都应使用PrintStream包装
PrintStream printStream = new PrintStream(fileOutputStream);
printStream.println("床前明月光,");
fileOutputStream.close();
printStream.close();
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3、转换流inputStreamReader与缓冲流BufferedReader用法

public class TestFileIO6 {
public static void main(String[] args)throws IOException{
//系统输入为System.in,默认为从键盘输入,是字节输入流InputStream类型
//使用转换流将InputStream转换为Reader字符输入流对象
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
//将Reader包装为字符缓存处理流BufferedReader对象
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
//定义缓存行
String bufferString = null;
//使用BufferedReader特色readLine()方法逐行读取输入
while((bufferString = bufferedReader.readLine()) != null){
//直到输入exit,停止程序
if(bufferString.equals("exit")){
System.exit(0);
}
//控制台输出输入内容
System.out.println("输入内容为:" + bufferString);
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

4、推回输入流PushbackInputStream

//通过一个返回某个字符串之前的文件内容的demo,理解推回输入流的读取缓存机制
public class TestFileIO7 {
public static void main(String[] args)throws IOException{
//创建一个推回字节输入流对象,指定缓冲区为64
PushbackReader pushbackInputStream = new PushbackReader(new FileReader("D:\\Git\\TCCP\\IO\\src\\package1\\TestFileIO7.java"), 64);
char[] buffer = new char[32];
//记录上次读取的字符串
String lastContent = "";
int hasRead = 0;
while((hasRead = pushbackInputStream.read(buffer)) > 0){
//将读取的字符转换为字符串
String content = new String(buffer, 0, hasRead);
int targetIndex = 0;
//将上次读取的字符串和本次读取的字符串拼接
//查找拼接后的字符串是否包含"new PushbackReader"(文件为此段源代码),返回位置由targetIndex记录
if((targetIndex = (lastContent + content).indexOf("targetIndex")) > 0){
//将拼接后字符串转化成字符数组后推回缓冲区
String newContent = lastContent + content;
pushbackInputStream.unread(newContent.toCharArray());
//定义一个长度为targetIndex的char数组,如果新大小大于32,则需要重新定义
if(targetIndex > 32){
buffer = new char[targetIndex];
}
//再次读取targetIndex长度的内容,其实就是目标字符串之前的内容
pushbackInputStream.read(buffer, 0, targetIndex);
//输出结果
System.out.println(new String(buffer, 0, targetIndex));
//退出程序
System.exit(0);
}
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

5、重定向标准输入\输入 
Java的标准输入为System.in默认为键盘输入,标准输入为System.out默认为屏幕输出。可通过setInt(InputStream in)方法与setOut(PrintStream out)方法修改(在这里,连标准输出的字节输出流都被包装成了PrintStream,我们在编程时有什么理由不适用输出流呢?)。

public class TestFileIO8 {
public static void main(String[] args)throws IOException{
FileInputStream fileInputStream = new FileInputStream("input.txt");
//重定向默认输入
System.setIn(fileInputStream);
//一次性创建PrintStream输出流对象(先创建文件字节输出流对象,再包装)
PrintStream printStream = new PrintStream(new FileOutputStream("output.txt"));
//重定向默认输出
System.setOut(printStream);
//获取System.in(input.txt文件中)的输入
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
//下面这段标准输出会输出在Output.txt中
System.out.println("输入的内容为:" + scanner.next());
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

6、对象处理流ObjectInputStream\ObjectOutputStream 
对象要想保存在磁盘或在网络上传输,其实体类必须可序列化,它是将对象转化为字节序列,使其可以脱机运行。 
要想实现序列化,实体类必须实现java.io.serializable接口。

//创建一个可序列化的实体类
public class Person implements Serializable{ private String username;
private int age;
public Person(String username, int age){
this.username = username;
this.age = age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class TestObjectIO {
public static void main(String[] args) throws Exception{
//ObjectOutputStream是一个处理流,必须建立在节点流上才能工作
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("output.txt"));
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("output.txt"));
objectOutputStream.writeObject(new Person("Leeon", 21));
Person person = (Person)objectInputStream.readObject();
System.out.println(person.getUsername() + person.getAge());
objectInputStream.close();
objectOutputStream.close();
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangliangzi/article/details/51226652

面试题:JavaIO流分类详解与常用流用法实例的更多相关文章

  1. 详解 I/O流

    I/O流是用于处理设备之前信息传输的流,在我们今后的学习甚至是工作中,都是十分重要的. 在我们的日常生活中,也是很常见的,譬如:文件内容的合并.设备之键的文件传输,甚至是下载软件时的断点续传,都可以用 ...

  2. (转)dp动态规划分类详解

    dp动态规划分类详解 转自:http://blog.csdn.NET/cc_again/article/details/25866971 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间 ...

  3. android shape的使用详解以及常用效果(渐变色、分割线、边框、半透明阴影效果等)

    shape使用.渐变色.分割线.边框.半透明.半透明阴影效果. 首先简单了解一下shape中常见的属性.(详细介绍参看  api文档 ) 转载请注明:Rflyee_大飞: http://blog.cs ...

  4. mybatis 详解(三)------入门实例(基于注解)

    1.创建MySQL数据库:mybatisDemo和表:user 详情参考:mybatis 详解(二)------入门实例(基于XML) 一致 2.建立一个Java工程,并导入相应的jar包,具体目录如 ...

  5. webpack4配置详解之常用插件分享

    前言 继上一次webpack的基础配置分享之后,本次将分享一些工作中项目常用的配置插件.也会包含一些自己了解过觉得不错的插件,如有分析不到位的,欢迎纠错,嗯,这些东西文档都有,大佬可绕过. Wepac ...

  6. [转帖]Ipvsadm参数详解(常用命令)

    Ipvsadm参数详解(常用命令) 2013年11月29日 12:41:40 怀素1980 阅读数:15901   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...

  7. 分区工具parted的详解及常用分区使用方法【转】

    来源:http://blog.51cto.com/zhangmingqian/1068779 分区工具parted的详解及常用分区使用方法 一.         parted的用途及说明 概括使用说明 ...

  8. Git 命令详解及常用命令

    Git 命令详解及常用命令 Git作为常用的版本控制工具,多了解一些命令,将能省去很多时间,下面这张图是比较好的一张,贴出了看一下: 关于git,首先需要了解几个名词,如下: 1 2 3 4 Work ...

  9. RMAN命令详解和常用汇总

    RMAN命令详解和常用汇总转摘汇集,日后使用本文链接:https://blog.csdn.net/EVISWANG/article/details/50448370http://blog.itpub. ...

随机推荐

  1. 关于this指向问题的总结【转自秘密花园】

    this 的工作原理 JavaScript 有一套完全不同于其它语言的对 this 的处理机制. 在五种不同的情况下 ,this 指向的各不相同. 第一种:全局范围内 this; 当在全部范围内使用  ...

  2. fn project hot functions 说明

    1. 简单介绍 所谓 hot  functions 实际上就是长时间运行的functions ,简单理解类似后台任务 2. fnproject  处理的方式 fnproject 使用 类似 http的 ...

  3. Servlet概念入门

    什么是Servlet Servlet 为创建基于 web 的应用程序提供了基于组件.独立于平台的方法,可以不受 CGI 程序的性能限制.Servlet 有权限访问所有的 Java API,包括访问企业 ...

  4. 【brew使用技巧】fix links

    brew link --overwrite python

  5. Delphi从Internet下载文件

    Delphi从Internet下载文件   今天在做拍卖系统的时候,因考虑到网络状况问题,需要将拍品所有信息下载到本机,包括拍品图片,因此需要实现从Internet下载文件的功能.      下面是代 ...

  6. 上一步是硬件描述语言,下一步是FPGA

    上一步是硬件描述语言,下一步是FPGA. 学习了硬件描述语言(Verilog或者VHDL)之后,FPGA该如何继续. 世上没有捷径,每一步都得踏踏实实的走.学习FPGA也是这样,在有了硬件描述语言的基 ...

  7. 【转】JMeter基础之——录制脚本

    Jmeter 是一个非常流行的性能测试工具,虽然与LoadRunner相比有很多不足,比如:它结果分析能力没有LoadRunner详细:很它的优点也有很多: ● 开源,他是一款开源的免费软件,使用它你 ...

  8. ByteBuf 类——Netty 的数据容器

    1.堆缓冲区 2.直接缓冲区 3.复合缓冲区 —CompositeByteBuf——实现了这个模式,它提供了一 个将多个缓冲区表示为单个合并缓冲区的虚拟表示 适用于 JDK 所使用的一种称为分散/收集 ...

  9. Vue.js:监听属性

    ylbtech-Vue.js:监听属性 1.返回顶部 1. Vue.js 监听属性 本章节,我们将为大家介绍 Vue.js 监听属性 watch,我们可以通过 watch 来响应数据的变化: 实例 & ...

  10. web项目WebContent目录结构参考(WEB-INF)

    WEB-INF目录是Java WEB应用的安全目录,客户端(浏览器等)无法访问,只有服务端可以访问.该目录主要用来存放配置文件,如web.xml等. 若是将jsp文件放在WEB-INF目录中,则必须通 ...