IO流
IO :输入输出
字符流:输出流 Writer --> 需要通过刷新 或是关闭资源 ,才会将字符从缓存区写入文件
- 缓冲流也是
字符流的byte[]缓存 与 缓存流 作用一致,只是缓存大小设置会影响传输效率
流的使用步骤
- 1>选择合适的流对象
- 2>读/写
- 3>关闭最外层的流
本节目标
1.File类的学习
2.IO流的相关概念
3.IO流体系图
4.四个基础流 √
5.四个缓冲流 √
6.两个个对象流 √
7.其他流:
转换流
打印流
标准输入输出流
一.File类的学习
File类的概述和作用
File的概念
- File类是文件和目录路径名的抽象表示形式
- Java中把[文件]或者[目录(文件夹)]都封装成File对象
总结:
- 1)在java当中, 使用File类来表示(文件路径)或者是(文件夹路径)
- 2)思路: 如果今后要操作硬盘中的某一个文件或者是文件夹的话, 那么首先要考虑将要操作的文件或文件夹路径, 封装成File对象.
File类的常见方法
1.File构造器
File(String pathname);//根据字符串实例化File类的对象
File(String parent,String child);//根据父级字符串和子集字符串 创建File类的对象
File(File parent,String child);//根据父级File对象和子集字符串 创建File类的对象
2.File类的常用方法
a. 访问文件名
- getName() 获得文件或目录的名字
- getPath() 获得路径
- getAbsoluteFile() 获得当前文件绝对路径的File对象
- getAbsolutePath() 获得文件所在的绝对路径
- getParent() 获得父级的文件路径
- getParentFile() 获得父级的文件对象
- toPath()
- renameTo(File newName)
b. 文件检测
- exists() 判断是否存在
- canWrite() 判断是否可写
- canRead() 判断是否可读
- isFile() 判断是否是文件
- isDirectory() 判断是否是目录
c. 文件相关
- createNewFile() 新建文件(新文件所在的目录是必须存在的)
- delete()
d. 目录相关
- mkdir();新建一级文件夹
- mkdirs();新建多级文件夹
- delete() 只能删除空目录
- list() 返回当前目录下所有文件或目录的名称
- listFiles() 返回当前目录下所有文件或目录的File对象
e. 获取常规文件信息
- lastModified() 返回文件最后一次修改的时间
- length() 文件字节数
注意:
- File相对路径为当前项目文件夹
- 且文件夹分割符若为反斜杠需要转义
二.IO流的相关概念
为什么要学习IO流?
- 持久化数据至:文件、数据库、网络
1.IO流的相关概念
流:一组有顺序的、有起点和终点的字节集合,数据传输的统称
IO:Input/Output 输入/输出
源节点:文件、网络、键盘、内存
目标节点:文件、网络、显示器、内存
注意:Java中的流的一端必须是程序(内存)
2.IO流的分类
按流向不同进行分类:
- 输入流:Input。数据从源节点传输到程序 ,负责读数据
- 输出流:Output。数据从程序传输到目标节点, 负责写数据
按传输单位不同进行分类:
- 字节流:传输单位是字节,能传输除了纯文本以外的所有数据,比如图片、视频、音频
- 字符流:传输单位是字符,往往用于读写纯文本文件。
按功能不同进行分类:
- 基础流(节点流):用于将数据从一个节点传输到另一个节点,没有它不行
- 增强流(处理流):用于在基础流的基础上增强功能,比如提高效率、序列化或反序列化等
三.IO流的体系图
1.InputStream字节输入流
- FileInputStream 文件字节输入流(文件——>程序,以字节为传输单位)
- BufferedInputStream 缓冲字节输入流(提高效率)
- ObjectInputStream对象字节输入流(反序列化)
2.OutputStream字节输出流
- FileOutputStream 文件字节输出流(程序——>文件,以字节为传输单位)
- BufferedOutputStream 缓冲字节输出流(提高效率)
- ObjectOutputStream对象字节输出流(序列化)
3.Reader字符读取流
- FileReader 文件字符读取流(文件——>程序,以字符为传输单位)
- BufferedReader缓冲字符读取流(提高效率)
4.Writer字符写入流
- FileWriter 文件字符写入流(程序——>文件,以字符为传输单位)
- BufferedWriter缓冲字符写入流(提高效率)
流的使用步骤
步骤1:创建流对象
步骤2:进行读read/写write操作
步骤3:关闭流,释放资源
注意:Java中的流的一端必须是程序(内存)
四.基础流
1.FileInputStream
**功能:**将数据以字节为单位从文件读取到程序
构造器
- new FileInputStram(String pathName)
- 该路径字符串指向的文件,要求必须存在,否则报受检异常FileNotFoundexception
常见方法
int read():读取单个字节,以整数形式返回该字节,如果读到文件末尾,返回-1
int read(byte[]):读取多个字节到byte[],返回读取到的实际字节个数,如果读到文件末尾,返回-1
int read(byte[],off,len):读取多个字节到byte[]的指定部分,返回读取到的实际字节个数,如果读到文件末尾,返回-1
close():关闭流资源
注意:
创建FileInputStream对象,如果指向文件不存在,会发生什么?
- 答:会发生FileNotFoundException!
- 小贴士:要求读取的文件必须存在
相关API
- new String(byte[]):将整个byte数组转换成字符串
- new String(byte[],off,len):将byte数组的指定部分转换成字符串
2.FileOutputStream
功能:将数据以字节为单位从程序写入到文件
构造器
- 注意:该文件可以不存在;如果不存在则创建,否则编辑
- new FileOutputStram(String pathName); -->覆盖模式
- new FileOutputStram(String pathName,true); -->追加模式
常见方法
write(int):写入单个字节,如果在读取的过程中, 读取到了-1, 说明到达了文件的末尾
write(byte[]):写入多个字节
write(byte[],off,len):写入字节数组的指定部分
close():关闭流资源
相关API
- str.getBytes([String charsetName]):将字符串转换成指定字符集的byte[]
FileOutputStream写数据加入异常处理:
FileOutputStream fos = null;
try {//受检异常处理
fos = new FileOutputStream("d.txt");
fos.write("hello".getBytes());//使用平台默认字符集,将字符串转换为字节数组
} catch (IOException e) {
e.printStackTrace();
} finally {
//用于释放资源
if (fos != null) {
// 释放资源
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.FileReader
功能:按字符从文件到程序
构造器
- new FileReader(String pathName);
- new FileReader(File file);
- 要求:指向的文件必须存在,存在受检异常 FileNotFoundException
常见方法
read():读取单个字符,如果读到文件末尾,返回-1
read(char[]):读取多个字符到byte数组,默认索引从0开始,如果读到文件末尾,返回-1
read(char[],off,len):读取多个字符到char数组的指定部分,默认索引从off开始,如果读到文件末尾,返回-1
close():关闭资源
4.FileWriter
**功能:**按字符从程序到文件
构造器
new FileWriter(String pathName);构建一个FileWriter,默认指针指向文件的首端 【覆盖】
new FileWriter(File file);构建一个FileWriter对象,默认指针指向文件的首端 【覆盖】
new FileWriter(String pathName,true);构建一个FileWriter对象,默认指针指向文件的尾端 【追加】
new FileWriter(File file,true);构建一个FileWriter对象,默认指针指向文件的尾端 【追加】
注意:
- ①如果文件不存在,则自动创建;如果文件存在,则编辑
- ②可以通过在构造器中指定第二个参数true,设置写入的追加模式,否则默认为覆盖模式
- ③通过字符写入流将数据先写入到缓冲区,如果要写入到文件,则需通过flush方法,强制写入
- close():先刷新再关闭
- flush():只有刷新
常见方法
write(int)
write(char[])
write(char[],off,len)
write(string)
write(string,off,len)
close() ★:必须关闭或刷新,否则写入不到文件,只是写到缓存
close方法内部先调用了flush
相关API
new String(byte[]):将整个字节数组转换成字符串
new String(byte[],off,len):将字节数组中len个字节(索引从off开始)转换成字符串
string.getBytes():将字符串转换成byte[]
五、处理流
一)缓冲流
1.功能:提高效率
2.原理: 缓冲流类本身提供了一个缓冲区数组,默认大小8192,数据先读/写到缓冲区,不用硬盘的文件和程序直接打交道,而是程序和缓冲区(内存)打交道,从而提高了效率
3.分类:
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
4.使用:
- 1.创建缓冲流对象,套接在一个对应的节点流基础上
- 2.执行读写
- 3.关闭流(只需要关闭最外层的流)
小贴士: 所有带缓冲区的写入流的写入,最后都要加flush或close方法,才能真正将数据写入到文件
多出来两个个好用的方法:
- readLine():一次读取一个文本行 belong BufferedReader
- newLine():写入一个行分隔符 belong BufferedWriter
newLine() --> 提高代码的移植性!
windowns : \r\n -> Windows自带记事本不会识别其他换行字符
Linux : \n
Mac : \r
二)对象流
1.功能:
提供了一系列读写基本类型和对象类型数据的方法,而且可以实现将存储的对象再还原回来
2.分类:
- ObjectOutputStream:对象字节输出流(序列化流) 将内存中的对象数据持久化到本地或网络
- ObjectInputStream:对象字节输入流(反序列化流)将本地或网络中的对象数据再还原回来
3.特点:
- 数组元素如果可以序列化,则对应数组对象也可以序列化;
- 集合可以进行序列化;
- 序列化对象中的属性也应该实现序列化接口
4.关于类的版本信息:versionUID
//测试序列化流
@Test
public void testObjectOutputStream() throws IOException {
//1.创建流对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src\\object.dat"));
//2.写入
oos.writeInt(100);
oos.writeDouble(12.5);
oos.writeChar('男');
oos.writeUTF("令狐冲");
oos.writeBoolean(true);
oos.writeObject(new Person("张亚飞"));
oos.writeObject(new Person("张进"));
//3.关闭
oos.close();
}
//测试反序列化流
@Test
public void testObjectInputStream() throws IOException, ClassNotFoundException {
//1.创建流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src\\object.dat"));
//2.写入:按存储对象的顺序读取
System.out.println(ois.readInt());
System.out.println(ois.readDouble());
System.out.println(ois.readChar());
System.out.println(ois.readUTF());
System.out.println(ois.readBoolean());
System.out.println(ois.readObject());
System.out.println(ois.readObject());
//3.关闭
ois.close();
}
三)转换流
1.功能
- 将字节流转换成字符流,更高效的处理数据
2.分类
- InputStreamReader:将InputStream–>Reader
- OutputStreamWriter:将OutputStream–>Writer
四)标准输入输出流
1.分类
- System.in 标准输入流,默认输入设备为:键盘,类型:InputStream
- System.out 标准输出流,默认输出设备为:显示器,类型:PrintStream
- System.err 标准错误流,默认输出设备为:显示器,类型:PrintStream
2.重定向:将输入输出流重定向于其他流
- System.setIn(InputStream);
- System.setOut(PrintStream);
- System.setErr(PrintStream);
//案例1:将键盘的数据读取到程序,并打印
//1.创建流对象
BufferedReader br = new BufferedReader( new InputStreamReader(System.in));
//2.读取
System.out.println(br.readLine());
//3.关闭
br.close();
//案例2:重定向,将键盘改为文件,将文件的数据读取到程序,并打印
//1.重定向
System.setIn(new FileInputStream("src\\joke.txt"));
//2.创建流对象
BufferedReader br = new BufferedReader( new InputStreamReader(System.in,"gbk"));
//3.读取
System.out.println(br.readLine());
//4.关闭
br.close();
五)打印流
功能
- 可以实现将任意类型的数据转换成字符串输出!
分类
- PrintStream 字节打印流
- PrintWriter 字符打印流
特点
1>只有输出,没有输入
2>提供了一系列打印基本类型或对象类型数据的方法
print()不换行打印
println()换行打印
printf()格式化输出
%s 字符串
%d 整型
%c 字符型
%f 浮点型
3>打印流调用打印方法,不需要显式处理异常
4>打印流具有自动刷新功能,但要满足以下两个条件
条件1》对应的 构造器传入boolean的参数true
new PrintStream(outputStream,true)
new PrintWriter(writer,true)
条件2》对于PrintStream来讲,要求必须调用println或write/print/printf方法+换行符的插入
对于PrintWriter来讲,要求必须调用println或printf或format方法中的某一个
5>打印流可以设置编码格式
/*
案例:从键盘输入字符串,要求将读取到的整行字符串转成大写输出到指定文件src\\chars.txt。
然后继续进行输入操作,直至当输入“e”或者“exit”时,退出程序。
*/
public static void main(String[] args) throws IOException {
//1.创建流对象
//字符缓存流+输入转换流+系统输入流:BufferedReader+InputStreamReader+System.in
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//2.循环读取
PrintStream out = System.out;//默认输出:显示器
while(true){
System.setOut(out);//重定向输出设备:显示器
System.out.println("请输入:");
String line = br.readLine();
if ("e".equalsIgnoreCase(line)||"exit".equalsIgnoreCase(line)) {
break;
}
//重定向输出设备:输出到本地文件的字节打印流
System.setOut(new PrintStream(new FileOutputStream("src\\chars.txt",true)));
System.out.println(line.toUpperCase());
}
//3.关闭流
br.close();
}
六)Properties类的使用
1.说明
- Properties属于Map集合框架中的Hashtable的子类,所以具备Hashtable的特点
2.特点
- ①存储键值对
- ②键不能重复,值可以重复
- ③不允许null键,null值
- ④Properites专门用于读写配置文件的
注: 配置文件专门用于存储项目的配置信息,
- 格式:键值对格式,
- 默认编码格式:ISO8859-1 ,键和值的类型都是String类型
示例:
- 键=值
相关API:
store(OutputStream/writer,String)
setProperty(String key,String value)
load(InputStream) ★
getProperty(String key) ★
getProperty(String key,String defaultValue)
配置文件加载-load(InputStream)的两种方式:
- 1)直接使用输入流:
- info.load(new FileInputStream(“src\user.properties”));
- 2)使用类加载器获取输入流
- info.load(Test.class.getClassLoader().getResourceAsStream(“src\user.properties”));//Test:当前类
案例:
//测试将键值对信息存储到Properties文件 程序——》文件
@Test
public void testSave() throws IOException {
//1.创建Properties对象
Properties info = new Properties();
//2.存储键值对信息到Properties集合容器 中
info.setProperty("username", "周杰伦");
info.setProperty("password", "123456");
//3.将Properties集合中的键值对写入到配置文件:调用Properties方法store()
FileOutputStream fos = new FileOutputStream("src\\user.properties");
info.store(fos, null);
//4.关闭流
fos.close();
}
//测试将配置文件的键值对信息读取到Properties文件 文件——》程序
@Test
public void testRead() throws IOException {
//1.创建Properties对象
Properties info = new Properties();
//2.加载
//info.load(new FileInputStream("src\\user.properties"));
info.load(Test.class.getClassLoader().getResourceAsStream("src\\user.properties"));//Test:当前类
//3.根据键获取值
System.out.println(info.getProperty("username"));
System.out.println(info.getProperty("password"));
}