文章目录
一、IO流概述和分类
IO流介绍
- IO:输入/输出(Input/Output)
- 流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输
- IO流就是用来处理设备间数据传输问题的。常见的应用: 文件复制; 文件上传; 文件下载
IO流的分类
- 按照数据的流向
- 输入流:读数据
- 输出流:写数据
- 按照数据类型来分
- 字节流
- 字符流
IO流的使用场景
- 如果操作的是纯文本文件,优先使用字符流
- 如果操作的是图片、视频、音频等二进制文件,优先使用字节流
- 如果不确定文件类型,优先使用字节流,字节流是万能的流
二、字节流
1.字节流概述
字节流抽象基类
- InputStream:这个抽象类是表示字节输入流的所有类的超类
- OutputStream:这个抽象类是表示字节输出流的所有类的超类
- 子类名特点:子类名称都是以其父类名作为子类名的后缀
字节输入流
- FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名
字节输入流读取数据的步骤
- 创建字节输入流对象
- 调用字节输入流对象的读数据方法
- 释放资源
字节输出流
- FileOutputStream(String name):创建文件输出流以指定的名称写入文件
使用字节输出流写数据的步骤
- 创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)
- 调用字节输出流对象的写数据方法
- 释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
2.字节流读数据的三种方式
方法名 | 说明 |
---|---|
int read() | 从此输入流中读取一个数据字节 |
int read(byte[] b) | 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中 |
int read(byte[] b, int off, int len) | 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中 |
3.字节流写数据的三种方式
方法名 | 说明 |
---|---|
void write(int b) | 将指定的字节写入此文件输出流 一次写一个字节数据 |
void write(byte[] b) | 将 b.length字节从指定的字节数组写入此文件输出流 一次写一个字节数组数据 |
void write(byte[] b, int off, int len) | 将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流一次写一个字节数组的部分数据 |
注意:
字节流写数据如何实现换行:
- windows:\n
- linux:\n
- mac:\r
字节流写数据如何实现追加写入
- public FileOutputStream(String name,boolean append)
- 创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头
4.字节流刷新和关闭的方法
方法名 | 说明 |
---|---|
flush() | 刷新流,之后还可以继续写数据 |
close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
三、字节缓冲流
1.字节缓冲流介绍
- lBufferOutputStream:该类实现缓冲输出流。通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
- lBufferedInputStream:创建BufferedInputStream将创建一个内部缓冲区数组。当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节
2.字节缓冲流构造方法
方法名 | 说明 |
---|---|
BufferedOutputStream(OutputStream out) | 创建字节缓冲输出流对象 |
BufferedInputStream(InputStream in) | 创建字节缓冲输入流对象 |
四、字符流
1.为什么会出现字符流
其实在我们学习完字节流之后,就会发现使用字节流也是能够操作纯文本文件的,那我们用字节流就好了啊,为什么会出现字符流呢?
当我们只想把文本文件中的中文读取到程序中,打印出来或者其他操作的时候。(并不想写到其他的文件中)这个时候字节流根本就做不到。
为什么呢?因为一个中文,在不同的编码环境下 他里面的字节数不一样,而字节流只能够一个字节一个字节的去读取,所以会出现乱码。
字符流 = 字节流 + 编码表
2.字符流读数据
介绍:
- Reader: 用于读取字符流的抽象父类
- FileReader: 用于读取字符流的常用子类
构造方法:
方法名 | 说明 |
---|---|
FileReader(File file) | 在给定从中读取数据的File的情况下创建一个新FileReader |
FileReader(String fileName) | 在给定从中读取数据的文件名的情况下创建一个新FileReader |
成员方法:
int read() | 一次读一个字符数据 |
int read(char[] cbuf) | 一次读一个字符数组数据 |
3.字符流写数据
介绍:
- Writer: 用于写入字符流的抽象父类
- FileWriter: 用于写入字符流的常用子类
构造方法:
方法名 | 说明 |
---|---|
FileWriter(File file) | 根据给定的File对象构造一个FileWriter对象 |
FileWriter(File file, boolean append) | 根据给定的 File 对象构造一个FileWriter对象 |
FileWriter(String fileName) | 根据给定的文件名构造一个FileWriter对象 |
FileWriter(String fileName, boolean append) | 根据给定的文件名以及指示是否附加写入数据的 boolean值来构造 FileWriter 对象 |
成员方法:
方法名 | 说明 |
---|---|
void write(int c) | 写一个字符 |
void write(char[] cbuf) | 写入一个字符数组 |
void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
void write(String str) | 写一个字符串 |
void write(String str, int off, int len) | 写一个字符串的一部分 |
4.字符流刷新和关闭的方法
方法名 | 说明 |
---|---|
flush() | 刷新流,之后还可以继续写数据 |
close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
五、字符缓冲流
介绍:
- BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途
- BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途
构造方法:
方法名 | 说明 |
---|---|
BufferedWriter(Writer out) | 创建字符缓冲输出流对象 |
BufferedReader(Reader in) | 创建字符缓冲输入流对象 |
1.字符缓冲流特有功能
BufferedReader
方法名 | 说明 |
---|---|
void newLine() | 写一行行分隔符,行分隔符字符串由系统属性定义 |
BufferedWriter
方法名 | 说明 |
---|---|
String readLine() | 读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符如果流的结尾已经到达,则为null |
六、IO六代码实例
xx地铁管理系统
针对xx地铁项目,需要开发一个信息化管理系统。请根据公司现有业务及需求完成该系统的初始设计。
【需求描述】
(1)记录管理人员信息。员工信息包括工号、姓名、性别和一个手机号,工号唯一标识每位员工。
(2)记录地铁站信息。地铁站信息包括地铁站编号、地铁站名称、所属路线。
【结构设计】
管理人员(工号,姓名,性别,手机号)
地铁站(地铁站编号,地铁站名称,所属路线)
【问题1】
请根据业务需求及结构,设计出管理人员类(Manager)和地铁站类(Subway)
要求:
1.包括所涉及的属性
2.要生成getter()&setter()方法
3.要包含无参和带全部参数的构造方法
4.要有相应的toString()方法,用于输出相关属性的值
【问题2】
运行程序,提示管理员进行登录,根据输入的工号和姓名判断是否登录成功,登录成功,进入下一步,登录失败,给出提示,结束程序
系统中现有管理人员信息如下:
10001,小王,男,13112345678
10002,老于,男,13212345678
10003,老方,男,13312345678
保存在当前项目模块下的managers.txt文件中
系统中现有地铁站信息如下:
s3002,南锣鼓巷,6号线
s5016,王府井,1号线
s2026,西直门,4号线
保存在当前项目模块下的subways.txt文件中
要求:
2.1. 运行程序,将managers.txt文件中的管理人员信息读取到集合中
2.1.1. 将读取到的一行数据切割成字符串数组
2.1.2. 将数组中的元素封装到Manager对象中
2.1.3. 将Manager对象添加到集合中
2.2. 将subways文件中的地铁站信息读取到另一个集合中
2.3. 给出提示,获取管理人员输入的工号和姓名
2.4. 判断管理人员信息集合中是否包含管理人员输入的工号和姓名,给出对应的登录结果
【问题3】
当管理人员登录成功后,给出选项提示,根据管理人员的选择,执行后续的操作
要求:
3.1. 给出提示: 1.查看地铁站 2.添加地铁站 3.退出
3.2. 获取管理人员输入的选择
3.3. 根据管理人员的选择,执行对应的操作
【问题4】
当管理人员选择1时,执行对应的查看地铁站操作
要求:
4.1. 判断地铁站集合中是否有地铁站信息
4.2. 如果没有地铁站信息,给出提示
4.3. 如果有地铁站信息,遍历集合,打印每个地铁站信息
【问题5】
当管理人员选择2时,执行对应的添加地铁站操作
要求:
5.1.依次给出提示,获取管理人员输入的地铁站信息,包括地铁站编号,地铁站名称,所属路线
5.2. 将管理人员输入的地铁站信息封装成对象,存储到集合中
5.3. 将集合中的地铁站信息更新到文件中,再次打开文件时,应该包含管理人员刚才录入进去的地铁站信息,程序结束
import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;
public class Test {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
BufferedReader bFileR1 = new BufferedReader(new FileReader("test/managers.txt"));
BufferedReader bFileR2 = new BufferedReader(new FileReader("test/subways.txt"