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. [python] 获得所有的最长公共子序列

    两句闲话 得到两个序列的最长公共子序列(LCS)是个经典问题,使用动态规划,实现起来并不难. 一般来说,我们只是输出一个LCS.但是,老师布置的作业是输出所有的LCS. 解法 按照一般的方法,我们首先 ...

  2. [独孤九剑]持续集成实践(三)- Jenkins安装与配置(Jenkins+MSBuild+GitHub)

    本系列文章包含: [独孤九剑]持续集成实践(一)- 引子 [独孤九剑]持续集成实践(二)– MSBuild语法入门 [独孤九剑]持续集成实践(三)- Jenkins安装与配置(Jenkins+MSBu ...

  3. webstorm-前端javascript开发神器中文教程和技巧分享(转)

    webstorm是一款前端javascript开发编辑的神器,此文介绍webstorm的中文教程和技巧分享. webstorm8.0.3中文汉化版下载:百度网盘下载:http://pan.baidu. ...

  4. 阿里云ESC服务器安装tomcat后无法远程访问

    问题描述:服务器上面没有部署文件,安装了tomcat,在服务器本地能通过"localhost:8080"访问到tom猫页面 但是远程访问“外网ip+:8080”就访问不了 解决方案 ...

  5. 学习动态性能表(5)--v$session

    学习动态性能表 第五篇--V$SESSION  2007.5.29 在本视图中,每一个连接到数据库实例中的session都拥有一条记录.包括用户session及后台进程如DBWR,LGWR,arcch ...

  6. 避免Android内存泄露

    摘自:http://blog.csdn.net/xyz_lmn/article/details/7108011 Android的应用被限制为最多占用16m的内存,至少在T-Mobile G1上是这样的 ...

  7. acm中文版

    http://acm.nyist.net/JudgeOnline/problem.php?pid=1

  8. 不用jq的异步数据获取

    function LoadData(url, sign) {             var message = "";             if (sign == " ...

  9. 使用Inno SetUp脚本打包Winform程序

    在开发桌面程序时,往往需要用到打包工具将程序打包为exe可执行文件. 之前在项目中用了下 InstallShield Limited Edition for Visual Studio  2015,它 ...

  10. emqtt 2 (我要连服务器)

    这一篇,主要分析下,client 是怎么 connect server的,以及成功connect server 之后,会做哪些事情,session是怎么 start的. 由protocol 开始 之前 ...