IO流
IO流
第一章 IO的概述
1.1 什么是IO
当你的电脑插上U盘时可以传输数据,我们把这种传输可以看做是一种数据的流动,按照流动的方向,以内存为基准分为 【输入input】和【输出output】即流向内存是输入流,流出内存是输出流
Java中的 I/O流操作主要是是使用 【Java.io】包下的内容进行输入、输出的操作,输入也叫做读取数据,输出也叫做写出数据
1.2 IO 的分类
根据数据的流向分为【输入流】和【输出流】
- 输入流:把数据从其他设备读取到内存中的流
- 输出流: 把数据从内存中写出到其他设备上的流
根据数据的类型分为【字节流】和【字符流】
- 字节流: 以字节为单位 读写数据的流
- 字符流:以字符为单位 读写数据的流
1.3 顶级的父类
| 输入流 | 输出流 | |
|---|---|---|
| 字节流 | 字节输入流 InputStream |
字节输出流 OutputStream |
| 字符流 | 字符输入流 Reader |
字符输出流 Writer |
第二章 字节流
2.1 字节输出流【OutputStream】 写入信息
Java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写到目的地,他定义了字节输出流的基本共性功能方法
-
【public void close()】 关闭输出流并释放与此流相关的任何系统资源
-
【public void flush()】 刷新此输出流并强制任何缓冲的输出字节被写出
-
【public void write(byte [] b)】 将b.length 字节从指定的字节数组写入此输出流
-
【public void write(byte[] b, int off ,int len)】 从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
int off: 表示开始索引
int len :表示 写几个字节
-
【public abstract void write(int b)】 将指定的字节输出流
小贴士:
close 方法当完成流的操作时,必须调用此方法,释放系统资源
【write(byte [] b)】方法和【write(byte[] b, int off ,int len)】方法可以一次写多个字节
如果写的第一个字节是正数(0-127)那么显示的是时候会查询ASCII表
如果写的第一个字节是负数,那么第一个字节会和第二个字节,两个字节组成一个中文显示,查询默认码表(GBK)
2.2 文件字节输出流【FileOutputStream】
【Java.io.FileOutputStream】继承自OutputStream
作用:把内存中的数据写入到硬盘的文件中
构造方法:
- 【public FileOutputStream(String name)】 创建一个向具有指定名称的文件中写入数据的输出文件流
- 【public FileOutputStream(File file)】 创建一个指定File对象的表示文件中的写入数据的文件是输出流
参数:
String name:目的地个文件的路径
File file: 目的地是一个文件
构造方法的作用
- 创建一个FileOutputStream的对象
- 会根据构造方法中传递的文件/或者文件路径,创建一个空的文件
- 会把FileOutputStream指向创建好的文件
代码示例:
package com.io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* FileOutputStream 文件字节输出流的使用一次写多个字节
*- 【**public void write(byte [] b)**】 将b.length 字节从指定的字节数组写入此输出流
* - 【**public void write(byte[] b, int off ,int len)**】从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
*/
public class OutputStreamDome02 {
public static void main(String[] args) throws IOException {
// show02();
show03();
}
/**
* 一次写入一个字节
* public void write(int b) throws IOException
*/
public static void show01() throws IOException{
FileOutputStream fos=new FileOutputStream("d:\\1.txt");
fos.write(123);
fos.close();
}
/**
* 一次写入多个字节
* public void write(byte b[]) throws IOException
*/
public static void show02() throws IOException{
FileOutputStream fos=new FileOutputStream("d:\\1.txt");
byte[] bytes=new byte[]{66,67,68,69,70};
fos.write(bytes);
fos.close();
}
/**
* 一次写入多个字节
* public void write(byte b[], int off, int len) throws IOException
*/
public static void show03() throws IOException{
FileOutputStream fos=new FileOutputStream("d:\\2.txt");
byte[] bytes=new byte[]{66,67,68,69,70};
fos.write(bytes,1,2); //写入 CD
fos.close();
}
}
2.3 字节输入流【InputStream】读取信息
java.io.InputStream 抽象类表示字节输入流的所有类的超类,可以读取字节信息到 内存中,他定义了字节输入流的基本共性功能方法
- 【public void close()】 关闭此输入流并释放,与此相关的任何系统资源
- 【public abstract int read()】 从输入流读取数据的下一个字节
- 【pubic int read(byte[] b)】从输入流中读取一些字节数,并将它们存储到字节数组中
小贴士
【close】方法当完成流的操作时,必须调用此方法,释放系统资源
2.4 FileInputStream类
java.io.FileInputStream 类是文件输入流,从文件中读取字节 继承自InputStream类
构造方法:
- 【public FileInputStream(File file)】 通过打开与实际文件的连接来创建一个FileInputStream,改文件由系统中的File对象 file 命名
- 【public FileInputStream(String name)】 通过打开与实际文件的连接来创建一个FileInputStream,改文件由系统中的路径名 name 命名
【String】类的构造方法:
- 【String(byte[] bytes)】把字节数组转换为字符串
- 【String(byte[] bytes, int offset, int length)】 把字节数组的一部分转换为字符串, offset表示数组的开始索引,length表示转换的字节个数
示例代码:
package com.io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* FileInputStream 文件字节输入流的使用
*
*/
public class InputStreamDome01 {
public static void main(String[] args) throws IOException {
// show01();
show02();
}
/**
* 一次读取两个字节的代码示例
*
* @throws IOException
*/
public static void show01()throws IOException {
FileInputStream fis=new FileInputStream("a.txt");
byte[] bytes=new byte[2];
int read = fis.read(bytes);
System.out.println(read); //输出2
System.out.println(new String(bytes)); //输出aa
}
/**
* 一次读取多个字节的代码示例
* @throws IOException
*/
public static void show02()throws IOException {
FileInputStream fis=new FileInputStream("a.txt");
byte[] bytes=new byte[1024];
int len=0;
while((len=fis.read(bytes))!=-1){
//使用String(byte[] bytes, int offset, int length)构造方法转换
System.out.println(new String(bytes,0,len)); //输出aaaaaaaabbbbbcccccccc
}
}
}
练习 文件复制
package com.io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 文件复制
* 1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
* 2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
* 3.使用字节输入流对象的read方法读取文件
* 4. 使用字节输出流的方法write方法把读取到的文件内容写入到目的地的文件中
* 5.关闭连接释放资源
*/
public class FileCopy {
public static void main(String[] args) throws IOException {
fileCopy();
}
public static void fileCopy() throws IOException {
//1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream inputStream=new FileInputStream("D:\\Typora\\java文件\\Java基础\\File和IO流\\IO流.assets\\1637256557651.png");
//2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream outputStream=new FileOutputStream("e:\\1637256557651.png");
//3.使用字节输入流对象的read方法读取文件
// int len=0;
// while((len = inputStream.read())!=-1){
// //4. 使用字节输出流的方法write方法把读取到的文件内容写入到目的地的文件中
// outputStream.write(len);
// }
//使用数组缓冲读取多个字节,写入多个字节
byte[] bytes=new byte[1024];
//使用字节输入流对象的read方法读取文件
int len =0;
while((len = inputStream.read(bytes))!=-1){
outputStream.write(bytes,0,len);
}
//5.关闭连接释放资源(先关写的流,再关读的流,因为写完了肯定读完了)
outputStream.close();
inputStream.close();
}
}
第三章 字符流
由于字节流读取中文时会出现乱码的问题,所以引入了字符流
3.1 字符输入流【Reader】
java.io.Reader 抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中,定义了字符输入流的基本共性功能的方法
- 【public void close()】 关闭此流并释放与此流相关的任何系统资源
- 【public int read()】 从输入流读取一个字符
- 【public int reader(char[] cbuf)】 从输入流中读取多个字符,并将它们存储到字符数组中
3.2 FileReader类
【java.io.FileReader】继承自 InputStreamReader ,【InputStreamReader】类继承自 Reader
【FileReader extends InputStreamReader】 , 【InputStreamReader extends Reader】
构造方法
- 【FileReader (File file)】 创建一个新的FileReader对象,给定要读取的file对象
- 【FileReader(String filename)】 创建一个新的FileReader, 给定要读取的文件的名称
当创建一个流对象时,必须传入一个文件路径,类似于FileInputStream
代码示例
package com.io.reader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Dome01 {
public static void main(String[] args) throws IOException {
show02();
}
/**
* 读取单个字节
* public int read()方法的使用
*/
public static void show01() throws IOException {
//创建一个FileReader对象,构造方法中的绑定读取的数据源
FileReader fileReader=new FileReader("a.txt");
int len=0;
while((len = fileReader.read())!=-1){
System.out.println((char)len);
}
fileReader.close();
}
/**
* 读取多个字节
* public int reader(char[] cbuf)方法的使用
*/
public static void show02() throws IOException {
//创建一个FileReader对象,构造方法中的绑定读取的数据源
FileReader fileReader=new FileReader("a.txt");
char[] chars=new char[1024];
int len=0;
while((len = fileReader.read(chars))!=-1){
//输出 aaaaaaaabbbbbcccccccc
System.out.println(new String(chars,0,len));
}
fileReader.close();
}
}
3.3 字符输出流(Writer)
【java.io.Writer】抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地,他定义了字符输出流的基本的共性功能方法
- 【public void write(int c)】 写入单个字符
- 【public void write(char[] chars)】写入字符数组
- 【public void write(char[] chars, int off, int len )】写入字符数组的某一部分,off表示数组开始的位置索引,len表示写入的字符个数
- 【public void write(String str)】 写入字符串
- 【public void write(String str , int off,int len)】 写入字符串的某一部分,off表示字符串开始的索引位置,len表示写入的字符个数
- 【public void flush()】 刷新该流的缓冲
- 【public void close()】 关闭此流,但是需要先刷新它
3.4 FileWriter 类
【java.io.FileWriter】 extends OutputStreamWriter extends Writer
构造方法
- 【FileWriter(File file)】 根据指定的File对象构造一个FileWriter对象
- 【FileWriter(String fileName)】 根据给定的文件名构造一个FileWriter对象
小贴士
1. 虽然参数为int类型的四个字节,但是只会保留一个字符的信息写出
2. 未调用close方法,数据只是保存到了缓冲区,并未写出到文件中
示例代码
package com.io.readerandwriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* FileWriter对象的使用
*/
public class Dome01Writer {
public static void main(String[] args) throws IOException {
show01();
}
/**
*写入单个字符
* public int read()方法的使用
*/
public static void show01() throws IOException {
//创建一个FFileWriter对象,构造方法中的绑定写入数据的目的地
FileWriter fileWriter=new FileWriter("a.txt");
fileWriter.write(97);
fileWriter.flush();
fileWriter.close();
}
// /**
// * 读取多个字符
// * public int reader(char[] cbuf)方法的使用
// */
// public static void show02() throws IOException {
// //创建一个FileReader对象,构造方法中的绑定读取的数据源
// FileReader fileReader=new FileReader("a.txt");
// char[] chars=new char[1024];
// int len=0;
// while((len = fileReader.read(chars))!=-1){
// //输出 aaaaaaaabbbbbcccccccc
// System.out.println(new String(chars,0,len));
// }
// fileReader.close();
// }
}
关闭和刷新
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中,但是关闭流对象,是无法继续写出数据的,如果我们既想写出数据又想使用流就需要flush方法了
- flush 刷新缓冲区,流对象可以继续使用
- close 先刷新缓冲区,然后释放资源,流对象不可以再被使用
续写和换行
1. 续写
构造方法
- 【FileWriter(String fileName,boolean append)】
- 【FileWriter(File file, boolean append)】
参数:
String fileName ,File file:写入数据的目的地
**boolean append ** 续写开关,true不会创建新的文件覆盖原文件,可以续写,false 创建新的文件覆盖原文件
2. 换行
换行符号: 【Windows \r\n】、 【Linux /n】、【 mac /r】
第四章 io流中的异常处理
JDK9和JDK7中的异常处理新特性
代码示例:
package com.ioexception;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 文件复制
* 1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
* 2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
* 3.使用字节输入流对象的read方法读取文件
* 4. 使用字节输出流的方法write方法把读取到的文件内容写入到目的地的文件中
* 5.关闭连接释放资源
*/
public class FileCopyException {
public static void main(String[] args) {
fileCopy();
}
/**
* jdk7新特性异常处理
*/
public static void fileCopy() {
try( //1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream inputStream=new FileInputStream("D:\\Typora\\java文件\\Java基础\\File和IO流\\IO流.assets\\1637256557651.png");
//2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream outputStream=new FileOutputStream("e:\\1637256557651.png");
){
//使用数组缓冲读取多个字节,写入多个字节
byte[] bytes=new byte[1024];
//使用字节输入流对象的read方法读取文件
int len =0;
while((len = inputStream.read(bytes))!=-1){
outputStream.write(bytes,0,len);
}
}catch(IOException e){
e.printStackTrace();
}
}
/**
* jdk9的io流异常处理
*/
public static void show02() {
//1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream inputStream=new FileInputStream("D:\\Typora\\java文件\\Java基础\\File和IO流\\IO流.assets\\1637256557651.png");
//2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream outputStream=new FileOutputStream("e:\\1637256557651.png");
try(inputStream;outputStream){
//使用数组缓冲读取多个字节,写入多个字节
byte[] bytes=new byte[1024];
//使用字节输入流对象的read方法读取文件
int len =0;
while((len = inputStream.read(bytes))!=-1){
outputStream.write(bytes,0,len);
}
}catch(IOException e){
e.printStackTrace();
}
}
}
第五章 属性集【Properties】
介绍
java.util.Properties 继承与Hashtable ,表示一个持久的属性集,它使用键值结构存储数据,每个键及其对应的值都是一个字符串,该类被许多java类使用,比如获取系统属性,System.getProperties方法就是获取一个Properties对象。
properties集合是唯一一个和IO流结合的集合,他是一个双列集合,key和value都是字符串
可以使用集合中的方法store ,把集合中的临时数据,持久化写入到硬盘中存储
可以使用集合中的方法load ,把硬盘中保存的文件(键值对),读取到集合中使用
构造方法
- 【public Properties()】 创建一个空的属性集合
基本的存储方法
- 【public Object setProperties(String key,String value)】 保存一对属性
- 【public String getProperties(String key)】 根据键获取此列表对应的属性值
- 【public Set
stringPropertyNames() 】 所有键的名称的集合
5.1 使用Properties集合存储数据
代码示例
package com.properties;
import java.util.Properties;
import java.util.Set;
/**
* Properties集合的使用
*/
public class Dome01Properties {
public static void main(String[] args) {
show01();
}
/**
* 【**public Object setProperties(String key,String value)**】 保存一对属性
* 【**public String getProperties(String key)**】 根据键获取此列表对应的属性值
* 【**public Set<String> stringPropertyNames()**】 所有键的名称的集合
* 方法的使用
*/
private static void show01() {
//创建Properties对象
Properties properties=new Properties();
properties.setProperty("赵丽颖","168");
properties.setProperty("迪丽热巴","170");
properties.setProperty("古力娜扎","190");
//使用stringPropertyNames方法把properties中的键取出,存储到set集合中
Set<String> strings = properties.stringPropertyNames();
//遍历set集合,取出Properties中的属性
for (String key : strings) {
System.out.println(properties.getProperty(key));
}
}
}
5.2 Properties集合中的方法store
使用方法【void store(Writer writer , String comments)】字符输流方式
代码示例
package com.properties;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
/**
* Properties集合中的方法store使用
*/
public class Dome02Properties {
public static void main(String[] args) throws IOException {
show01();
}
/**
* 可以使用集合中的方法store ,把集合中的临时数据,持久化写入到硬盘中存储
* void store(OutputStream out,String comments)
* void store(Writer writer , String comments)
* 参数:
* OutputStream out:字节输出流,不能写入中文
* Writer writer:字符输出流,可以写中文
* String comments:注释,用来解释说明保存的文件是来做什么的,
* 不能使用中文,会产生乱码,默认使用的是Unicode编码,一般使用“”空字符串
*
* 方法的使用
*/
private static void show01() throws IOException {
//创建Properties对象
Properties properties=new Properties();
properties.setProperty("赵丽颖","168");
properties.setProperty("迪丽热巴","170");
properties.setProperty("古力娜扎","190");
//创建字符输出流对象,构造方法中绑定要输入的目的地
FileWriter writer=new FileWriter("a.txt");
//使用Properties集合中的方法store 把集合中的临时数据,持久化写入到硬盘中存储
properties.store(writer,"save data");
writer.close();
}
}
运行结果

使用【void store(OutputStream out,String comments)】字节输出流方式
代码示例
package com.properties;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
/**
* Properties集合中的方法store使用
*/
public class Dome03Properties {
public static void main(String[] args) throws IOException {
show01();
}
/**
* 可以使用集合中的方法store ,把集合中的临时数据,持久化写入到硬盘中存储
* void store(OutputStream out,String comments)
* void store(Writer writer , String comments)
* 参数:
* OutputStream out:字节输出流,不能写入中文
* Writer writer:字符输出流,可以写中文
* String comments:注释,用来解释说明保存的文件是来做什么的,
* 不能使用中文,会产生乱码,默认使用的是Unicode编码,一般使用“”空字符串
*
* 方法的使用
*/
private static void show01() throws IOException {
//创建Properties对象
Properties properties=new Properties();
properties.setProperty("赵丽颖","168");
properties.setProperty("迪丽热巴","170");
properties.setProperty("古力娜扎","190");
//创建字节输出流对象,构造方法中绑定要输入的目的地
FileOutputStream fileOutputStream=new FileOutputStream("a.txt");
//使用Properties集合中的方法store 把集合中的临时数据,持久化写入到硬盘中存储
properties.store(fileOutputStream,"save data");
fileOutputStream.close();
}
}
运行结果

5.3 Properties集合中的方法 load
使用【 void load(Reader reader)】字符流方式
代码示例
package com.properties;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
/**
* Properties集合中的方法 load 使用
*/
public class Dome04Properties {
public static void main(String[] args) throws IOException {
show01();
}
/**
* 可以使用集合中的方法 load ,把集合中的临时数据,持久化写入到硬盘中存储
* void load(InputStream inStream)
* void load(Reader reader)
* 参数:
* InputStream inStream:字节输入流,不能读取含有中文的键值对
* Reader reader:字符输入流,可以读取含有中文的键值对
* 注意事项:
* 1. 存储键值对文件中,键与值默认的连接符号可以使用=,空格(其他符号),
* 2. 存储键值对文件中,可以使用#注释,被注释的键值对不能被读取
* 3. 存储键值对文件中,键与值默认都是字符串,不用加引号
* 方法的使用
*/
private static void show01() throws IOException {
//创建Properties对象
Properties properties=new Properties();
//使用Properties中的 load 方法读取文件
properties.load(new FileReader("a.txt"));
//使用stringPropertyNames方法把properties中的键取出,存储到set集合中
Set<String> strings = properties.stringPropertyNames();
//遍历set集合,取出Properties中的属性
for (String key : strings) {
System.out.println(key+"="+properties.getProperty(key));
}
}
}
运行结果

使用【void load(InputStream inStream)】字节流方式
代码示例
package com.properties;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
/**
* Properties集合中的方法 load 使用
*/
public class Dome05Properties {
public static void main(String[] args) throws IOException {
show01();
}
/**
* 可以使用集合中的方法 load ,把集合中的临时数据,持久化写入到硬盘中存储
* void load(InputStream inStream)
* void load(Reader reader)
* 参数:
* InputStream inStream:字节输入流,不能读取含有中文的键值对
* Reader reader:字符输入流,可以读取含有中文的键值对
* 注意事项:
* 1. 存储键值对文件中,键与值默认的连接符号可以使用=,空格(其他符号),
* 2. 存储键值对文件中,可以使用#注释,被注释的键值对不能被读取
* 3. 存储键值对文件中,键与值默认都是字符串,不用加引号
* 方法的使用
*/
private static void show01() throws IOException {
//创建Properties对象
Properties properties=new Properties();
//使用Properties中的 load 方法读取文件
properties.load(new FileInputStream("a.txt"));
//使用stringPropertyNames方法把properties中的键取出,存储到set集合中
Set<String> strings = properties.stringPropertyNames();
//遍历set集合,取出Properties中的属性
for (String key : strings) {
System.out.println(key+"="+properties.getProperty(key));
}
}
}
运行结果

第六章 缓冲流
6.1 概述
缓冲流也叫高效流,是对四个基本的流的增强,所以也是四个流,按照数据类型分类
- 字节缓冲流:BufferedInputStream, BufferedOutputStream
- 字符缓冲流: BufferedReader, BufferedWriter
原理:
创建流对象时,会创建一个内置默认大小的缓冲区数组,通过缓冲区读写,减少系统的IO次数,从而提高读写的效率
6.2 字节缓冲流
构造方法
- 【public BufferedInputStream(InputStream in)】 创建一个新的缓冲输入流
- 【public BufferedOutputStream(OutputStream out)】 创建一个新的缓冲输出流
6.2.1 字节缓冲输出流【BufferedOutputStream】
代码示例
package com.iobuffered;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 字节缓冲输出流使用案例
*/
public class BufferedOutputStreamDome01 {
public static void main(String[] args) throws IOException {
show01();
}
public static void show01() throws IOException {
//1.创建一个 FileOutputStream 对象
FileOutputStream fileOutputStream=new FileOutputStream("a.txt");
// 2. 创建 BufferedOutputStream 对象 构造方法中传递 FileOutputStream 对象
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(fileOutputStream);
// 3.使用 BufferedOutputStream 对象中的 write 方法,将数据写入到文件中
bufferedOutputStream.write("我把数据写入到了缓冲区中".getBytes());
//4. 调用 BufferedOutputStream 对象的 flush 方法
bufferedOutputStream.flush();
//5. 释放资源
bufferedOutputStream.close();
}
}
运行结果

6.2.2 字节缓冲输入流【BufferedInputStream】
代码示例
package com.iobuffered;
import java.io.*;
/**
* 字节缓冲输入流
*/
public class BufferedInputStreamDome01 {
public static void main(String[] args) throws IOException {
show01();
}
/**
* 使用 int read() 方法
* @throws IOException
*/
public static void show01() throws IOException {
//1.创建一个 FileInputStream 对象
FileInputStream fileInputStream=new FileInputStream("a.txt");
// 2. 创建 BufferedInputStream 对象 构造方法中传递 FileOutputStream 对象
BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream);
// 3.使用 BufferedInputStream 对象中的 read 方法读取文件数据
int len=0;
while((len = bufferedInputStream.read())!=-1){
System.out.println(len);
}
//4. 释放资源
bufferedInputStream.close();
}
/**
* 使用 int read(byte[] bytes) 方法
* @throws IOException
*/
public static void show02() throws IOException {
//1.创建一个 FileInputStream 对象
FileInputStream fileInputStream=new FileInputStream("a.txt");
// 2. 创建 BufferedInputStream 对象 构造方法中传递 FileOutputStream 对象
BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream);
// 3.使用 BufferedInputStream 对象中的 read 方法读取文件数据
byte[] bytes=new byte[1024];
int len=0;
while((len = bufferedInputStream.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
//4. 释放资源
bufferedInputStream.close();
}
}
a.txt文件

运行结果

6.3 字符缓冲流
- 【public BufferedReader(Reader reader)】 创建一个新的缓冲输入流
- 【public BufferedWriter(Writer writer)】 创建一个新缓冲输出流
构造举例代码如下:
//创建一个新的缓冲输入流
BufferedReader br=new BufferedReader(new FileReader("a.txt"));
//创建一个新缓冲输出流
BufferedWriter bw=new BufferedWriter(new FileWriter("a.txt"));
6.3.1 字符缓冲输出流 【BufferedWriter】
代码示例
package com.iobuffered;
import java.io.*;
public class BufferedWriterDome01 {
public static void main(String[] args) throws IOException {
show01();
}
private static void show01() throws IOException {
//创建一个新的缓冲输入流
// BufferedReader br=new BufferedReader(new FileReader("a.txt"));
//创建一个新缓冲输出流
BufferedWriter bw=new BufferedWriter(new FileWriter("a.txt"));
//使用 BufferedWriter 对象中的 write 方法,将数据写入到文件中
bw.write("使用字符缓冲输出流");
bw.close();
}
}
6.3.2 字符缓冲输入流 【BufferedReader】
代码示例
package com.iobuffered;
import java.io.*;
public class BufferedReaderDome01 {
public static void main(String[] args) throws IOException {
show01();
}
/**
* 使用 BufferedReader 对象中的额readLine 方法每次读取一行数据
* @throws IOException
*/
private static void show01() throws IOException {
//创建一个新的缓冲输入流
BufferedReader br=new BufferedReader(new FileReader("a.txt"));
//使用 BufferedReader 对象中的额readLine 方法每次读取一行数据
String line;
while((line = br.readLine()) != null){
System.out.println(line);
}
br.close();
}
}
a.txt文本

运行结果

第七章 转换流
7.1 字符编码和字符集




7.2 编码引出的问题

7.3 InputStreamReader类(读)

代码示例
package com.ioforconversion;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* InputStreamReader 缓冲流的使用
*/
public class DomeInputStreamReader01 {
public static void main(String[] args) throws IOException {
show01();
}
private static void show01() throws IOException {
//创建一个 OutputStreamWriter 对象
InputStreamReader inputStreamReader =new InputStreamReader(new FileInputStream("a.txt"),"utf-8" );
//使用 InputStreamReader 对象中的方法 read 将字符转为字节存储到缓存区中
int len =0;
while((len = inputStreamReader.read())!=-1){
System.out.println((char)len);
}
//关闭资源
inputStreamReader.close();
}
}
7.4 OutputStreamWriter类(写)

代码示例
package com.ioforconversion;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/**
* OutputStreamWriter 缓冲流的使用
*/
public class DomeOutputStreamWriter01 {
public static void main(String[] args) throws IOException {
show01();
}
private static void show01() throws IOException {
//创建一个 OutputStreamWriter 对象
OutputStreamWriter outputStreamWriter=new OutputStreamWriter(new FileOutputStream("a.txt"),"utf-8" );
//使用 OutputStreamWriter 对象中的方法write 将字符转为字节存储到缓存区中
outputStreamWriter.write("你好");
//刷新
outputStreamWriter.flush();
//关闭资源
outputStreamWriter.close();
}
}
第八章 序列化和序列化概述
8.1 概述

8.2 ObjectOutputStream类
java.io.ObjectOutputStream 类 将java对象的原始数据写出到文件中,实现对象的持久存储
构造方法
- 【**public ObjectOutputStream(OutputStream out) **】创建一个指定 **OutputStream ** 的 ObjectOutputStream
代码示例
FileOutputStream fileOut=new FileOutputStream("a.txt");
ObjectOutputStream out=new ObjectOutputStream(fileOut);
序列化操作
一个对象想要序列化必须满足两个条件
- 该类必须实现 【java.io.Serializable】接口,Serializable 是一个标记接口,不实现此接口的类将不会使任何状态序列化或者反序列化,会抛出 NotSerializableException
- 该类的所有属性必须是可序列化的,如果有一个属性不需要序列化,则该属性必须注明是瞬态的,使用 transient 关键字修饰
代码示例
package com.ioforserialization;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
* ObjectOutputStream 序列化流的操作
*/
public class ObjectOutputStreamDome01 {
public static void main(String[] args) throws IOException {
show01();
}
private static void show01() throws IOException {
//创建 ObjectOutputStream 对象 构造方法中传递字节输出流
ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream("person.txt"));
//使用 ObjectOutputStream 对象中的writeObject 方法,把对象写到文件中
objectOutputStream.writeObject(new Person("小程",19));
//释放资源
objectOutputStream.close();
}
}
被序列化的类:
package com.ioforserialization;
import java.io.Serializable;
public class Person implements Serializable {
private String name;
private int age;
public Person(){}
public Person(String name,int age){
this.age=age;
this.name=name;
}
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 "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
运行后person.txt文件的内容
�� sr com.ioforserialization.Person�0B[�d�G I ageL namet Ljava/lang/String;xp t 小程
8.3 ObjectInputStream 类
ObjectInputStream 反序列化流,将之前使用的 ObjectOutputStream序列化的原始数据恢复到对象
反序列化的前提
- 类必须实现接口 Serializable
- 必须存在类对应的class文件
构造方法
- 【**public ObjectInputStream (InputStream in) **】创建指定InputStream 的 ObjectInputStream
反序列化操作
如果能够找到一个对象的class文件,我们就可以进行反序列化操作,调用 **ObjectInputStream ** 读取对象的方法
- 【public final Object readObject()】 读取一个对象,该方法会抛出 ClassNotFoundException 异常
代码示例
package com.ioforserialization;
import java.io.*;
/**
* ObjectInputStream 反序列化流的操作
*/
public class ObjectInputStreamDome01 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
show01();
}
private static void show01() throws IOException, ClassNotFoundException {
//创建 ObjectInputStream 对象 构造方法中传递字节输出流
ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("person.txt"));
//使用 ObjectInputStream 对象中的readObject 方法,读取保存对象的文件
Object o = objectInputStream.readObject();
//释放资源
objectInputStream.close();
//打印读取出来的对象
System.out.println(o);//Person{name='小程', age=19}
Person person=(Person)o;
System.out.println("姓名----"+person.getName()+", 年龄---"+person.getAge());
}
}
注意事项:
static静态关键字,优先非静态加载到内存中,静态优先于对象加载到内存中
被static修饰的成员不能被序列化,序列化的都是对象
transient 关键字,是个瞬态关键字,被它修饰的成员不能被序列化。
8.4 反序列化操作时出现的异常解决
当JVM反序列化时,能找到class文件,但是class文件在序列化之后发生了改变,那么反序列化操作也会失败,抛出一个 InvalidClassException 异常,发生这个异常的原因
- 该类的序列版本号与从流中读取的类的描述版本号不匹配
- 该类包含未知数据类型
- 该类没有可访问的无参构造方法
Serializable 接口给需要序列化的类提供了一个序列版本号,serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配
解决方案:在类中手动加入序列化版本号【 private static final long serialVersionUID=1l;】
代码示例:
package com.ioforserialization;
import java.io.Serializable;
public class Person implements Serializable {
//手动加入序列号版本
private static final long serialVersionUID=1l;
private String name;
private int age;
//添加新的属性,重新编译,仍然可以反序列化,该属性设为默认值
private String address;
public Person(){}
public Person(String name,int age){
this.age=age;
this.name=name;
}
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 String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
8.5 练习 序列化集合
Person类
package com.listserializable;
import java.io.Serializable;
public class Person implements Serializable {
//手动加入序列号版本
private static final long serialVersionUID=1l;
private String name;
private int age;
//添加新的属性,重新编译,仍然可以反序列化,该属性设为默认值
private String address;
public Person(){}
public Person(String name, int age){
this.age=age;
this.name=name;
}
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 String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
ListSerializable类
package com.listserializable;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* 序列化集合练习
*/
public class ListSerializable {
public static void main(String[] args) throws IOException, ClassNotFoundException {
show01();
}
private static void show01() throws IOException, ClassNotFoundException {
//定义一个集合
List<Person> list=new ArrayList<>();
list.add(new Person("小程",19));
list.add(new Person("小花",17));
list.add(new Person("小冬",15));
list.add(new Person("小江",20));
//创建一个序列化 ObjectOutputStream 对象
ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream("listperson.txt"));
//使用 ObjectOutputStream 对象中的writeObject 方法,把对象写到文件中
objectOutputStream.writeObject(list);
//创建一个反序列化 ObjectInputStream 对象 构造方法中传递字节输出流
ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("listperson.txt"));
//使用 ObjectInputStream 对象中的readObject 方法,读取保存对象的文件
List<Person> people = (List<Person>) objectInputStream.readObject();
//遍历集合
for (Person person : people) {
System.out.println(person);
}
//释放资源
objectInputStream.close();
objectOutputStream.close();
}
}
运行结果


浙公网安备 33010602011771号