(一)IOException的处理方式
把真正的异常原因包装到RuntimeException中然后抛出。使调用者更加灵活。
public class copy_picture {
public static void main(String[] args)throws IOException {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
//找到目标文件
File file1=new File("E:\\picture1\\2.jpg");//源目标文件
File file2=new File("F:\\picture2\\大猫.jpg");//目的目标文件
//建立数据通道
fileInputStream=new FileInputStream(file1);
fileOutputStream=new FileOutputStream(file2);
//读取数据
int length=0;//记录本次读取的字节数
//建立缓冲字节数组
byte[] buf=new byte[1024];
//边读边写
while((length=fileInputStream.read(buf))!=-1) {
fileOutputStream.write(buf,0,length);//这样写保证读到多少写多少,不会每次都写1024个字节,导致写多
}
}catch(IOException e) {
System.out.println("拷贝出错...");
throw new RuntimeException(e);
}finally {
try {
//关闭资源(原则:先开后关,后开先关)
if(fileOutputStream!=null) {
fileOutputStream.close();
}
}catch(IOException e) {
System.out.println("关闭资源失败...");
throw new RuntimeException(e);
}finally {
try {
if(fileInputStream!=null) {
fileInputStream.close();
}
}catch(IOException e) {
System.out.println("关闭资源失败...");
throw new RuntimeException(e);
}
}
}
}
}
(二)输入缓冲字节流
使用FileInputStream读取文件数据时如何读取效率是最高?
使用字节数组作为缓冲区读取的效率是最高的。
缓冲输入字节流的作用:提高读取文件数据的效率。
输入字节流的体系:
InputStream 抽象类 所有输入字节流的基类
FileInputStream 读取文件数据的输入字节流
BufferedInputStream 缓冲输入字节流 该类的本质是在内部维护了一个8KB的字节数组。主要是为了提高读取文件的效率
凡是缓冲流都没有读写文件的能力。
BufferedInputStream要注意的事项:
1.BufferedInputStream的close方法实际关闭的是传进去的fileInputStream。
public class iobuffer_demo1 {
public static void main(String[] args) throws FileNotFoundException, IOException {
buffer_read1();
}
public static void buffer_read1() throws FileNotFoundException, IOException {
//第一步,找到目标文件
File file=new File("E:\\aaa.txt");
//第二步:建立文件与数据的输入通道
FileInputStream fileInputStream=new FileInputStream(file);
//第三步:建立缓冲输入字节流
/*
疑问:为什么创建BufferedInputStream对象需要传入一个FileInputStream对象呢?
BufferedInputStream没有读取文件数据的能力,但又要读取数据,只能依赖一个具备
读取文件数据能力的对象。
*/
BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream);
//第四步:读取文件数据
int content=0;
/*
疑问:BufferedInputStream的read方法每次只是读取一个字节数据,FileInputStream的read方法每次也是读取一个字节数据,
那么为何BufferedInputStream能提高读取文件数据的效率。
BufferedInputStream读取数据是从8kb的字节数组中读取,数组在内存中,效率较高。
程序运行时读取数据是从内存读取。
* */
while((content=bufferedInputStream.read())!=-1) {//read()每次只读取一个字节数据,并返回
System.out.print((char)content);
}
/*
while((content=fileInputStream.read())!=-1) {//read()每次只读取一个字节数据,并返回
System.out.print((char)content);
}
//从硬盘中读取数据,效率较低
*/
//bufferedInputStream.close();
fileInputStream.close();
}
}
(三)输出缓冲字节流
缓冲输出字节流:为了提高写文件的效率。
OutputStream 抽象类,所有输出字节流的基类。
FileOutputStream 向文件写出数据的输出字节流对象。
BufferedOutputStream 缓冲输出字节流,提高文件数据的写出效率。
BufferedOutputStream需要注意的事项:
1.使用BufferedOutputStream的write方法时,数据其实是写入了BufferedOutputStream内部维护的字节数组中,只有调用了
BufferedOutputStream的close方法或flush方法,数据才会真正写到硬盘中去,或者内部维护的字节数组已经存储满,此时数据也会写到硬盘中。
2.BufferedOutputStream的close方法实际上关闭的是传入的OutputStream对象的close方法。
public class iobuffer_demo2 {
public static void main(String[] args) throws IOException {
buffer_write1();
}
public static void buffer_write1() throws FileNotFoundException, IOException {
//找到目标文件
File file=new File("E:\\aaa.txt");
//建立数据输出通道
FileOutputStream fileOutputStream=new FileOutputStream(file);
//建立缓冲输出字节流
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(fileOutputStream);
//写数据
String data="hello world";
bufferedOutputStream.write(data.getBytes());//write()为了提高效率,先将数据写入字节数据数组,写够以后,再一起存入字节数组。
bufferedOutputStream.flush();//把缓冲字节数组的数据写到硬盘中
fileOutputStream.close();
}
}
练习:
使用缓冲字节流拷贝照片
public class iobuffer_cpoyImage {
public static void main(String[] args) throws IOException {
//输入
File file1=new File("E:\\picture1\\2.jpg");
FileInputStream fileInputStream=new FileInputStream(file1);
BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream);
//输出
File file2=new File("F:\\picture2\\大猫.jpg");
FileOutputStream fileOutputStream=new FileOutputStream(file2);
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(fileOutputStream);
//边读边写
int content=0;
while((content=bufferedInputStream.read())!=-1) {
bufferedOutputStream.write(content);
}
//将字节数组中数据写入内存
//bufferedOutputStream.flush();
bufferedOutputStream.close();
bufferedInputStream.close();
}
}
(四)输入字符流
字符流:读取的数据是以字符为单位,会把读取到的字节数据转换成看得懂的字符。字符流=字节流+编码(解码)
输入字符流:
Reader 抽象类 所以输入字符流的基类
FileReader 读取文件数据的输入字符流
建立数据的输入通道
FileReader fileReader=new FileReader(file);
//建立缓冲字符数组,读取文件数据
char[] buf=new char[1024];
int length=0;
while((length=fileReader.read(buf))!=-1) {//read(char[] buf)读取到的字符数组存储到了字符数组中,返回的是读取到的字符个数
System.out.println(new String(buf,0,length));
}
fileReader.close();
}
//方法1:每次只会读取一个字符的数据
public static void read1() throws FileNotFoundException, IOException {
//找到目标文件
File file =new File("E:\\aaa.txt");
//建立数据的输入通道
FileReader fileReader=new FileReader(file);
//读取数据
int content=0;
while((content=fileReader.read())!=-1) {//fileReader.read()每次读取一个字符数据,返回该字符数据,如果读到了文件末尾返回-1表示
System.out.print((char)content);
}
fileReader.close();
}
}
(五)输出字符流
输出字符流:
Writer 抽象类 输出字符流的基类。
FileWriter 向文件写数据输出流。
FileWriter
1.找到目标文件
2.建立数据输出通道
3.写出数据
4.关闭资源
FileWriter要注意的事项:
1.new FileWriter(file)时,若目标文件不存在,会先创建文件。
2.使用FileWriter(file)构造方法默认会清空文本的数据,然后再写入新的数据。如需要追加数据需要使用
FileWriter(file,true).
3.使用FileWriter的write方法时,数据是写入了FileWriter内部维护的字符数组中,如果需要把数据真正写到硬盘上去,需要调用flush方法或close方法。
public class demo1 {
public static void main(String[] args) throws IOException {
File file=new File("E:\\aaa.txt");
FileWriter fileWriter=new FileWriter(file,true);
//准备数据,把数据写出
String str="阴天快乐";
fileWriter.write(str);//可以直接写入一个字符串,不用转成字节数组
fileWriter.close();
//fileWriter.flush();//刷新输出字符流
}
}
练习:输入输出字符流拷贝一个java文件。
public class demo2 {
public static void main(String[] args) throws IOException {
File file1=new File("C:\\Users\\lenovo\\eclipse-workspace\\day19\\src\\output\\copy_picture.java");
File file2=new File("E:\\cpoy_image.java");
FileReader fileReader=new FileReader(file1);
FileWriter fileWriter=new FileWriter(file2);
//边读边写
int length=0;
//字符数组缓冲区
char[] buf=new char[1024];
while((length=fileReader.read(buf))!=-1) {
fileWriter.write(buf,0, length);//每次读取到多少写多少
}
fileWriter.close();
fileReader.close();
}
}
如果操作是是文本数据,使用字符流。
如果操作的是非文本数据,使用字节流。图片、视频、音频、word.(不会经过解码、转化处理)
(六)输入缓冲字符流
缓冲输入字符流:
字符流的体系:
Reader 抽象类 所有输出字符流的基类。
FileReader 读取文件字符数据的输入字符流
BufferedReader 该类出现的目的:提高读取文件字符数据的效率,对FileReader的功能进行了拓展--readLine()。 缓冲输入字符流
public class iobuffer_demo3 {
public static void main(String[] args) throws IOException {
File file=new File("C:\\Users\\lenovo\\eclipse-workspace\\day19\\src\\output\\copy_picture.java");
//File file=new File("E:\\aaa.txt");
FileReader fileReader=new FileReader(file);
String line=null;
while((line=myReadLine(fileReader))!=null) {
System.out.println(line);
}
}
//自己实现一个readLine方法,只读一行
public static String myReadLine(FileReader fileReader) throws IOException {
StringBuilder sb=new StringBuilder();
int content=0;
while((content=fileReader.read())!=-1) {
if(content=='\r') {
continue;
}else if(content=='\n') {
return sb.toString();
}else {
sb.append((char)content);
}
}
return null;
}
//缓冲字符流读取
public static void read1() throws FileNotFoundException, IOException {
File file=new File("E:\\aaa.txt");
FileReader fileReader=new FileReader(file);
BufferedReader bufferedReader =new BufferedReader(fileReader);
//读取文件数据
String line=null;
while((line=bufferedReader.readLine())!=null) {//每次读取一行
System.out.println(line);
}
bufferedReader.close();//关闭的是传入进来的参数fileReader
}
}
(七)输出缓冲字符流
缓冲输出字符流 BufferedWriter
体系:
Writer 抽象类 所有输出字符流的基类
FileWriter 向文件输出数据的输出字符流。
BufferedWriter 缓冲输出字符流,目的:为了提高写文件数据的效率以及拓展FileWriter的功能。
public class iobuffer_demo4 {
public static void main(String[] args) throws IOException {
File file=new File("E:\\aaa.txt");
FileWriter fileWriter=new FileWriter(file,true);//可以追加
BufferedWriter bufferedWriter=new BufferedWriter(fileWriter);
//准备数据,把数据写出
bufferedWriter.newLine();//追加到新的一行
bufferedWriter.write("你好aaa");//可以直接写字符串
//刷新缓冲区
bufferedWriter.flush();
}
}