JAVA高级特性——流
- 一、概念
- 二、分类
- (1)按方向分类
- 1、输入流
- 2、输出流
- (2)按内容分类
- 1、字节流
- 2、字符流
- (3)按功能分类
- 1、节点流
- 2、处理流
- (4)是否依赖网络
- 1、本地流(文件流)
- 2、网络流
- 三、文件流
- (1)目录
- (2)文件
- (3)文件流
- 1)字节文件流
- 2)字符文件流
- 3)缓冲流
- 4)序列化与反序列化
- 四、流的异常处理
- 一、try catch finally
- 二、JDK1.7之后
- 三、JDK1.9之后
一、概念
1、概念:是一组有序的数据序列(字节数组)
二、分类
(1)按方向分类
1、输入流
将硬盘中的数据读取到内存中。
(1)XxxInputStream
(2)XxxReader
2、输出流
将内存里的数据保存到硬盘中。
(1)XxxOutputStream
(2)XxxWriter
(2)按内容分类
1、字节流
- 一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一 样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底 层传输的始终为二进制数据。
(1)XxxInputStream
(2)XxxOutputStream
2、字符流
- 当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为 一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文 件。
(1)XxxReader
(2)XxxWriter
(3)按功能分类
1、节点流
- 直接面向数据源的流(基础流)
2、处理流
- 扩展了节点流在某些特性领域的操作
(4)是否依赖网络
1、本地流(文件流)
2、网络流
三、文件流
(1)目录
public class Test {
public static void main(String[] args) {
//-----------------目录
File dir = new File("C:/Users/Administrator/Desktop/中博学习/java"); //创建目录对象
boolean exists = dir.exists(); //判断目录是否存在
System.out.println(exists);
boolean isDir = dir.isDirectory(); //判断是否为目录
System.out.println(isDir);
boolean isFile = dir.isFile(); //判断是否为文件
System.out.println(isFile);
File dir = new File("copy/unload");
boolean mkdir = dir.mkdirs(); //创建所有不存在的的目录
System.out.println(mkdir)
//相对路径:项目的根路径
//绝对路径:从分区根目录开始的路径
}
}
(2)文件
public class Test {
public static void main(String[] args) {
//-----------------文件
File file = new File("C:/Users/Administrator/Desktop/中博学习/java/story.txt"); //创建文件对象
//判断文件是否存在
System.out.println(file.exists());
//判断是否为目录
System.out.println(file.isDirectory());
//判断是否为文件
System.out.println(file.isFile());
//获取父目录对象
System.out.println(file.getParentFile());
//获取父目录字符串
System.out.println(file.getParent());
//获取文件所在路径
System.out.println(file.getPath());
//获取文件名称
System.out.println(file.getName());
//获取文件实际的字节数
System.out.println(file.length());
//获取文件可存剩余字节数
System.out.println(file.getFreeSpace());
//创建一个文件,如果该工程的所有目录下没有该文件
File file = new File("test.txt");
if(!file.exists()){
if(file.createNewFile()){
System.out.println(file.getName()+"文件创建成功!");
System.out.println(file.getPath());
System.out.println(file.getAbsolutePath());
}else{
System.out.println(file.getName()+"文件创建失败")
}
}else{
System.out.println(file.getName()+"文件已存在");
}
}
}
(3)文件流
1)字节文件流
1、字节输入流:
/*
java.io.InputStream:字节输入流
此抽象类是表示字节输入流的所有类的超类
定义了所有子类共性的方法:
int read() 从输入流中读取数据的下一个字节
int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中
void close() 关闭此输入流并释放与该流关联的所有系统资源
java.io.FileInputStream extends InputStream
FileInputStream:文件字节输入流
作用:把硬文件中的数据,读取到内存中使用
构造方法:
FileInputStream(String name)
FileInputStream(File file)
参数:读取文件的数据源
String name:文件的路径
File file: 文件
构造方法的作用:
1、会创建一个FileInputStream对象
2、会把FileInputStream对象指定构造方法中要读取的文件
读取数据的原理:(硬盘---->内存)
java程序-->JVM-->OS-->OS读取数据的方法-->读取文件
字节输入流的使用步骤(重点):
1、创建FileInputStream对象,构造方法中绑定要读取的数据源
2、使用FileInputStream对象中的方法read,读取文件
3、释放资源
*/
public class Dmeo01InputStream {
public static void main(String[] args) throws IOException {
//1、创建FileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("files/a.txt");
//2、使用FileInputStream对象中的方法read,读取文件
//共性方法一:int read() 从输入流中读取数据的一个字节并返回,读取到文件的末尾返回-1
int len = fis.read();
System.out.println(len);
len = fis.read();
System.out.println(len);
len = fis.read();
System.out.println(len);
len = fis.read();
System.out.println(len);
len = fis.read();
System.out.println(len);
/*
发现以上读取文件是一个重复的过程,使用循环优化
不知道文件有多少字节,使用while循环
循环结束条件:读取到-1的时候结束
布尔表达式:-1!=(len=fis.read())
1、fis.read():读取一个字节
2、len = fis.read():把读取到的字节赋值给变量len
3、-1!=(len=fis.read());判断变量len是否不等于-1
int len =0;//记录读取到的字节
while(-1!=(len=fis.read())){
System.out.println(len);
}
*/
//共性方法二:int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中
byte[] bytes = new byte[1024];
int len = 0;
while(-1!=(len=fis.read(bytes))){
System.out.println(new String(bytes,0,5));
}
// 3、释放资源
fis.close();
}
}
2、字节输出流:
- 文件存储原理:
- 一次写入一个字节的方法写入:
/*
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开始输出到此输出流
public abstract void write(int b); 将指定的字节输出流
java.io.FileOutputStram extends OutputStream
FileOutputStream:文件字符输出流
作用:把内存中的数据写到硬盘的文件中
构造方法:
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流
FileOutputStream(File file) 创建一个向指定File对象表示的文件中写入数据的文件输出流
参数:写入数据的目的:
String name: 目的地是一个文件的路径
File file : 目的地是一个文件
构造方法的作用:
1、创建一FileOutputStream对象
2、会根据构造方法中传递的文件/文件路径,创建一个空文件
3、会把FileOutputStream对象指向创建好的文件
写入数据的原理(内存-》硬盘):
java程序-->JVM虚拟机-->OS(操作系统)-->OS调入写数据的方法-->把数据写入到文件中
字节输出流的使用步骤(重点)
1、创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
2、调用FileOutputStream对象中的方法write,把数据写到文件中
3、释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序效率)
*/
public class Demo01OutputStream {
public static void main(String[] args) throws IOException {
//1、创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
FileOutputStream fos = new FileOutputStream("files/a.txt");
// 2、调用FileOutputStream对象中的方法write,把数据写到文件中
fos.write(97);
// 3、释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序效率)
fos.close();
}
}
- 一次写入多个字节的方法写入:
/*
一次写多个字节的方法
public void write(byte[] b); 将b.length字节从指定的字节数组写入此输出流
public void write(byte[] b,int off, int len); 从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
*/
public class Demo02OutputStream {
public static void main(String[] args) throws IOException {
// 1、创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
FileOutputStream fos = new FileOutputStream(new File("files/b.txt"));
//2、调用FileOutputStream对象中的方法write,把数据写到文件中
//在文件中显示100,写几个字节?
fos.write(49);
fos.write(48);
fos.write(48);
/*
public void write(byte[] b); 将b.length字节从指定的字节数组写入此输出流
一次写多个字节:
如果写的第一个字节是正数(0~127),显示的时候会查询ASCII码表
如果写的第一个字节是负数,那么第一二个字节会组成一个中文显示,查询GBK
*/
byte[] bytes = {65,66,67,68,69}; //ABCDE
//byte[] bytes = {-65,-66,-67,68,69}; //烤紻E
fos.write(bytes);
/*
public void write(byte[] b,int off, int len);
从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
*/
fos.write(bytes,1,2); //BC
/*
写入字符串的方法:可以使用String类中的方法把字符串转化为字节数组
byte[] getBytes() 把字符串转化为字符数组
*/
byte[] bytes2 = "你好".getBytes();
System.out.println(Arrays.toString(bytes2)); //[-28, -67, -96, -27, -91, -67]
fos.write(bytes2);
// 3、释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序效率)
fos.close();
}
}
- 追加写/续写
/*
追加写/续写:使用两个参数的构造方法
FileOutputStream(String name,boolean append) 创建一个向具有指定name的文件中写入数据的输出文件流
FileOutputStream(File file,boolean append) 创建一个向指定file对象表示的文件中写入数据的文件输出流
参数:
String name,File file:写入数据的目的地
boolean append: 追加写开关
true:创建对象不会覆盖源文件,继续在文件末尾追加写数据
false:创建一个新文件,覆盖源文件
写换行:写换行符
windon:\r\n
linux;\n
mac:\r
*/
public class Demo03OutputStream {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("files/c.txt",true);
for (int i = 0; i < 10; i++) {
fos.write("你好".getBytes());
fos.write("\r\n".getBytes());
}
fos.close();
}
}
- 文件复制的原理:
2)字符文件流
1、字符输入流:
/*
java.io.Reader:字符输入流:是字符输入流的最顶层的父类,定义了一些共性的成员方法,是一个抽象类
共性的成员方法:
int read():读取单个字符并返回
int read(char[] char):一次读取多个字符,将字符读入数组
void close():关闭该流并释放与之关联的所有资源
java.io.FileReader extends InputStreamReader extends Reader
FileReader:文件字符输出流:
作用:把硬盘文件中的数据以字符的方式读取到内存中
构造方法:
FileReader(String fileName):
FileReader(File file):
参数:读取文件的数据源
String FileName:文件的路径
File file: 一个文件
FileReader构造方法的作用:
1、创建一个FileReader对象
2、将FileReader对象指向要读取的文件
字符输入流使用步骤:
1、创建FileReader对象, 构造方法中绑定压要读取的数据源
2、使用FileReader对象中的read方法读取文件
3、释放资源
*/
public class Demo01Reader {
public static void main(String[] args) throws IOException {
//1、创建FileReader对象, 构造方法中绑定压要读取的数据源
FileReader fr = new FileReader("files/c.txt");
//2、使用FileReader对象中的read方法读取文件
//共性方法一:int read():读取单个字符并返回
int len=0;
while(-1!=(len=fr.read())){
System.out.print((char)len);
}
//共性方法二:int read(char[] char):一次读取多个字符,将字符读入数组
char[] chars =new char[1024];
int len=0;
while(-1!=(len=fr.read(chars))){
/*
String类的构造方法
String(char[] value):字符数组转化为字符串
String(char[] value,int offset,int count):把字符数组的一部分转化为字符串,offset:数组的开始索引,count:转换的个数
*/
System.out.println(new String(chars,0,len));
}
//3、释放资源
fr.close();
}
}
2、字符输出流:
- 一次写入单个字符:
/*
java.io.Writer:字符输出流:所有字符输出流的最顶层的父类,是一个抽象类
共性的成员属性:
void write(int c): 写入单个字符
void write(char[] chars):写入字符数组
abstract void write(char[] cahrs,int offset, int len):写入字符数组的一部分
void write(String str):写入字符串
void writechar[] cahrs,int offset, int len):写入字符数组的一部分
void flush():刷新该流的缓冲
void close():关闭此流,先刷新它
java.io.FileWriter extends OutputStreamWriter extends Writer
FileWriter:文件字符输出流
作用:把内存中的字符数据写入到文件中
构造方法:
FileWriter(File file):根据给定的File对象构造一个FileWriter对象
FileWriter(String FileName):根据给定的文件名构造一个FileWriter对象
参数:写入数据的目的地
fileName:文件的路径
File file:一个文件
构造方法的作用:
1、会创建一个FileWriter对象
2、会根据构造方法中传递的文件或者文件的路径,创建文件
3、会把FileWriter对象指向创建好的文件
使用步骤:
1、创建一个FileWriter对象,构造方法中写入数据的目的地
2、使用FileWriter中的write方法,把数据写到内存缓冲区中,字符转化为字节的过程
3、使用FileWriter中的flush方法,将内存缓冲区的数据,刷新到文件中
4、释放资源(会把内存缓冲区中的数据刷新到文件中)
*/
public class Demo01Writer {
public static void main(String[] args) throws IOException {
//1、创建一个FileWriter对象,构造方法中写入数据的目的地
FileWriter fw = new FileWriter("files/d.txt");
//2、使用FileWriter中的write方法,把数据写到内存缓冲区中,字符转化为字节的过程
//void write(int c): 写入单个字符
fw.write(97);
//3、使用FileWriter中的flush方法,将内存缓冲区的数据,刷新到文件中
fw.flush();
//4、释放资源(会把内存缓冲区中的数据刷新到文件中)
fw.close();
}
}
- 字符输出流其他写入方式
/*
字符输出流写入数据的其他方法:
void write(char[] chars):写入字符数组
void write(char[] cahrs,int offset, int len):写入字符数组的一部分
void write(String str):写入字符串
void write(String str,int offset, int len):写入字符串的一部分
*/
public class Demo02Writer {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("files/f.txt");
//void write(char[] chars):写入字符数组
char[] cs = {'a','b','c','d','e'};
fw.write(cs);//abcde
//void write(char[] cahrs,int offset, int len):写入字符数组的一部分
fw.write(cs,1,3);
//void write(String str):写入字符串
fw.write("课工场");//课工场
//void write(String str,int offset, int len):写入字符串的一部分
fw.write("我爱你中国",3,2);//中国
fw.close();
}
}
- 追加写/续写
/*
续写与换行:
续写,追加写:使用两个参数的构造方法
FileWriter(String fileName,boolean append)
FileWriter(File file,boolean append)
参数:
String fileName,File file:写入数据的目的地
boolean append:续写开关 true:不会创建新的文件覆盖源文件,可以续写 false:会创建新的文件覆盖源文件
换行:换行符号
windows:\r\n
linux:\n
mac:\n
*/
public class Demo03Writer {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("files/g.txt",true);
for (int i = 0; i <10 ; i++) {
fw.write("HelloWorld"+i+"\r\n");
}
fw.close();
}
}
- flush与close方法的区别
/*
flush和close方法的区别
flush:刷新缓冲区,流对象可以继续使用
close:先刷新缓冲区,然后告知系统释放资源,流对象不可以再被使用
*/
public class Demo02FlushAndClose {
public static void main(String[] args) throws IOException {
//1、创建一个FileWriter对象,构造方法中写入数据的目的地
FileWriter fw = new FileWriter("files/e.txt");
//2、使用FileWriter中的write方法,把数据写到内存缓冲区中,字符转化为字节的过程
//void write(int c): 写入单个字符
fw.write(97);
//3、使用FileWriter中的flush方法,将内存缓冲区的数据,刷新到文件中
fw.flush();
//刷新之后,流可以继续使用
fw.write(98);
//4、释放资源(会把内存缓冲区中的数据刷新到文件中)
fw.close();
//close方法之后流已经关闭,从内存中消失了,流就不能再使用了
//fw.write(99);//报异常:java.io.IOException: Stream closed
}
}
3)缓冲流
- 缓冲流的原理:
- 字节缓冲输入流:
/*
java.io.BufferedInputStream extends InputStream
BufferedInputStream: 字节缓冲输入流:
继承自父类的成员方法:
int read() 从输入流中读取数据的下一个字节
int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中
void close() 关闭此输入流并释放与该流关联的所有系统资源
构造方法:
BufferedInputStream(InputStream in):创建一个BufferedInputStream并保存其参数,即输入流in,以便将来使用
BufferedInputStream(InputStream in,int size):创建具有缓冲区大小的BufferedInputStream并保存其参数,即输入流in,以便将来使用
参数:
InputStream in:字节输入流
我们可以传递FileInputStream,缓冲流会给FileInputStream增加一个缓冲区,提高FileInputStream读取效率
int size:指定缓冲流内部缓冲区的大小,不指定就默认的大小
使用步骤:(重点)
1、创建FileInputStream对象,构造方法中绑定要读取的数据源
2、创建BufferedInputStream对象,构造方法中传递FileInputStream对象,提高FileInputStream对象的读取效率
3、使用BufferedInputStream对象的read方法,读取文件
4、释放资源
*/
public class Demo02BufferedInputStream {
public static void main(String[] args) throws IOException {
// 1、创建FileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("files/a.txt");
// 2、创建BufferedInputStream对象,构造方法中传递FileInputStream对象,提高FileInputStream对象的读取效率
BufferedInputStream bis = new BufferedInputStream(fis);
//3、使用BufferedInputStream对象的read方法,读取文件
// int read() 从输入流中读取数据的下一个字节
// int len = 0;
// while(-1!=(len=bis.read())){
// System.out.println(len);
// }
//int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中
byte[] bytes = new byte[1024];//存储每次读取的数据
int len = 0;//记录每次读取的有效字节个数
while(-1!=(len=bis.read(bytes))){
System.out.println(new String(bytes,0,len));
}
//4、释放资源
bis.close();
}
}
- 字节缓冲输出流:
/*
java.io.BiufferedOutputStream :字节缓冲输出流 (extends 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开始输出到此输出流
public abstract void write(int b); 将指定的字节输出流
构造方法:
BufferedOutputStream(OutputStream out):创建一个新的缓冲输出流,将数据写入指定的底层输出流
BufferedOutputStream(OutputStream out,int size):创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流
参数:
OutputStream out:字节输出流
我们可以传递FileOutputStream,缓冲流会给FileOutputStream增加一个缓冲区,提高FileOutputStream的写入效率
int size:指定缓冲流内部缓冲区的大小,不指定就默认的大小
使用步骤:(重点)
1、创建FileOutputStream对象,构造方法中绑定要输出的目的地
2、创建BufferedFileOutputStream对象,构造方法中传递FileOutputStream的对象,提高FileOutputStream对象效率
3、使用BufferedFileOutputStream对象中write方法,将数据写入到内部的缓冲区当中
4、使用BufferedFileOutputStream对象中flush方法,把内部缓冲区的数据,刷新到文件中
5、释放资源(会先调用flush方法刷新数据,第四步骤给以省略)
*/
public class Demo01BufferedOutputStream {
public static void main(String[] args) throws IOException {
// 1、创建FileOutputStream对象,构造方法中绑定要输出的目的地
FileOutputStream fos = new FileOutputStream("files/a.txt");
// 2、创建BufferedFileOutputStream对象,构造方法中传递FileOutputStream的对象,提高FileOutputStream对象效率
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 3、使用BufferedFileOutputStream对象中write方法,将数据写入到内部的缓冲区当中
bos.write("我把数据写到内部缓冲区中".getBytes());
// 4、使用BufferedFileOutputStream对象中flush方法,把内部缓冲区的数据,刷新到文件中
bos.flush();
// 5、释放资源(会先调用flush方法刷新数据,第四步骤可以省略)
bos.close();
}
}
- 文件复制练习:
/*
文件复制练习:
明确:
数据源:files/g.txt
数据的目的地:files/f.txt
文件复制的步骤:
1、创建字节缓冲输入流对象,构造方法中绑定要读取的数据源
2、创建字节缓冲输出流对象,构造方法中绑定要写入的目的地
3、使用字节缓冲输入流对象中的read方法读取文件
4、使用字节缓冲输出流的write方法,把要读取的数据写入到内存缓冲区中
5、释放资源(先把缓冲区的数据刷新到文件中)
*/
public class Demo01CopyFile {
public static void main(String[] args) throws IOException {
long begin = System.currentTimeMillis();
// 1、创建字节缓冲输入流对象,构造方法中绑定要读取的数据源
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("files/g.txt"));
// 2、创建字节缓冲输出流对象,构造方法中绑定要写入的目的地
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("files/f.txt"));
// 3、使用字节缓冲输入流对象中的read方法读取文件
//一次读取一个字节写入一个字节的方式
// int len = 0;
// while(-1!=(len=bis.read())){
// bos.write(len);
// }
//一次读取多个字节写入多个字节的方式
byte[] bytes = new byte[1024];
int len=0;
while(-1!=(len=bis.read(bytes))){
bos.write(bytes,0,len);
}
bos.close();
bis.close();
long end = System.currentTimeMillis();
System.out.println("复制文件耗时:"+(end-begin)+"毫秒");
}
}
- 字符缓冲输入流:
/*
java.io.BufferedReader extends Reader
继承自父类的共性的成员方法:
int read():读取单个字符并返回
int read(char[] char):一次读取多个字符,将字符读入数组
void close():关闭该流并释放与之关联的所有资源
构造方法:
BufferedReader(Reader in):创建一个使用默认大小输入缓冲区的缓冲字符输入流
BufferedReader(Reader in,int size):创建一个指定大小输入缓冲区的缓冲字符输入流
参数:
Reader in :字符输入流
我们可以传递FileWriter,缓冲流会给FileReader增加一个缓冲区,提高效率
特有的成员方法:
String readline():读取一个文本行,读取一行数据
行的终止符号:通过下列字符之一即可认为某行已终止:换行('\n')、回车('\r')或者或回车后直接换行(\r\n)
返回值:包含该行内容的字符串,不包含任何终止符,如果以达到流末尾,则返回null
使用步骤:
1、创建字符缓冲输入流对象,构造方法中传递字符输入流
2、调用字符输入流对象的read/readline方法,读取文本
3、释放资源
*/
public class Demo04BufferedReader {
public static void main(String[] args) throws IOException {
// 1、创建字符缓冲输入流对象,构造方法中传递字符输入流
BufferedReader br = new BufferedReader(new FileReader("files/c.txt"));
//2、调用字符输入流对象的read/readline方法,读取文本
// String line = br.readLine();
// System.out.println(line);
//
// line = br.readLine();
// System.out.println(line);
//
// line = br.readLine();
// System.out.println(line);
//
// line = br.readLine();
// System.out.println(line);
/*
循环优化,不知道文件中有多少行数据,所以使用while循环
while的结束条件:读取到null结束
*/
String line;
while(null!=(line=br.readLine())){
System.out.println(line);
}
//3、释放资源
br.close();
}
}
- 字符缓冲输出流:
/*
java.io.BufferedWriter extends Writer
BufferedWriter:字符缓冲输出流
继承自父类共性的成员方法:
void write(int c): 写入单个字符
void write(char[] chars):写入字符数组
abstract void write(char[] cahrs,int offset, int len):写入字符数组的一部分
void write(String str):写入字符串
void writechar[] cahrs,int offset, int len):写入字符数组的一部分
void flush():刷新该流的缓冲
void close():关闭此流,先刷新它
构造方法:
BufferedWriter(writer out):创建一个使用默认大小输出缓冲区的缓冲字符输出流
BufferedWriter(writer out,int size):创建一个使用给定大小输出缓冲区的新缓冲字符输出流
参数:
writer out:字符输出流
我们可以传递FileWriter.缓冲流会给FileWriter增加一个缓冲区,提高xiaolv
int size:指定缓冲区的大小,不写默认大小
特有的成员方法:
void newline():写入一个行分隔符。会根据不同的操作系统,获取不同的行分隔符
使用步骤:
1、创建字节缓冲输出流对象,构造方法中传递字符输出流
2、调用字节缓冲输出流中的writer方法,把数据写入到内存缓冲区中
3、调用字节缓冲输出流中的flush方法,把内存缓冲区中的数据刷新到文件中
4、释放资源
*/
public class Demo03BufferedWriter {
public static void main(String[] args) throws IOException {
//1、创建字节缓冲输出流对象,构造方法中传递字符输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("files/c.txt"));
// 2、调用字节缓冲输出流中的writer方法,把数据写入到内存缓冲区中
for (int i = 0; i <10 ; i++) {
bw.write("课工场"+i);
//bw.write("\r\n");
bw.newLine();
}
// 3、调用字节缓冲输出流中的flush方法,把内存缓冲区中的数据刷新到文件中
bw.flush();
// 4、释放资源
bw.close();
}
}
4)序列化与反序列化
- 概念:
- 序列化:
/*
java.io.ObjectOutputStream extends OutputStream
ObjectOutputStream :对象的序列化流
作用:把对象以流的方式写入到文件中保存
构造方法:
ObjectOutputStream(OutputStream out) 创建写入指定OutputStream的ObjectOutputStream
参数:
OutputStream out:字节输出流
特有的成员方法:
void writerObject(Object obj)将指定的对象写入ObjectOutputStream
使用步骤:
1、创建ObjectOutputStream对象,构造方法中传递字节输出流
2、使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
3、释放资源
*/
public class Demo01ObjectOutputStream {
public static void main(String[] args) throws IOException {
// 1、创建ObjectOutputStream对象,构造方法中传递字节输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("files/person.txt"));
//2、使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
oos.writeObject(new Person("小美女",18));
//3、释放资源
oos.close()
}
}
/*
序列化与反序列化的时候,会抛出NotSerializableException没有序列化异常
类通过实现java.io.Serializable接口以启用其序列化功能。未实现此接口的类将无法使用其任何状态序列化或反序列化
Serializable接口也叫标记型接口
要进行序列化和反序列化的类必须实现Serializable接口,就会给类添加一个标记
当我们进行序列化和反序列化的时候,就会检测类上是否有这个标记。
如果有,就可以序列化或者反序列化
如果没有,就会抛出NotSerializableException
*/
public class Person implements Serializable {
private String name;
private int age;
public Person() {
}
public Person(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 "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 反序列化:
/*
java.io.ObjectInputStream extends InputStream
ObjectInputStream :对象的反序列化流
作用:把文件中保存的对象,以流的方式读取出来使用
构造方法:
ObjectInputStream(InputStream in):创建从指定InputStream 读取的 ObjectInputStream
参数:
InputStream in:字节输入流
特有的成员方法:
Object readObject() 从ObjectInputStream 读取对象
使用步骤:
1、创建ObjectInputStream对象,在构造方法中传递字节输入流
2、使用ObjectInputStream对象的readObject方法,读取保存对象的文件
3、释放资源
4、使用读取出来的对象,直接打印
readObject()方法声明抛出了ClassNotFoundException异常:class文件找不到异常
当不存在对象的calss文件时,抛出此异常
反序列化的前提:
1、类必须实现serializable接口
2、必须存在类对应的class文件
*/
public class Demo02ObjectInputStream {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//1、创建ObjectInputStream对象,在构造方法中传递字节输入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("files/person.txt"));
//2、使用ObjectInputStream对象的readObject方法,读取保存对象的文件
Object o = ois.readObject();
//3、释放资源
ois.close();
//4、使用读取出来的对象,直接打印
System.out.println(o);
//也可强转成Person类打印
Person p=(Person)o;
System.out.println(p.getName()+p.getAge());
}
}
四、流的异常处理
一、try catch finally
/*
在jdk1.7之前可以使用try catch finally处理异常
格式:
try{
可能会产生异常的代码
}catch(异常类的变量 变量名){
异常的处理逻辑
}finally{
一定会指定的代码
资源释放
}
*/
public class Demo01TryCatch {
public static void main(String[] args) {
//提高变量fw的作用域,让finally可以使用
//变量在定义的时候可以没有值,在使用的时候必须有值
//fw = new FileWriter("files/g.txt",true);如果执行失败,fw没有值,fw.close就会报错
FileWriter fw=null ;
try{
//可能会产生异常的代码
fw = new FileWriter("files/g.txt",true);
for (int i = 0; i <10 ; i++) {
fw.write("HelloWorld"+i+"\r\n");
}
fw.close();
}catch(IOException e){
//异常的处理逻辑
System.out.println(e);
}finally{
//一定会指定的代码
//创建对象失败了,fw的默认值为null,null是不能调用方法的,会抛出NullPointerException异常,需要增加一个判断,不是null再把资源释放了
if(fw!=null){
try {
//fw.close方法声明抛出IOException异常,所以要处理这个异常对象,要么trycatch,要么throws,
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
二、JDK1.7之后
/*
JDK7的新特性
在try的后面可以增加一个(),在括号中可以定义流对象
那么这个流对象的作用域就在try中有效
try中的代码执行完毕后,就会自动的把流对象释放,不用写finally
格式:
try(定义流对象....){
可能会产生异常的代码
}catch(异常类的变量 变量名){
异常的处理逻辑
}
*/
public class Demo01JDK07Exception {
public static void main(String[] args) {
try(FileInputStream fis = new FileInputStream("files/b.txt");
FileOutputStream fos = new FileOutputStream("files/test1.txt");){
//可能会出现异常的代码
//一次读取一个字节fangfa
int len = 0;
while((len=fis.read())!=-1){
fos.write(len);
}
}catch(IOException e){
//异常的处理逻辑
System.out.println(e);
}
}
}
三、JDK1.9之后
/*
JDK9新特性
try的前面可以定义流对象,
在try后面的()中可以直接引入流对象的名称(变量名)
在try代码块执行完毕后,流对象也可以释放掉,不用写finally
格式:
A a = new A();
B b = new B();
try(a;b){
可能会产生异常的代码
}catch(异常类的变量 变量名){
异常的处理逻辑
}
*/
public class Demo01JDK09Exception {
public static void main(String[] args) throws FileNotFoundException {
FileInputStream fis = new FileInputStream("files/b.txt");
FileOutputStream fos = new FileOutputStream("files/test1.txt");
try(fis;fos){
//一次读取一个字方法
int len = 0;
while((len=fis.read())!=-1){
fos.write(len);
}
}catch(IOException e){
System.out.println(e);
}
}
}