io流学习流程
说白了,本节的目的就是对 文件增删改查,先说一下学习顺序吧
- 定位文件
- File类可以定位文件:可以进行删除文件内容,读取文件本身信息等操作,但是不能读写文件内容
- 字符集
- 想要读取文件中的数据,就必须知道数据的底层形式(字节,字符)
- 读写文件内容
- IO流可以对硬盘中的文件进行读写
File类
File类学习流程
- 如何创建一个File类
- 使用File类,创建、删除、判断、获取
- 遍历文件夹
- 删除文件夹
File类概述和构造方法
-
File类介绍
- 它是文件和目录路径名的抽象表示
- 文件和目录是可以通过File封装成对象的
- 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已.它可以是存在的,也可以是不存在的.将来是要通过具体的操作把这个路径的内容转换为具体存在的
-
File类的构造方法
方法名 | 说明 |
---|---|
File(String pathname) | 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例 |
File(String parent, String child) | 从父路径名字符串和子路径名字符串创建新的 File实例 |
File(File parent, String child) | 从父抽象路径名和子路径名字符串创建新的 File实例 |
- 示例代码
public class FileDemo01 {
public static void main(String[] args) {
//File(String pathname): 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
File f1 = new File("E:\\iotest\\java.txt");
System.out.println(f1);
//File(String parent, String child): 从父路径名字符串和子路径名字符串创建新的 File实例
File f2 = new File("E:\\iotest","java.txt");
System.out.println(f2);
//File(File parent, String child): 从父抽象路径名和子路径名字符串创建新的 File实例
File f3 = new File("E:\\iotest");
File f4 = new File(f3,"java.txt");
System.out.println(f4);
}
}
绝对路径和相对路径
- 绝对路径
是一个完整的路径,从盘符开始 - 相对路径
是一个简化的路径,相对当前项目下的路径 - 示例代码
public class FileDemo02 {
public static void main(String[] args) {
// 是一个完整的路径,从盘符开始
File file1 = new File("D:\\iotest\\a.txt");
// 是一个简化的路径,从当前项目根目录开始
File file2 = new File("a.txt");
File file3 = new File("模块名\\a.txt");
}
}
File类创建功能-通过File创建文件
- 方法分类
方法名 | 说明 |
---|---|
public boolean createNewFile() | 当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件 |
public boolean mkdir() | 创建由此抽象路径名命名的目录 |
public boolean mkdirs() | 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录 |
- 示例代码
import java.io.File;
import java.io.IOException;
public class FileDemo02 {
public static void main(String[] args) throws IOException {
//需求1:我要在E:\\iotest目录下创建一个文件java.txt
File f1 = new File("E:\\iotest\\java.txt");
File parentFile = f1.getParentFile(); // E:\iotest 就是获取上一个文件夹/文件的内容
System.out.println("创建文件夹,解决因为文件不存在发生的异常:" + parentFile.mkdirs());
System.out.println("创建一个文件:" + f1.createNewFile()); // //注意点:文件所在的文件夹必须要存在.
System.out.println("--------");
//需求2:我要在E:\\iotest目录下创建一个目录JavaSE,不能创建多级
File f2 = new File("E:\\iotest\\JavaSE");
System.out.println(f2.mkdir());
System.out.println("--------");
//需求3:我要在E:\\iotest目录下创建一个多级目录JavaWEB\\HTML
File f3 = new File("E:\\iotest\\JavaWEB\\HTML");
System.out.println(f3.mkdirs());
System.out.println("--------");
// 获取当前模块路径
String currentPath=System.getProperty("user.dir");
//需求4:我要在当前模块目录下创建一个多级目录JavaWEB\\HTML
File f4 = new File("iotest4\\java.txt");
if( f4.getParentFile() != null && f4.getParentFile().mkdirs()){
System.out.println("成功创建文件夹");
}
System.out.println("创建一个文件:" + f4.createNewFile());
}
}
File类删除功能
Java中File.delete删除当前文件或者文件夹,java删除的文件,将会直接删除,不会进入回收站。
如果删除的是文件夹,则该文件必须为空,如果要删除一个非空的文件夹,则需要首先删除该文件夹下面每个文件和文件夹,才可以删除。
- 方法分类
方法名 | 说明 |
---|---|
public boolean delete() | delete方法只能删除文件和空文件夹 |
- 示例代码
public class FileDemo03 {
public static void main(String[] args) throws IOException {
// 获取当前模块路径
String currentPath=System.getProperty("user.dir");
// 删除文件
File f1 = new File("iotest\\java.txt");
f1.delete();
// 删除目录
File f2 = new File("iotest");
f2.delete();
}
}
File类判断和获取功能
- 判断功能
方法名 | 说明 |
---|---|
public boolean isDirectory() | 测试此抽象路径名表示的File是否为目录 |
public boolean isFile() | 测试此抽象路径名表示的File是否为文件 |
public boolean exists() | 测试此抽象路径名表示的File是否存在 |
- 获取功能
方法名 | 说明 |
---|---|
public String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串 |
public String getPath() | 将此抽象路径名转换为路径名字符串 |
public String getName() | 返回由此抽象路径名表示的文件或目录的名称 |
public File[] listFiles() | 返回此抽象路径名表示的目录中的文件和目录的File对象数组 |
- 示例代码
public class FileDemo04 {
public static void main(String[] args) {
//创建一个File对象
File f = new File("myFile\\java.txt");
// public boolean isDirectory():测试此抽象路径名表示的File是否为目录
// public boolean isFile():测试此抽象路径名表示的File是否为文件
// public boolean exists():测试此抽象路径名表示的File是否存在
System.out.println(f.isDirectory());
System.out.println(f.isFile());
System.out.println(f.exists());
// public String getAbsolutePath():返回此抽象路径名的绝对路径名字符串
// public String getPath():将此抽象路径名转换为路径名字符串
// public String getName():返回由此抽象路径名表示的文件或目录的名称
System.out.println(f.getAbsolutePath());
System.out.println(f.getPath());
System.out.println(f.getName());
System.out.println("--------");
// public File[] listFiles():返回此抽象路径名表示的目录中的文件和目录的File对象数组
File f2 = new File("E:\\iotest");
File[] fileArray = f2.listFiles();
for(File file : fileArray) {
// System.out.println(file);
// System.out.println(file.getName());
if(file.isFile()) {
System.out.println(file.getName());
}
}
}
}
File类练习-遍历文件夹下所有文件-控制台以树形展示
- 案例需求
遍历文件夹下所有文件
打印格式如下:
filemodule
|_aaa
|__a.txt
|___111.txt 0MB
|__b.txt 0MB
- 代码实现
import java.io.File;
class FileSystem {
public static void main(String[] args) {
File f = new File("filemodule");// 指定文件位置
System.out.println(f.getName());// 打印在这个文件下地文件夹;
tree(f, 1);// 方法!进入子文件夹中 并打印子文件名
}
private static void tree(File f, int level) {
File[] childs = f.listFiles();// 返回一个抽象路径名数组,这些路径名表示此抽象路径名所表示目录中地文件
for (int i = 0; i < childs.length; i++) {
// 打印前缀
for (int j = 0; j < level; j++) {
if (j == 0) {
System.out.print("|_");
} else {
System.out.print("_");
}
}
if (childs[i].isDirectory()) { //
System.out.println(childs[i].getName());// 打印子文件地名字
tree(childs[i], level + 1);
} else {
System.out.println(childs[i].getName() + "\t\t\t\t\t" + childs[i].length() / 1024 / 1024 + "MB");// 如果是文件把大小也打印出来
}
}
}
}
File类练习-删除文件夹所有内容
- 案例需求
删除一个多级文件夹 - 实现步骤
-
- 定义一个方法,接收一个File对象
- 遍历这个File对象,获取它下边的每个文件和文件夹对象
- 判断当前遍历到的File对象是文件还是文件夹
- 如果是文件夹,递归调用自己,将当前遍历到的File对象当做参数传递
- 将得到的文件或者空目录删除
- 参数传递过来的文件夹File对象已经处理完成,最后直接删除这个空文件夹
- 代码实现
import java.io.File;
public class Test2 {
public static void main(String[] args) {
/**
* delete方法只能删除文件和空文件夹
* 如果现在要删除一个有内容的文件夹
* 先删掉这个文件夹里面所有的内容
* 最后再删除这个文件夹
*/
File src = new File("iotest2");
remove(src);
}
/**
* 删除指定文件夹下的全部内容
*
* @param file
*/
public static void remove(File file) {
File[] files = file.listFiles();//将file子目录及子文件放进文件数组
if (files != null) {//如果包含文件进行删除操作
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {//通过递归方法删除子目录的文件
remove(files[i]);
}
files[i].delete();//删除子目录/子文件
}
file.delete(); // 删除传过来的目录
}
}
}
字符集
字符集相关概念
我们是怎么把文字存储到计算机的
- 我们把文字转换成十进制的表现方式(比如“a”相当于97),然后转换成二进制,然后就可以存储到计算机。
什么是字符集?什么叫字符编码
字符集(Character set)是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。计算机要准确的存储和识别各种字符集符号,就需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等
- 字符集:规定了字符和字符码之间的对应关系。 可以将字符集理解成一个很大的表格,它列出了所有字符和二进制的对应关系,计算机显示文字或者存储文字,就是一个查表的过程。
- 字符编码:规定了一个字符码在计算机中如何存储。
常用字符集
-
ASCII字符集(American Standard Code for Information Interchange,美国信息交换标准代码)
- 是最早产生的编码规范,包括数字、英文、符号
- 一个字节存储一个字符,也就是8位,总共可以表示128个字符信息(2^8=256,不包括负数)
-
GBK(即“国标”“扩展”汉语拼音的第一个字母) 字符集:全称《汉字内码扩展规范》
- window系统默认的码表。兼容ASCII码表,包括中日韩
- 一个中文以两个字节存储,英文1个字节
- Unicode字符集(又叫万国码、统一码):是计算机科学领域里的一项业界字符编码规范
- Unicode包含了全世界所有的字符,兼容ASCII 。Unicode最多可以保存4个字节容量的字符。也就是说,要区分每个字符,每个字符的地址需要4个字节。这是十分浪费存储空间的,于是,程序员就设计了几种字符编码方式,比如:UTF-8,UTF-16,UTF-32。最广为程序员使用的就是UTF-8,UTF-8是一种变长字符编码,注意:UTF-8不是编码规范,而是编码方式。
- utf-8:一个中文以3个字节存储,英文1个字节
- Unicode包含了全世界所有的字符,兼容ASCII 。Unicode最多可以保存4个字节容量的字符。也就是说,要区分每个字符,每个字符的地址需要4个字节。这是十分浪费存储空间的,于是,程序员就设计了几种字符编码方式,比如:UTF-8,UTF-16,UTF-32。最广为程序员使用的就是UTF-8,UTF-8是一种变长字符编码,注意:UTF-8不是编码规范,而是编码方式。
小结
- 英文和数字在任何国家的字符集中都占一个字节(在任何国家的编码中都不会乱码)
- GBK中一个中文字符2个字节
- UTF-8中一个中文字符3个字节
- 编码前的字符集和编码后的字符集必须一致,否则乱码
- 中文的字节存储方式
- 用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼接成中文,如何识别是中文的呢?
- 汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数
字符集的编码、解码操作
代码如下:
class FileSystem {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "a1爱";
byte[] gbks1 = str.getBytes();
System.out.println(gbks1.length);
System.out.println("以当前默认字符集编码:" + Arrays.toString(gbks1));
System.out.println("以当前默认字符集解码:" + new String(gbks1));
byte[] gbks2 = str.getBytes("GBK");
System.out.println(gbks2.length);
System.out.println("指定以GBK编码:" + Arrays.toString(gbks2));
System.out.println("以当前默认字符集解码GBK编码的数据:" + new String(gbks2));
System.out.println("指定以GBK解码:" + new String(gbks2,"GBK"));
}
}
输出如下
5
以当前默认字符集编码:[97, 49, -25, -120, -79]
以当前默认字符集解码:a1爱
4
指定以GBK编码:[97, 49, -80, -82]
以当前默认字符集解码GBK编码的数据:a1��
指定以GBK解码:a1爱
汉字的存储和解析过程
IO流
IO流的使用流程
- 创建输入/输出流
- 读/写 操作
- 关闭输入/输出流
IO流的概念与作用
I/O是Input/Output的缩写, 用于处理设备之间的数据传输。如读/写文件,网络通讯等。
流是一种抽象概念,它代表了数据的无结构化传递。
Java程序中,对于数据的输入/输出操作以”流(stream)” 的方式进行,所以叫io流。java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。常见的应用: 文件复制; 文件上传; 文件下载
IO流的分类
按照数据的流向(方向)
- 输入流:读数据,是数据从硬盘文件读入到内存的过程 =》 硬盘->内容
- 输出流:写数据,是内存程序的数据从内存写出到硬盘文件的过程=》内存->硬盘
按照数据类型(单位)
- 字节流:以字节为单位,可以读写所有数据
- 字符流:以字符为单位
使用场景
如果操作的是纯文本,比如json文件,txt文件,优先使用字符流
- 怎么判断是纯文本呢? 能用记事本打开并且能看懂的就是纯文本
如果是图片、视频、音频等二进制文件,优先使用字节流
如果不确认文件类型,优先使用字节流,字节流是万能的流
IO流体系结构图
字节流(byte) | 字符流(char) | |||
---|---|---|---|---|
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
抽象基类 | InputStream | OutputStream | Reader | Writer |
操作文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
操作数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
转换流 | InputStreamReader | OutputStreamWriter | ||
对象操作流 | ObjectInputStream | ObjectOutputStream | ||
打印流 | PrintStream | PrintWriter |
其中,转换流都是字节流转字符流。
- OutputStreamWriter : 字节输出流 -> 字符输出流;
- InputStreamReader : 字节输入流 -> 字符输入流
对象操作流也叫序列化流
字节流/字符流基础操作
字节输入流InputStream主要方法:
-
read() :从此输入流中读取一个数据字节。
-
read(byte[] b) :从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
-
read(byte[] b, int off, int len) :从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
-
close():关闭此输入流并释放与该流关联的所有系统资源。
字节输出流OutputStream主要方法:
- write(byte[] b) :将 b.length 个字节从指定 byte 数组写入此文件输出流中。
- write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
- write(int b) :将指定字节写入此文件输出流。
- flush() :刷新流,之后还可以继续写数据
- close() :关闭此输入流并释放与该流关联的所有系统资源。
字符输入流Reader主要方法:
- read():读取单个字符。
- read(char[] cbuf) :将字符读入数组。
- read(char[] cbuf, int off, int len) : 将字符读入数组的某一部分。
- read(CharBuffer target) :试图将字符读入指定的字符缓冲区。
- close() :关闭此流,但要先刷新它。
字符输出流Writer主要方法:
-
write(char[] cbuf) :写入字符数组。
-
write(char[] cbuf, int off, int len) :写入字符数组的某一部分。
-
write(int c) :写入单个字符。
-
write(String str) :写入字符串。
-
write(String str, int off, int len) :写入字符串的某一部分。
-
flush() :刷新流,之后还可以继续写数据
-
close() :关闭此流,但再次之前刷新它。 一旦流已关闭,进一步的write()或flush()调用将导致抛出IOException。 关闭以前关闭的流无效。
另外,字符缓冲流还有两个独特的方法:
- BufferedWriter类newLine() :写入一个行分隔符。这个方法会自动适配所在系统的行分隔符。
- BufferedReader类readLine() :读取一个文本行。
注意:输出流必须刷新才能写入,当然也可以直接调用
close()
,他里面包含了flush
,但是使用close()
关闭流后就不能在使用了如上,常用方法
输入流都有read方法
输出流都有write,flush方法
字节输入流读文件
代码如下:
public class ByteInputStreamTest1 {
public static void main(String[] args) throws IOException {
/**
* 字节输入流的使用方式
*/
// 1、创建输入流 => InputStream
InputStream fileInputStream = new FileInputStream("aa.txt"); // abc123测试
// 2、读文件
// read() :从此输入流中读取一个数据字节。
int read = fileInputStream.read();
System.out.println(read); // 97
System.out.println((char) read); // a
byte[] buffered = new byte[3];
// read(byte[] b) :从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
//int read1 = fileInputStream.read(buffered);
//System.out.println(read1); // 读取的字符数量 => 3
//System.out.println(Arrays.toString(buffered)); // [98, 99, 49]
//System.out.println(new String(buffered)); // bc1
// read(byte[] b, int off, int len) :从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
int read2 = fileInputStream.read(buffered, 0, 2);
System.out.println(read2); // 2
System.out.println(Arrays.toString(buffered)); // [98, 99, 0]
System.out.println(new String(buffered)); // bc
// 如果没有读取到呢吗返回-1
// 3、关闭资源
fileInputStream.close();
}
}
字符输入流读文件
- 介绍
Reader: 用于读取字符流的抽象父类
FileReader: 用于读取字符流的常用子类 - 构造方法
方法名 | 说明 |
---|---|
FileReader(File file) | 在给定从中读取数据的 File 的情况下创建一个新 FileReader |
FileReader(String fileName) | 在给定从中读取数据的文件名的情况下创建一个新 FileReader |
- 成员方法
方法名 | 说明 |
---|---|
int read() | 一次读一个字符数据 |
int read(char[] cbuf) | 一次读一个字符数组数据 |
- 代码演示
import java.io.FileReader;
import java.io.IOException;
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("myCharStream\\b.txt");
//int read():一次读一个字符数据
int ch;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
// int read(char[] cbuf):一次读一个字符数组数据
char[] chs = new char[1024];
int len;
while ((len = fr.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
// 释放资源
fr.close();
}
}
字节输出流写数据
-
使用字节输出流写数据的步骤
- 创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)
- 调用字节输出流对象的写数据方法
- 释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
-
写数据的方法分类
方法名 | 说明 |
---|---|
void write(int b) | 将指定的字节写入此文件输出流 一次写一个字节数据 |
void write(byte[] b) | 将 b.length字节从指定的字节数组写入此文件输出流 一次写一个字节数组数据 |
void write(byte[] b, int off, int len) | 将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流 一次写一个字节数组的部分数据 |
- 示例代码
package ioreview.bytestream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo02 {
public static void main(String[] args) throws IOException {
// 1、创建输出流
//FileOutputStream(String name):创建文件输出流以指定的名称写入文件
//FileOutputStream fos = new FileOutputStream("fos.txt");
// FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件
FileOutputStream fos = new FileOutputStream(new File("fos.txt"));
// 2、写入数据
// void write(int b):将指定的字节写入此文件输出流
fos.write(97);
fos.write(98);
fos.write(99);
//void write(byte[] b):将 b.length字节从指定的字节数组写入此文件输出流
byte[] bys = {97, 98, 99};
fos.write(bys);
//byte[] getBytes():返回字符串对应的字节数组
byte[] bys2 = "abc".getBytes();
fos.write(bys2);
// void write(byte[] b, int off, int len):将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流
fos.write(bys, 0, bys.length);
fos.write(bys, 1, 1);
// fos.flush(); // 刷新流,之后还可以继续写数据
// 3、关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据
fos.close();
}
}
字符输出流写文件
- 介绍
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) | 写一个字符串的一部分 |
- 刷新和关闭的方法
方法名 | 说明 |
---|---|
flush() | 刷新流,之后还可以继续写数据 |
close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
- 代码演示
import java.io.FileWriter;
import java.io.IOException;
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("myCharStream\\a.txt");
//void write(int c):写一个字符
fw.write(97);
fw.write(98);
fw.write(99);
// void writ(char[] cbuf):写入一个字符数组
char[] chs = {'a', 'b', 'c', 'd', 'e'};
fw.write(chs);
// void write(char[] cbuf, int off, int len):写入字符数组的一部分
fw.write(chs, 0, chs.length);
fw.write(chs, 1, 3);
// void write(String str):写一个字符串
fw.write("abcde");
// void write(String str, int off, int len):写一个字符串的一部分
fw.write("abcde", 0, "abcde".length());
fw.write("abcde", 1, 3);
// 释放资源
fw.close();
}
}
异常处理-处理释放资源
try-catch-finally
- 异常处理格式
- try-catch-finally
try{ 可能出现异常的代码;}catch(异常类名 变量名){ 异常的处理代码;}finally{ 执行所有清除操作;}
- 示例代码
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo04 {
public static void main(String[] args) {
//加入finally来实现释放资源
FileOutputStream fos = null;
try {
fos = new FileOutputStream("myByteStream\\fos.txt");
fos.write("hello".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//最后先关闭输出,在关闭输入,防止空指针异常加入if
if (fos != null) fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
try-catch-resource
jdk1.7后增加了try-with-resources,他是一个声明一个或多个资源的try语句,且()
中只能放置资源对象,否则报错。一个资源作为一个对象,必须在程序结束之后关闭。try-with-resources语句确保在语句的最后每个资源都被关闭,任何实现了java.lang.AutoCloseable和java.io.Closeable的对象都可以使用try-with-resource来实现异常处理和关闭资源。
- 异常处理格式
- try-catch-resource
try(定义流对象){
}catch(){
}
- 示例代码
public class Test9 {
//JDK7改进方案
public static void main(String[] args) {
try (//这里只能放置资源对象,用完会自动关闭,自动调用资源对象的close方法关闭资源(即使出现异常也会做关闭操作)
InputStream io = new FileInputStream("src/aaa.txt");
OutputStream ot = new FileOutputStream("D:/www.txt");
//int a=1;//报错这里只能写资源
) {
byte[] arr = new byte[1024];
int len;
while ((len = io.read(arr)) != -1) {
ot.write(arr, 0, len);
}
System.out.println("文件拷贝成功");
} catch (IOException e) {
e.printStackTrace();
}
}
}
输出流写数据-换行/追加数据
-
写数据如何实现换行
- windows:\r\n
- linux:\n
- mac:\r
-
写数据如何实现追加写入
- public FileOutputStream(String name,boolean append)
- 创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头
-
示例代码
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo03 {
public static void main(String[] args) throws IOException {
//创建字节输出流对象
// FileOutputStream fos = new FileOutputStream("fos.txt");
FileOutputStream fos = new FileOutputStream("fos.txt", true);
// 写数据
for (int i = 0; i < 10; i++) {
fos.write("hello".getBytes());
fos.write("\r\n".getBytes());
}
// 释放资源
fos.close();
}
}
如何使用字节输入流读取中文内容输出不乱码?
- 定义一个与文件一样大的字节数组,一次性读取文件全部字节,但是如果文件过大,字节数据可能溢出
字节流复制练习
字节文件输入/输出流
代码
package ioreview.bytestream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author 韦存滨
* @className Test1
* @description 文件字节输入/输出流 完成文件复制
* @date 2023年02月11日 23:17
*/
public class Test1 {
public static void main(String[] args) {
// 复制 - 其实下载也相当于一个复制,从网下下载到本地
// 1、创建输出流/输出流
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream("aa.txt");
fileOutputStream = new FileOutputStream("bb.txt");
// 2、读/写数据
String data = "";
byte[] bytes = new byte[1024];
int length;
while ((length = fileInputStream.read(bytes)) != -1) {
// 输出文件到
fileOutputStream.write(bytes, 0, length);
data += new String(bytes);
}
System.out.println("输出的文件内容为:" + data);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3、关闭流
try {
if (fileInputStream != null) {
fileInputStream.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (Exception e) {
}
}
}
}
字节数组输入/输出流
代码
package ioreview.bytestream;
import java.io.*;
/**
* @author 韦存滨
* @className Test1
* @description 字节数组输入/输出流 完成文件复制
* @date 2023年02月11日 23:17
*/
public class Test2 {
public static void main(String[] args) {
// 1、创建输出流/输出流
ByteArrayInputStream byteArrayInputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
String data = "abc123测试";
byte[] dataBytes = data.getBytes();
byteArrayInputStream = new ByteArrayInputStream(dataBytes);
byteArrayOutputStream = new ByteArrayOutputStream();
// 2、读/写数据
byte[] bytes = new byte[3];
int length;
while ((length = byteArrayInputStream.read(bytes)) != -1) {
byteArrayOutputStream.write(bytes, 0, length);
System.out.println(byteArrayOutputStream);
}
// 2.1、获取文件内容
byte[] bytes1 = byteArrayOutputStream.toByteArray();
String s = new String(bytes1);
System.out.println("读取的内容是:" + s);
// 或者直接输出
System.out.println("读取的内容是:" + byteArrayInputStream.toString());
int size = byteArrayOutputStream.size();
// 将此 byte 数组输出流的
// count 字段重置为零,从而丢弃输出流中目前已累积的所有输出。通过重新使用已分配的缓冲区空间,
// 可以再次使用该输出流
//byteArrayOutputStream.reset();
// 2.2、将此数组输出流的全部内容写入到指定的输出流参数中
FileOutputStream fileOutputStream = new FileOutputStream("cc88.txt");
byteArrayOutputStream.writeTo(fileOutputStream);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (byteArrayInputStream != null) {
byteArrayInputStream.close();
}
if (byteArrayOutputStream != null) {
byteArrayOutputStream.close();
}
} catch (Exception e) {
}
}
}
}
字节缓冲输入/输出流
代码
package ioreview.bytestream;
import java.io.*;
/**
* @author 韦存滨
* @className Test1
* @description 字节缓冲输入/输出流 完成文件复制
* @date 2023年02月11日 23:17
*/
public class Test3 {
public static void main(String[] args) {
// 1、创建输出流/输出流
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
bufferedInputStream = new BufferedInputStream(new FileInputStream("aa.txt"));
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("bb.txt"));
String data = "";
byte[] bytes = new byte[1024];
int length;
while ((length = bufferedInputStream.read(bytes)) != -1) {
data += new String(bytes);
bufferedOutputStream.write(bytes, 0, length);
}
System.out.println("读取的内容是:" + data);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3、关闭流
try {
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
} catch (Exception e) {
}
}
}
}
字节缓冲流——old
缓冲流的主要作用就是提高流的读取,写入效率。
- 操作方式:字节流字节操作文件,字节缓冲流先将数据添加到缓冲区,再将数据写入到文件中(或者读取文件);
- 效率:字节缓冲流的效率要高于字节流;(例子:把一堆砖头从A地搬往B地,一块一块的搬(字节流)的效率要远低于 先把砖头装进小推车再运往B地(缓冲流))
字节缓冲流构造方法
- 构造方法:
方法名 | 说明 |
---|---|
BufferedOutputStream(OutputStream out) | 该类实现缓冲输出流.通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用 |
BufferedInputStream(InputStream in) | 创建BufferedInputStream将创建一个内部缓冲区数组.当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节 |
- 示例代码
public class CopyAviDemo {
public static void main(String[] args) throws IOException {
//复制视频
// method1();
method2();
}
//字节缓冲流一次读写一个字节数组
public static void method2() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\iotest\\字节流复制图片.avi"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myByteStream\\字节流复制图片.avi"));
byte[] bys = new byte[1024];
int len;
while ((len=bis.read(bys))!=-1) {
bos.write(bys,0,len);
}
bos.close();
bis.close();
}
//字节缓冲流一次读写一个字节
public static void method1() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\iotest\\字节流复制图片.avi"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myByteStream\\字节流复制图片.avi"));
int by;
while ((by=bis.read())!=-1) {
bos.write(by);
}
bos.close();
bis.close();
}
}
案例-字节缓冲流复制视频
-
案例需求
把“E:\itcast\字节流复制图片.avi”复制到模块目录下的“字节流复制图片.avi” -
实现步骤
-
- 根据数据源创建字节输入流对象
- 根据目的地创建字节输出流对象
- 读写数据,复制视频
- 释放资源
-
代码实现
import java.io.*;
public class FileCopy {
public static void main(String[] args) {
/**
* 复制文件
*/
BufferedInputStream in = null;
BufferedOutputStream out = null;
try {
//abc.txt ->内存
in = new BufferedInputStream(new FileInputStream("aa.jpg"));
//内存 ->xyz.txt
out = new BufferedOutputStream(new FileOutputStream("cc.jpg"));
//开辟缓冲区 数组 将文件内容在数组中读取
byte[] buf = new byte[1024];
int len;
// int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
//在不等于-1 说明文件里还有字节 一直输入直到 返回值为-1
while ((len = in.read(buf)) != -1) {
// void write(byte[]b,int off,int len)将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流 一次写一个字节数组的部分数据
out.write(buf, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//最后先关闭输出,在关闭输入,防止空指针异常加入if
if (out != null) out.close();
if (in != null) in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符流
为什么会出现字符流
- 字符流的介绍
- 由于字节流操作中文不是特别的方便,所以Java就提供字符流
- 字符流 = 字节流 + 编码表
字符串中的编码解码问题
- 相关方法
方法名 | 说明 |
---|---|
byte[] getBytes() | 使用平台的默认字符集将该 String编码为一系列字节 |
byte[] getBytes(String charsetName) | 使用指定的字符集将该 String编码为一系列字节 |
String(byte[] bytes) | 使用平台的默认字符集解码指定的字节数组来创建字符串 |
String(byte[] bytes, String charsetName) | 通过指定的字符集解码指定的字节数组来创建字符串 |
- 代码演示
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class StringDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
//定义一个字符串
String s = "123中";
byte[] bys1 = s.getBytes(); // 当前默认编码方式
byte[] bys2 = s.getBytes("UTF-8");
byte[] bys3 = s.getBytes("GBK");
System.out.println(Arrays.toString(bys1)); // [49, 50, 51, -28, -72, -83]
System.out.println(Arrays.toString(bys2)); // [49, 50, 51, -28, -72, -83]
System.out.println(Arrays.toString(bys3)); // [49, 50, 51, -42, -48]
String ss1 = new String(bys1); // 123中
String ss2 = new String(bys1, "UTF-8"); // 123中
String ss3 = new String(bys1, "GBK"); // 123涓�
System.out.println(ss1);
System.out.println(ss2);
System.out.println(ss3);
}
}
字符缓冲流
-
字符缓冲流介绍
- BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途
- BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途
-
构造方法
方法名 | 说明 |
---|---|
BufferedWriter(Writer out) | 创建字符缓冲输出流对象 |
BufferedReader(Reader in) | 创建字符缓冲输入流对象 |
- 代码演示
import java.io.*;
public class BufferedStreamDemo01 {
public static void main(String[] args) throws IOException {
//BufferedWriter(Writer out)
BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\bw.txt"));
bw.write("hello\r\n");
bw.write("world\r\n");
bw.close();
// BufferedReader(Reader in)
BufferedReader br = new BufferedReader(new FileReader("myCharStream\\bw.txt"));
// 一次读取一个字符数据
int ch;
while ((ch = br.read()) != -1) {
System.out.print((char) ch);
}
// 一次读取一个字符数组数据
char[] chs = new char[1024];
int len;
while ((len = br.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
br.close();
}
}
字符缓冲流特有功能
- 方法介绍
BufferedWriter:
BufferedReader:
方法名 | 说明 |
---|---|
void newLine() | 写一行行分隔符,行分隔符字符串由系统属性定义 |
方法名 | 说明 |
---|---|
String readLine() | 读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符如果流的结尾已经到达,则为null |
- 代码演示
import java.io.*;
public class BufferedStreamDemo02 {
public static void main(String[] args) throws IOException {
//创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\bw.txt"));
// 写数据
for (int i = 0; i < 10; i++) {
bw.write("hello" + i);
bw.write("\r\n");
bw.newLine();
bw.flush();
}
// 释放资源
bw.close();
// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("myCharStream\\bw.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
}
转换流
字符流中和编码解码问题相关的两个类
- InputStreamReader:是从字节流到字符流的桥梁,父类是Reader
它读取字节,并使用指定的编码将其解码为字符
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集 - OutputStreamWriter:是从字符流到字节流的桥梁,父类是Writer
是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
转换流读写数据
- 构造方法
方法名 | 说明 |
---|---|
InputStreamReader(InputStream in) | 使用默认字符编码创建InputStreamReader对象 |
InputStreamReader(InputStream in,String chatset) | 使用指定的字符编码创建InputStreamReader对象 |
OutputStreamWriter(OutputStream out) | 使用默认字符编码创建OutputStreamWriter对象 |
OutputStreamWriter(OutputStream out,String charset) | 使用指定的字符编码创建OutputStreamWriter对象 |
- 代码演示
import java.io.*;
public class ConversionStreamDemo {
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("fos.txt"));
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("fos.txt"), "GBK");
osw.write("中国");
osw.close();
InputStreamReader isr = new InputStreamReader(new FileInputStream("fos.txt"));
//InputStreamReader isr = new InputStreamReader(new FileInputStream("fos.txt"), "GBK");
// 一次读取一个字符数据
int ch;
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
}
isr.close();
}
}
对象操作流
对象序列化流
序列化:将对象的状态信息转换为可以存储或传输的形式的过程。程序通过序列化把Java对象转换成二进制字节流,然后就可以把二进制字节流写入网络或磁盘。
反序列化:读取磁盘或网络中的二进制字节流数据,转化为Java对象
序列化流:ObjectOutputStream
反序列化流:ObjectInputStream
注意事项
- 一个对象要想被序列化,该对象所属的类必须必须实现Serializable 接口
- Serializable是一个标记接口,实现该接口,不需要重写任何方法
-
对象序列化介绍
- 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
- 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息
- 字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
- 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
-
对象序列化流: ObjectOutputStream
- 将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
-
构造方法
方法名 | 说明 |
---|---|
ObjectOutputStream(OutputStream out) | 创建一个写入指定的OutputStream的ObjectOutputStream |
- 序列化对象的方法
方法名 | 说明 |
---|---|
void writeObject(Object obj) | 将指定的对象写入ObjectOutputStream |
- 示例代码
学生类
测试类
public class Student implements Serializable {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws IOException {
//ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
// 创建对象
Student s = new Student("佟丽娅", 30);
// void writeObject(Object obj):将指定的对象写入ObjectOutputStream
oos.writeObject(s);
// 释放资源
oos.close();
}
}
对象反序列化流
-
对象反序列化流: ObjectInputStream
- ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
-
构造方法
方法名 | 说明 |
---|---|
ObjectInputStream(InputStream in) | 创建从指定的InputStream读取的ObjectInputStream |
- 反序列化对象的方法
方法名 | 说明 |
---|---|
Object readObject() | 从ObjectInputStream读取一个对象 |
- 示例代码
public class ObjectInputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
//Object readObject():从ObjectInputStream读取一个对象
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}
}
serialVersionUID&transient
-
serialVersionUID
-
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
- 会出问题,会抛出InvalidClassException异常
-
如果出问题了,如何解决呢?
- 重新序列化
-
给对象所属的类加一个serialVersionUID
- private static final long serialVersionUID = 42L;
-
-
transient
- 如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
- 给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
- 如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
-
示例代码
学生类
测试类
public class Student implements Serializable {
//private static final long serialVersionUID = 42L;
private String name;
//private int age;
private transient int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ObjectStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
write();
read();
}
//序列化
private static void write() throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
Student s = new Student("佟丽娅", 20);
oos.writeObject(s);
oos.close();
}
//反序列化
private static void read() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}
}
对象操作流练习
-
案例需求
创建多个学生类对象写到文件中,再次读取到内存中 -
实现步骤
-
- 创建序列化流对象
- 创建多个学生对象
- 将学生对象添加到集合中
- 将集合对象序列化到文件中
- 创建反序列化流对象
- 将文件中的对象数据,读取到内存中
-
代码实现
学生类
测试类
public class Student implements Serializable{
private static final long serialVersionUID = 2L;
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Demo03 {
/**
* read():
* 读取到文件末尾返回值是 -1
* readLine():
* 读取到文件的末尾返回值 null
* readObject():
* 读取到文件的末尾 直接抛出异常
* 如果要序列化的对象有多个,不建议直接将多个对象序列化到文件中,因为反序列化时容易出异常
* 建议: 将要序列化的多个对象存储到集合中,然后将集合序列化到文件中
*/
public static void main(String[] args) throws Exception {
/*// 序列化
//1.创建序列化流对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myCode\\oos.txt"));
ArrayList<Student> arrayList = new ArrayList<>();
//2.创建多个学生对象
Student s = new Student("佟丽娅",30);
Student s01 = new Student("佟丽娅",30);
//3.将学生对象添加到集合中
arrayList.add(s);
arrayList.add(s01);
//4.将集合对象序列化到文件中
oos.writeObject(arrayList);
oos.close();*/
// 反序列化
//5.创建反序列化流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myCode\\oos.txt"));
//6.将文件中的对象数据,读取到内存中
Object obj = ois.readObject();
ArrayList<Student> arrayList = (ArrayList<Student>)obj;
ois.close();
for (Student s : arrayList) {
System.out.println(s.getName() + "," + s.getAge());
}
}
}
打印流
Properties集合
Properties作为Map集合的使用
-
Properties介绍
- 不属于io流体系,
- 是一个Map体系的集合类
- Properties可以保存到流中或从流中加载
- 属性列表中的每个键及其对应的值都是一个字符串
-
Properties基本使用
package cc;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo01 {
public static void main(String[] args) {
//创建集合对象
// Properties<String,String> prop = new Properties<String,String>(); //错误
Properties prop = new Properties();
//存储元素
prop.put("itheima001", "佟丽娅");
prop.put("itheima002", "赵丽颖");
prop.put("itheima003", "刘诗诗");
//遍历集合
Set<Object> keySet = prop.keySet();
for (Object key : keySet) {
Object value = prop.get(key);
System.out.println(key + "," + value);
}
}
}
Properties作为Map集合的特有方法
- 特有方法
方法名 | 说明 |
---|---|
Object setProperty(String key, String value) | 设置集合的键和值,都是String类型,底层调用 Hashtable方法 put |
String getProperty(String key) | 使用此属性列表中指定的键搜索属性 |
Set stringPropertyNames() | 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串 |
- 示例代码
package cc;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo02 {
public static void main(String[] args) {
//创建集合对象
Properties prop = new Properties();
//Object setProperty(String key, String value):设置集合的键和值,都是String类型
prop.setProperty("itheima001", "佟丽娅");
prop.setProperty("itheima002", "赵丽颖");
prop.setProperty("itheima003", "刘诗诗");
//String getProperty(String key):使用此属性列表中指定的键搜索属性
// System.out.println(prop.getProperty("itheima001"));
// System.out.println(prop.getProperty("itheima0011"));
// System.out.println(prop);
//Set<String> stringPropertyNames():从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
Set<String> names = prop.stringPropertyNames();
for (String key : names) {
// System.out.println(key);
String value = prop.getProperty(key);
System.out.println(key + "," + value);
}
}
}
Properties和IO流相结合的方法
- 和IO流结合的方法
方法名 | 说明 |
---|---|
void load(Reader reader) | 从输入字符流读取属性列表(键和元素对) |
void store(Writer writer, String comments) | 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流 |
- 示例代码
package cc;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
public class PropertiesDemo03 {
public static void main(String[] args) throws IOException {
//把集合中的数据保存到文件
myStore();
//把文件中的数据加载到集合
myLoad();
}
private static void myLoad() throws IOException {
Properties prop = new Properties();
//void load(Reader reader):
FileReader fr = new FileReader("fw.txt");
prop.load(fr);
fr.close();
System.out.println(prop);
}
private static void myStore() throws IOException {
Properties prop = new Properties();
prop.setProperty("itheima001", "佟丽娅");
prop.setProperty("itheima002", "赵丽颖");
prop.setProperty("itheima003", "刘诗诗");
//void store(Writer writer, String comments):
FileWriter fw = new FileWriter("fw.txt");
prop.store(fw, null);
fw.close();
}
}
Properties集合练习
-
案例需求
在Properties文件中手动写上姓名和年龄,读取到集合中,将该数据封装成学生对象,写到本地文件 -
实现步骤
-
- 创建Properties集合,将本地文件中的数据加载到集合中
- 获取集合中的键值对数据,封装到学生对象中
- 创建序列化流对象,将学生对象序列化到本地文件中
-
代码实现
学生类
测试类
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) throws IOException {
//1.创建Properties集合,将本地文件中的数据加载到集合中
Properties prop = new Properties();
FileReader fr = new FileReader("prop.properties");
prop.load(fr);
fr.close();
//2.获取集合中的键值对数据,封装到学生对象中
String name = prop.getProperty("name");
int age = Integer.parseInt(prop.getProperty("age"));
Student s = new Student(name,age);
//3.创建序列化流对象,将学生对象序列化到本地文件中
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
oos.writeObject(s);
oos.close();
}
}