IO流
【摘要】IO流~
前言
IO流相关概念
IO能力是一门编程语言的标准能力,几乎所有的编程语言都有IO的能力,但是,java语言的IO能力还是很强的。
IO可以简单解释为 对文件的输入输出操作。
- 文件[File],它是一个宽泛的概念,包含:
普通文件
块文件
网络文件
文件夹
设备文件
…
在OS中,比较重要一个概念是文件系统[FS], 比如:NTFS, FAT32, …
在java中,通过 java.io.File
类型来表示OS的文件,每一个OS的文件都可以使用一个路径来表示,而这个路径可以使用String类型来表达,并且我们可以很容易地把这个字符串所表示的路径转换成 File的实例。
如:
1 | String path = "E:\\JAVA实训\\note\\javase\\day01.txt"; //文件的路径 |
- 路径[path]
- 绝对路径[absolute path]:以盘符开头的路径
- 相对路径[relative path]:不以盘符开头的路径
每一个资源[文件]都有唯一的绝对路径。
File类
- File类[没有能力操作文件的内容]。
- 核心方法:
- length()
- canRead()
- canWrite()
- getAbsolutePath()
- getPath()
- getName()
- isFile()
- isDirectory()
- createNewFile(); //创建文件
- mkdir(); //创建目录
- mkdirs(); //创建目录结构,含父目录
- delete(); //删除文件、空目录
- deleteOnExit(); 在JVM进程退出之前再删除
- listFiles
- list
- …
注:利用File类的delete方法删除文件时,需要注意
A.被其它进程占用的文件 删除会失败。
B.有内容的文件夹 删除会失败。
流 [stream]
流的源头
文件、网络、内存、扫描器,….
流的目的地
文件、网络、内存、终端,…
流的分类
- 根据数据的流向
以JVM为界,流可以分为:- 输入流:把外界的数据读入到JVM之中。
- 输出流:把JVM之中的数据写出到外界。
- 以功能来划分
- 字节流:以字节为单位的流。
- 字符流:以字符为单位的流。[专门用来处理 文本类的文件]
- 根据流数据的包装过程:
- 节点流:又称为低级流,特点是:数据源明确,真实负责读写数据的流。
- 处理流:又称为高级流,特点是:不能单独存在(没意义),用来处理其他流,所有高级流都封装了某些特定功能的读写操作,目的是简化我们的读写操作具体的流。
综合以上前两种划分,共计可以分为:
字节流
字节输入流
1 | java.io.InputStream |
字节输出流
1 | java.io.OutputStream |
- 使用IO流的基本步骤:
1.把路径字符串转换成 File实例
2.有效性判断
3.创建流 [new ….]
4.循环读、写
5.释放资源
作业:
- 写一个程序,完成文件的COPY
- 写一个程序,完成文件夹的COPY。
节点流:
拥有真正的读写能力的流
1 | FileInputStream/FileOutputStream *[针对文件操作的字节流] |
过滤流 [FilterInputStream/FilterOutputStream]
本身没有读写能力,它必需架接在节点流的基础上,才能做读写操作,它可以在
节点流的基础上添加新的功能,如:
1 | BufferInputStream/BufferedOutputStream [添加缓存功能] |
IO流中API 的这种设计叫 装饰模式,它把类型分成两种:
A. 拥有核心基本能力的类
B. 装饰能力的类 [必需以 拥有基本能力的类 为构造]
基于这种模式,我们可以构建成功能强大的流:
1.构建一个带缓存功能的文件流
1 | BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)); |
2.构建一个带缓存并且读基本数据类型的流
1 | DataInputStream dis = new DataInputStream( |
3.构建一个带缓存并且读对象类型的流
1 | ObjectInputStream dis = |
读写基本数据类型
1 | DataInputStream |
读写对象数据类型 – 对象序列化
要想持久化一个对象,要求这个对象必需要实现 java.io.Serializable接口,而且这个对象的属性类型也必需要实现 Serializable。
如:
1 | public class Student implements Serializable{ |
之所以要把对象写入文件中,是为了保存此对象的状态[持久化它的数据]。
对于对象的集合 又该如何?
直接持久化集合即可【要求集合中的元素必需实现 Serializable】
如:
1 | List<Student> stuList = ....; |
利用IO流的知识,完成如下业务
我们之前开发过银行帐户类:Account,
改写:要求它的no属性是自动生成的,起始值A1000,每创建一个帐户,no自动增1,
如:A1001, A1002, A1003, …
1 | //Code |
并且也开发过它的业务类:AccountService
现在,在之前的基础上,提供一个业务接口:IAccountService
然后,改写之前的AccountService类,使用实现IAccountService接口.
新要求:
开发一个银行类 Bank, 要求此类是一个单例,它提供如下属性:
1 | private static final String PATH = ""; // 存放帐户文件的路径 |
字符流
以字符为处理的基本单位的流
字符输入流
1 | java.io.Reader |
字符输出流
1 | java.io.Writer |
InputStreamReader
把字节流转换成字符流的桥梁,它的构造:
public InputStreamReader(InputStream in); //默认字符集
public InputStreamReader(InputStream in, String charSet);//指定字符集
如:
在d:\\temp\\hehe.txt
文本文件,则可以用如下方式来打开:
1 | //1. |
了解
System.in => InputStream
它被JVM默认指定为 标准输入设备,也就是键盘
System.out => PrintStream [OutpuStream的子类]
它被JVM默认指定为 标准输出设备,也就是终端[console]
JVM允许我们修改标准输出输出设备,也就是对流进行重定向。
System.setIn() 和 System.setOut()
利用System.in和桥接器,我们可以让用户从键盘输入任意字符。
如:
1 | BufferedReader br = |
随机存取流
java.io.RandomAccessFile这个流既可以读也可以写。而且支持基本数据类型、对象类型的读和写。更关键的是,这个流支持文件指针的定位【指定从哪个位置开始读】
1 | 构造方法: |
思考:如何读取一个巨大的日志文件的最后一行?
作业:
请把 文件夹“文本文档”下的8个文本文件全部读取出来进行分析:
要求:
统计出空行的数量
英文单词的数量
中文词的数量
进阶:
分析每一个英文单词出现的次数。
结束语
作业现在不写~