一、前情回顾(字节流)
package com.bianyiit.cast;
import java.io.*;
public class Demo0 {
public static void main(String[] args) throws IOException {
//创建字节输入流对象
//FileInputStream is = new FileInputStream(new File("D:\\重要代码Demo\\文件IO对象\\FileDemo2\\f.txt"));
//java.io.FileNotFoundException: D:\重要代码Demo\文件IO对象\FileDemo2\f.txt (系统找不到指定的文件。)
try(
FileInputStream is = new FileInputStream("D:\\重要代码Demo\\文件IO对象\\FileDemo2\\a.txt");
//创建输出流对象
FileOutputStream os = new FileOutputStream("D:\\重要代码Demo\\文件IO对象\\FileDemo2\\f.txt",true);
//输出流有自动创建文件对象的效果
){
int length;
//定义一个字节数组
byte[] arr=new byte[1024];
while((length=is.read(arr))!=-1){
os.write(arr,0,length);
}
}
//jdk7版本的新特性,可以不用写close(),默认关闭流空间
}
}
二、字符流
1.字符输入流FileReader
1.1 Reader (字符输入流,抽象类,不能直接创建对象)的直接子类是InputStreamReader(字节转换流--桥梁)的直接子类是FileReader
相当于FileReader是Reader的间接子类
1.2 InputStream(字节输入流,抽象类,不能直接创建对象)的直接子类是FileInputStream
相当于FileInputStream是InputStream的直接子类
1.3 字符流=编码表+字节流
package com.bianyiit.cast;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class ZiFuIO1 {
public static void main(String[] args) throws IOException {
//字符流:字符输入流(读数据)FileReader
Reader rd = new FileReader("D:\\重要代码Demo\\文件IO对象\\字符流\\a.txt");
/*int read = rd.read();
System.out.println((char)read);*/
char[] arr=new char[2];
int length;
while((length=rd.read(arr))!=-1){
String s = new String(arr, 0, length);
System.out.print(s);
}
}
}
2.字符输出流FileWriter
2.1 Writer-->OutputStreamWriter-->FileWriter
相当于FileWriter是Writer的间接子类
2.2 输出流会在默认路径自动创建文件对象
2.3 使用字符输出流往文件写数据的时候,还要有一个刷新的过程
2.4 关流的close方法自带刷新的效果,如果忘记写了flush(),而写了close(),也是能够将字符写进文本文件中
//字符流:字符输出流(写数据)FileWriter
package com.bianyiit.cast;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class ZiFuIO2 {
public static void main(String[] args) throws IOException {
//字符输出流(写数据)Writer-->OutputStreamWriter-->FileWriter
//创建字符输出流对象
Writer wt = new FileWriter("D:\\重要代码Demo\\文件IO对象\\字符流\\b.txt");
//输出流会在默认路径自动创建文件对象
String s="世界你好!!";
//把字符串转换成字符数组
char[] chs = s.toCharArray();
//把字符数组写入文本文件中
wt.write(chs); //没写进去
//直接将字符串写入文本文件中
wt.write(s); //同样没写进去
//使用字符输出流往文件写数据的时候,还要有一个刷新的过程
wt.flush(); //刷新该流的缓冲
//关流的close方法自带刷新的效果,如果忘记写了flush(),而写了close(),能够写进文本文件中
}
}
3.面试题:使用字符输出流写数据的时候为什么一定要刷新才能把内容写入到指定的文件中
本质:
内存中存在了一个缓冲区
执行原理:
从内存中写入硬盘中,先从内存中写入缓冲区中.然后通过刷新,将字符通过编码表转换成二进制,然后通过字节输出流写入硬盘
如果是从硬盘中写入内存中,通过先加载至缓冲区,而缓冲区本身就是内存的一部分,当写入缓冲区时本质上就是写入了内容,因为缓冲区同样是内存的一部分
注意:
缓冲区的大小只有8KB,如果需要写入的内容超过了8KB,超过的部分会自动写入硬盘文件中,不需要刷新的过程
面试题分析图解:
4.利用字符流进行文本的复制
package com.bianyiit.cast;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class ZiFuIO3 {
public static void main(String[] args) throws IOException {
//使用字符流进行文件的复制
//close()默认有刷新方法flush(),而使用jdk7的新特性,会默认有close()
try(
FileReader rd = new FileReader("D:\\重要代码Demo\\文件IO对象\\字符流\\a.txt");
FileWriter fw = new FileWriter("D:\\重要代码Demo\\文件IO对象\\字符流\\k.txt")){;
char[] arr=new char[1024];
int length;
while((length=rd.read(arr))!=-1){
fw.write(arr,0,length);
}
}
}
}
5.提示:字符流不要去操作图片、音频、视频等一些文件的读和写,因为没有对应的编码表可以将图片、音频、视频文件的字节转换成对应的字符
6.需求:往文件中写数据 实现 hello java 排列是换行的
package com.bianyiit.cast;
import java.io.FileWriter;
import java.io.IOException;
public class HuanHangDemo {
public static void main(String[] args) throws IOException {
//需求:往文件中写数据 hello java 排列是换行的
FileWriter wt = new FileWriter("D:\\重要代码Demo\\文件IO对象\\转换流\\b.txt");
//wt.write("hello"+"\r\n"+"java");
wt.write("hello"+System.lineSeparator()+"java");
//如何加一个换行符 操作系统中的换行符 PC端 Windows 92% Linux 1% Mac os 5% dos
//windows: \r\n Mac os--1.9版本之前: \r 1.9版本之后: \n
//Linux Niux: \n Dos: \r
//java的程序是一次编写,到处运行 不同的操作系统都可以运行
//获取本系统的换行符:System.LineSeparator
//wt.write("java");
wt.flush();
//手机端操作系统:IOS--苹果 android--安卓(谷歌) 塞班Sysbian--诺基亚
}
}
三、转换流
需求:假如只给了字节流对象,但是规定要使用字符流操作文本文件,这个时候就要用到转换流了
解决:需要使用转换流 InputStreamReader 将字节输入流到字符输入流的转换
1.InputStreamReader 字节输入转换流 字节流--字符流
package com.bianyiit.cast;
import java.io.*;
public class ZiFuIO4 {
public static void main(String[] args) throws IOException {
//需求:只给了字节流对象,但是规定要使用字符流操作文本文件
//需要使用转换流 InputStreamReader 将字节输入流到字符输入流的转换
InputStream is = new FileInputStream("D:\\重要代码Demo\\文件IO对象\\转换流\\a.txt");
InputStreamReader isr = new InputStreamReader(is);
char[] arr=new char[1024];
int length;
while((length=isr.read(arr))!=-1){
String s=new String(arr,0,length);
System.out.println(s);
}
}
}
2.OutputStreamWriter 字节输出转换流 字符流--字节流
package com.bianyiit.cast;
import java.io.*;
public class ZhuanHuanLiuDemo2 {
public static void main(String[] args) throws IOException {
//InputStreamReader 字节输入转换流 字节流--字符流
//OutputStreamWriter 字节输出转换流 字符流--字节流
//转换流不是两个流角色发生改变,而是输入和输出的时候用到了两个不同的流,这两个流之间需要一根桥梁搭建起来
InputStream is = new FileInputStream("D:\\重要代码Demo\\文件IO对象\\转换流\\a.txt");
InputStreamReader isr = new InputStreamReader(is);
//isr调用的是字符流的方法
FileOutputStream fs = new FileOutputStream("D:\\重要代码Demo\\文件IO对象\\转换流\\b.txt");
OutputStreamWriter osw = new OutputStreamWriter(fs);
//osw调用还是字符流的方法
//流的转换不是真正的字节流变成了字符流,也不是字符流变成字节流
//假设输出的时候是字节流,而输入的时候是字符流
//假设输出的时候是字符流,而输入的时候是字节流
}
}
注意:转换流不是两个流角色发生改变,而是输入和输出的时候用到了两个不同的流,这两个流之间需要一根桥梁搭建起来
3.转换流分析图解
四、缓冲流
1.为什么要使用缓冲流??
原因:经过分析我们发现,无论是字节流还是字符流,在操作数据的时候,都是一个字节一个字节(一个字符一个字符的操作),每一次操作都需要和硬件资源打交道,不仅会对硬盘产生损耗,而且效率非常低
解决:于是这是就引入了缓冲流的概念,内存中有一块8KB大小的缓冲区,我们由原来一个字节一个字节的读和写变成一个写8KB的数据进入缓冲区,而取也是一次取8KB的数据,从而减少了对硬盘的访问次数,提高了读写的效率
2.缓冲流图解分析
3.字节缓冲输入流 BufferedInputStream
package com.bianyiit.cast;
import java.io.*;
import java.nio.Buffer;
public class BufferDemo1 {
public static void main(String[] args) throws IOException {
//使用缓冲流的原因:1.减少对硬盘的访问次数;2.提高了读写的效率
InputStream is = new FileInputStream("D:\\重要代码Demo\\文件IO对象\\缓冲流\\a1.txt");
BufferedInputStream bis = new BufferedInputStream(is);
/*int read = bis.read(); //这里一次还是读的是一个字节
System.out.println((char)read);*/
//method(bis);
byte[] arr=new byte[1024];
int length;
while((length=bis.read(arr))!=-1){
String s = new String(arr, 0, length);
System.out.println(s);
}
}
private static void method(BufferedInputStream bis) throws IOException {
byte[] arr=new byte[1024];
int read;
int i=0;
while((read=bis.read())!=-1){
byte b=(byte)read;
arr[i]=b;
i++;
}
String s = new String(arr, 0, i);
System.out.println(s);
//数组的长度只有1k,如果txt里面的数据超过1k,就会报数组越界异常
}
}
注意:使用第二种方法,当数组的长度只有1k,如果txt里面的数据超过1k,就会报数组越界异常
4.字节缓冲输出流 BufferedOutputStream
package com.bianyiit.cast;
import java.io.*;
public class BufferDemo2 {
public static void main(String[] args) throws IOException {
//字节输出缓冲流
OutputStream os = new FileOutputStream("D:\\重要代码Demo\\文件IO对象\\缓冲流\\a1.txt");
BufferedOutputStream bos = new BufferedOutputStream(os);
//字符串-->字节数组
bos.write("hello".getBytes());
bos.flush();
bos.close();
//可能使用字节的时候效果还是一样的,但是底层还是有较大的区别
}
}
注意:使用字节流的时候是不需要刷新的,那使用字节缓冲流需不需要刷新呢??
结果:使用字节流直接写数据的时候不需要刷新,而使用字节缓冲流写数据的时候还有刷新才能够把数据写进文件
原因:如果是以字节流直接写数据到文件中,而以缓冲流写数据,先写到缓冲区,需要刷新才能从缓冲区写到文件中
5.字符缓冲输入流 BufferedReader
package com.bianyiit.cast;
import java.io.*;
public class BufferDemo3 {
public static void main(String[] args) throws IOException {
//字符缓冲流
Reader rs = new FileReader("D:\\重要代码Demo\\文件IO对象\\缓冲流\\b.txt");
BufferedReader br = new BufferedReader(rs);
/*char[] arr=new char[1024];
int length;
while((length=br.read(arr))!=-1){
String s = new String(arr, 0, length);
System.out.println(s);
}*/
//一次读一行(字符缓冲流特有的方法readline())
String s;
while((s=br.readLine())!=null){
//可以将后面的空字节全部读出来
System.out.println(s);
}
}
}
6.字符输出缓冲流 BufferedWriter
package com.bianyiit.cast;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferDemo4 {
public static void main(String[] args) throws IOException {
//字符输出缓冲流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\重要代码Demo\\文件IO对象\\缓冲流\\b.txt",true));
bw.write("打开一个文件夹!!");
//BufferWriter特有的功能:newline()进行换行
bw.newLine();
bw.write("我是一个superman");
bw.flush(); //需要刷新一下
bw.close();
}
}