IO流
学习目标:
什么是IO流,IO流分类有哪些,IO流的功能是什么?
能够正确使用字节/字符缓冲流读写文件
能够正确处理IO流程序开发过程的异常
一、异常
概念
非正常情况,即异常就是程序出现的错误;
分类(顶层 Throwable)
a) 异常(Exception):常说的异常,合理的应用程序可能需要捕捉的异常,如NullPointException(空指针异常)
b)错误(Error):合理的应用程序不应该试图捕捉的问题,如StackOverFlowError(栈内存溢出)
异常处理方式
a) JVM默认的异常处理方式:在控制台打印错误信息,并终止程序;
b)开发中异常处理的方式:
♦ try—catch(finally):捕捉异常,自己处理;
try {
//尝试执行的代码
//代码有异常跳到catch,没有异常则运行完直接到finally
} catch(Exception e) {
//出现可能的异常之后的处理代码
} finally {
//一定会执行的代码,如关闭资源
}
特点: 处理完异常后,程序会继续执行;
就算之前有return,finally中的代码也会继续执行完再终止 程序;
♦throws:抛出异常,交给调用者处理,调用者必须处理异常;
pubilc void test() throws Exception {}
调用者解决异常:
a) 继续也抛出异常;特点:执行结束后,程序不在执行;
b) 采用try—catch;
try {
//尝试执行的代码
//代码有异常跳到catch,没有异常则运行完直接到finally
test();
} catch(Exception e) {
//出现可能的异常之后的处理代码
System.out.println("代码有异常");
}
System.out.println("可以继续执行");
二、IO流
概念
I/O,即输入(Input)和输出(Output),IO流指数据像连绵的流体一样进行传输,即Java中用来传输数据的。
IO流作用
在本地磁盘和网络上操作数据;
分类
1、按数据流向分类:
♦输入流: 读取数据
♦输出流: 往外写数据
2、操作方式分类:
♦字节流
a) InputStream(字节输入流的顶层抽象类)
b) OutputStream(字节输出流的顶层抽象类)
♦字符流
a) Reader(字符输入流的顶层抽象类)
b) writer(字符输出流的顶层抽象类)
IO流体系(常用的)
1、字符流:按字符读写数据的IO流
Reader:FileReader(普通字符输入流),BufferedReader(高效字符输入流,也叫缓冲字符输入流,自带缓冲区,大小为8192个字符,也就是16KB)
Writer:FileWriter,BufferedWriter
2、字节流:按字节读写的数据流
InputStream: FileInputStream, BufferedInputStream
OutputStream: FileOutputStream,BuferedOutputStream
三、File类
概念
文件,文件夹,一个File对象代表磁盘上的某个文件或文件夹,即就是用来操作文件(夹)路径的;
构造方法
File(String pathname):根据字符串形式的路径来创建对应的File对象;
File(String parent, String child):根据父目录和子目录来创建对应的File对象;
File(File parent, String child):先将父目录封装成File对象,然后结合字符串形式的目录来获取新的File对象
成员方法(创建、判断、获取功能)
创建功能:文件不存在创建文件,存在则不创建 返回false
createNewFile():创建文件
mkdir()和mkdirs():创建目录
判断功能:
isDirectory():判断File对象是否为目录
isFile():判断File对象是否为文件
exists():判断File对象是否存在
获取功能:
getAbsolutePath(): 获取绝对路径,以盘符开头的路径
getPath(): 获取文件的相对路径,Java中是指相对于当前项目路径来讲的
getName(): 获取文件名
list(): 获取指定目录下所有文件(夹)名称数组
listFiles(): 获取指定目录下所有文件(夹)File数组
学习代码
package filedemo;
import java.io.File;
import java.io.IOException;
/**
* @author: @橘子先森
* @create: 2020-11-10 19:40
**/
/*
**概念**
文件,文件夹,一个File对象代表磁盘上的某个文件或文件夹;
**构造方法**
File(String pathname):根据字符串形式的路径来创建对应的File对象;
File(String parent, String child):根据父目录和子目录来创建对应的File对象;
File(File parent, String child):先将父目录封装成File对象,然后结合字符串形式的目录来获取新的File对象
**成员方法(创建、判断、获取功能)**
createNewFile():创建文件
mkdir()和mkdirs():创建目录
isDirectory():判断File对象是否为目录
isFile():判断File对象是否为文件
exists():判断File对象是否存在
*/
public class Test {
//main函数是所有程序的主入口,所有的代码都是从这里开始的
public static void main(String[] args) throws IOException {
//需求:将 D:\abc\1.txt 封装成File对象
//方法一: 根据字符串形式的路径获取File对象
//注意,Java中 \ 表示转义符,复制路径中 \ 会自动填写成 \\,或者写成 /
//File file1 = new File("D:\\abc\\1.txt");
File file1 = new File("D:/abc/1.txt");
System.out.println("file1 " + file1);
//方法二:根据字符串形式的父目录和子目录创建File对象
File file2 = new File("D:/abc/","1.txt");
System.out.println("file2 " + file2);
//方式三:根据父目录File对象和字符串形式的子目录来获取File对象
File file3 = new File("D:/abc/");
File file4 = new File(file3,"1.txt");
System.out.println("file4 " + file4);
System.out.println("--------------------------");
//创建功能
//需求:在D:盘下创建 2.txt 文件
File file5 = new File("D:/2.txt");
boolean flag1 = file5.createNewFile();
System.out.println("flag1 " + flag1);
//需求:在D:盘下创建abc文件夹
File file6 = new File("d:/abc");
boolean flag2 = file6.mkdir(); //make directory;创建单级目录
System.out.println("flag2 " + flag2);
//需求:在D:盘下创建abc/a/b/c文件夹
File file7 = new File("D:/abc/a/b/c");
boolean flag3 = file7.mkdirs(); //make directories;创建多级目录,也可以单级目录
System.out.println("flag3 " + flag3);
System.out.println("--------------------------");
//判断功能
File file8 = new File("D:/abc/a");
//boolean flag4 = file8.isDirectory();
//System.out.println("判断是否是文件夹 " + flag4);
System.out.println("判断是否是文件夹 " + file8.isDirectory());
System.out.println("判断是否是文件 " + file8.isFile());
System.out.println("判断是否存在 " + file8.exists());
//获取功能
//在项目中创建一个lib文件夹,在文件夹中创建 1.txt文件
File file9 = new File("lib/1.txt");
//获取file9的绝对路径
String absolutePath = file9.getAbsolutePath();
System.out.println("绝对路径: " + absolutePath); //绝对路径: D:\JavaStudy\lib\1.txt
//获取file9的相对路径
String path = file9.getPath();
System.out.println("相对路径: " + path); //相对路径: lib\1.txt
//获取文件名
String name = file9.getName();
System.out.println("文件名: " + name); //文件名: 1.txt
//获取lib目录下所有文件(夹)的名称数组 String[]
File file10 = new File("lib");
String[] list = file10.list();
for (String s : list) {
System.out.print("lib目录下文件(夹)的名称数组:" + s + " ");
}
System.out.println();
//获取lib目录下所有文件(夹)的File对象数组 File[]
File[] files = file10.listFiles();
for (File file : files) {
System.out.print("lib目录下所有文件(夹)的File对象数组:" + file +" ");
}
}
}
四、字符流读写文件
1、字符流读数据(两种)——按单个字符读取
♦创建字符流读文件对象(Reader是抽象类,需用其子类)
Reader reader = new FileReader("readme.txt");
♦调用方法读取数据(读取一个字符,返回该字符代表的整数 a-97(ASCII码值),若达到流的末尾,返回 -1)
int data = reader.read();
♦异常处理
throws IOException;
♦关闭资源(节约资源,提高效率)
reader.close();
代码学习
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
* @author: @橘子先森
* @create: 2020-11-11 10:17
**/
public class Test {
public static void main(String[] args) throws IOException {
//需求:通过字符流读取数据,lib包下的1.txt文件,内容 abc
//1、创建字符流输入对象
Reader reader = new FileReader("lib/1.txt"); //抛出FileNotFoundException异常
//2、读取数据
/*int read1 = reader.read();
System.out.println(read1); //a-97
int read2 = reader.read();
System.out.println(read2); //a-98
int read3 = reader.read();
System.out.println(read3); //a-99
int read4 = reader.read();
System.out.println(read4); //读取不到数据 -1*/
/*
优化,循环
因为不知道次数,所以用while循环
*/
int read; //ASCII码值,整数
while ((read = reader.read()) != -1) {
System.out.println(read); //97 98 99
}
//3、释放资源
reader.close(); //抛出IOException异常,FileNotFoundException异常属于OException异常所以可以不写
}
}
2、字符流读数据——按字符数组读取
♦创建字符流读文件对象
Reader reader = new FileReader("readme.txt");
♦调用方法读取数据(读取字符到数组中,返回读取的 有效 字符数,若达到流的末尾,返回 -1)
c har[] chs = new char[2048];
int len = r.read(chs);
♦异常处理
throws IOException;
♦关闭资源(节约资源,提高效率)
reader.close();
代码学习
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
* @author: @橘子先森
* @create: 2020-11-11 10:50
**/
public class Text {
public static void main(String[] args) throws IOException {
//需求:通过字符流读取数据,一次读取一个字符数组,lib包下的2.txt文件 qwertyuiop
//1、创建字符输入流对象
Reader reader = new FileReader("lib/2.txt");
//2、读取数据
//定义数组,初始长度3
/*char[] chs = new char[3];
int len1 = reader.read(chs);
System.out.println(chs); //q,w,e
System.out.println(len1); //3
int len2 = reader.read(chs);
System.out.println(chs); //r,t,y
System.out.println(len2); //3
int len3 = reader.read(chs);
System.out.println(chs); //u,i,o
System.out.println(len3); //3
int len4 = reader.read(chs);
System.out.println(chs); //p,i,o 因为读取数组是覆盖,只有 g 有效覆盖了上一数组的 u
System.out.println(len4); //1
int len5 = reader.read(chs);
System.out.println(chs); //p,i,o 没有读取到
System.out.println(len5); // -1*/
/*
优化,while循环
*/
//定义数组
char[] chs = new char[3];
//定义一个变量,记录读取有效字符长度
int len;
while ((len = reader.read(chs)) != -1) {
/*
chs: 表示要操作的数组
0: 表示起始索引
len: 表示要操作的字符个数
*/
//将读取到的内容,转换成字符串打印
//String s1 = new String(chs); //qwe rty uio pio
String s = new String(chs,0,len); //qwe rty uio p
System.out.println(s);
}
//3、释放资源
reader.close();
}
}
3、字符流写数据(三种)——按单个字符写入
♦创建字符流写文件对象(Writer是抽象类,需用其子类)
Writer writer = new FileWriter("dest.txt");
♦调用方法写入数据
int a = '中'; //因为字符的底层是一个整数
writer.write(a);
♦异常处理
throws IOException;
♦关闭资源
writer.close();
4、字符流写数据——按字符数组写入
♦创建字符流写文件对象(Writer是抽象类,需用其子类)
Writer writer = new FileWriter("dest.txt");
♦调用方法写入数据
char[] chs ={'橘','子','先','森'}
writer.write(chs);
♦异常处理
throws IOException;
♦关闭资源
writer.close();
5、字符流写数据——按字符串写入
♦创建字符流写文件对象(Writer是抽象类,需用其子类)
Writer writer = new FileWriter("dest.txt");
♦调用方法写入数据
writer.write("橘子先森");
♦异常处理
throws IOException;
♦关闭资源
writer.close();
字符流写数据代码学习
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
/**
* @author: @橘子先森
* @create: 2020-11-11 12:05
**/
public class WriterDemo {
public static void main(String[] args) throws IOException {
//通过字符流写数据
//1、创建字符输出流对象
Writer writer = new FileWriter("lib/1.txt");
//2、写数据 (覆盖)
//2.1一次写一个字符
//writer.write('嗨');
//2.2一次写一个指定字符数组
//char[] chs = {'橘','子','先','森','啊'};
//writer.write(chs);
//writer.write(chs,2,3); //先森啊
//2.3一次写一个字符串
writer.write("好好学习,天天向上");
//3、释放资源
writer.close();
}
}
6、字符流拷贝文件(Reader和Writer同时使用)——按单个字符读写
♦创建字符流读文件对象(Reader是抽象类,需用其子类)
Reader reader = new FileReader("readme.txt");
♦创建字符流写文件对象(Writer是抽象类,需用其子类)
Writer writer = new FileWriter("dest.txt");
♦调用方法读取数据(读取一个字符,返回该字符代表的整数 a-97(ASCII码值),若达到流的末尾,返回 -1)
int data = reader.read();
♦调用方法写入数据
writer.write(data);
♦异常处理
throws IOException;
♦关闭资源
reader.close();
writer.close();
代码学习
import java.io.*;
/**
* @author: @橘子先森
* @create: 2020-11-11 14:07
**/
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
//需求:通过字符流拷贝文件,一次读写一个字符;将1.txt中的内容复制到2.txt文件中
//1、创建字符流读文件对象,字符输入流对象,关联数据源文件
//Reader reader = new FileReader("lib/1.txt");
FileReader reader = new FileReader("lib/1.txt");
//2、创建字符流写文件对象,字符输出流对象,关联目的地文件
//注意:如果目的地文件不存在,程序会自动创建
FileWriter writer = new FileWriter("lib/3.txt");
//3、调用方法读数据,定义变量记录读取到的内容
int len;
//4、循环读取,只要条件满足一直读取,并将读取到的内容赋值给变量
while ((len = reader.read()) != -1) {
//5、调用方法写数据,将读取到的数据写入到目的地文件中
writer.write(len);
}
//6、释放资源
reader.close();
writer.close();
}
}
7、字符流拷贝文件(Reader和Writer同时使用)——按字符数组读写
♦创建字符流读文件对象(Reader是抽象类,需用其子类)
Reader reader = new FileReader("readme.txt");
♦创建字符流写文件对象(Writer是抽象类,需用其子类)
Writer writer = new FileWriter("dest.txt");
♦调用方法读取数据
char[] chs = new char[2048]; //最好1024整数倍,计算机底层换算单位1024
♦调用方法写入数据
writer.write(chs,0,len);
♦异常处理
throws IOException;
♦关闭资源
reader.close();writer.close();
代码学习
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author: @橘子先森
* @create: 2020-11-11 15:08
**/
public class CopyFile2Demo {
public static void main(String[] args) throws IOException {
//需求:通过字符流拷贝文件,一次读写一个字符数组
//将1.txt文件内容复制到2.txt中
//1、创建字符输入流对象,关联源文件
FileReader fr = new FileReader("lib/1.txt");
//2、创建字符输出流对象,关联目的地文件
FileWriter fw = new FileWriter("lib/2.txt");
//3、定义变量记录读取到的内容
//定义一个字符数组
char[] chs = new char[1024]; //最好1024整数倍
//定义用来记录读取到的有效字符数
int len;
//4、循环读取,只要满足条件一直读取,并将读取到的内容复制给变量
while ((len = fr.read(chs)) != -1) {
//5、调用方法写数据,将读取到的文件写入到目的地文件中
fw.write(chs,0,len);
}
//6、释放资源
fr.close();
fw.close();
}
}
8、字符缓冲流拷贝文件的标准代码
(高效字符输入流,也叫缓冲字符输入流,自带缓冲区,大小为8192个字符,也就是16KB,只能拷贝 纯文本文件 )
成员方法:
readLine(); 一次读取一行数据并返回读取到的内容,读取不到返回null;
newLine();根据当前操作系统给出对应的换行符;
♦创建字符流读文件对象
BufferedReader br = new BufferedReader(new FileReader("readme.txt"));
♦创建字符流写文件对象
BufferedWriter bw = new BufferedWriter(new FileWriter("dest.txt"));
♦异常处理
throws IOException;
♦使用while循环读取数据
int len;
while ((len = br.read()) != -1) {
bw.write(len);
}
♦关闭资源
br.close();
bw.close();
代码学习
import java.io.*;
/**
* @author: @橘子先森
* @create: 2020-11-11 17:48
**/
public class CopyFile3Demo {
public static void main(String[] args) throws IOException {
//需求:通过字符缓冲流流拷贝文件
//将1.txt文件内容复制到2.txt中
//1、创建字符输入流对象,关联源文件
FileReader fr = new FileReader("lib/1.txt");
BufferedReader br = new BufferedReader(fr);
//2、创建字符输出流对象,关联目的地文件
BufferedWriter bw = new BufferedWriter(new FileWriter("lib/2.txt")); //简化
//3、定义变量记录读取到的内容
int len;
//4、循环读取,只要满足条件一直读取,并将读取到的内容复制给变量
while ((len = br.read()) != -1) {
//5、调用方法写数据,将读取到的文件写入到目的地文件中
bw.write(len);
}
//6、释放资源
fr.close();
br.close();
bw.close();
}
}
五、字节流读写文件
1、字节流拷贝文件——按单个字节读写
♦创建字节流读文件对象
InputStream is = new FileInputStream("Desktop.jpg");
♦创建字节流写文件对象
OutputStream os = new FileOutoutStream("D:\\a.jpg");
♦异常处理
throw IOException;
♦使用while循环读写数据
int b;
while ((b = is.read()) != -1) {
os.write(b);
}
♦关闭资源
is.close();
os.close();
代码学习
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author: @橘子先森
* @create: 2020-11-11 21:31
**/
public class CopyFile5Demo {
public static void main(String[] args) throws IOException {
//需求:通过普通字节流,一次读写一个字节的方式,将a.jpg 复制到 b.jpg 中
//1、创建字节输入流,关联数据源文件
FileInputStream fis = new FileInputStream("lib/a.jpg");
//2、创建字节输出流,关联目的地文件
FileOutputStream fos = new FileOutputStream("lib/b.jpg");
//3、定义变量,用来记录读取到的内容
int len;
//4、循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
while ((len = fis.read()) != -1) {
//5、将读取到的内容写入到目的地文件中
fos.write(len);
}
//6、释放内存
fis.close();
fos.close();
}
}
2、字节流拷贝文件——按字节数组读写
♦创建字节流读文件对象
InputStream is = new FileInputStream("Desktop.jpg");
♦创建字节流写文件对象
OutputStream os = new FileOutoutStream("D:\\a.jpg");
♦异常处理
throw IOException;
♦定义一个字节数组,每次读取2048个字节
byte[] b = new byte[2048];
♦使用while循环读写数据
int len;
while ((len = is.read(b)) != -1) {
os.write(b,0,len);
}
♦关闭资源
is.close();
os.close();
代码学习
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author: @橘子先森
* @create: 2020-11-11 21:31
**/
public class CopyFile6Demo {
public static void main(String[] args) throws IOException {
//需求:通过普通字节流,一次读写一个字节数组的方式,将a.jpg 复制到 b.jpg 中
//1、创建字节输入流,关联数据源文件
FileInputStream fis = new FileInputStream("lib/a.jpg");
//2、创建字节输出流,关联目的地文件
FileOutputStream fos = new FileOutputStream("lib/b.jpg");
//3、定义变量,用来记录读取到的内容
byte[] bys = new byte[2048];
//用来记录读取到的有效字节数
int len;
//4、循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
while ((len = fis.read()) != -1) {
//5、将读取到的内容写入到目的地文件中
fos.write(bys,0,len);
}
//6、释放内存
fis.close();
fos.close();
}
}
3、字节缓冲流拷贝文件的标准代码
♦创建字节流读文件对象
InputStream is = new FileInputStream("Desktop.jpg");
♦创建字节流写文件对象
OutputStream os = new FileOutoutStream("D:\\a.jpg");
♦异常处理
throw IOException;
♦定义一个字节数组,每次读取2048个字节
byte[] b = new byte[2048];
♦使用while循环读写数据
int len;
while ((len = is.read(b)) != -1) {
os.write(b,0,len);
}
♦关闭资源
is.close();
os.close();
代码学习
package demo1;
import java.io.*;
/**
* @author: @橘子先森
* @create: 2020-11-11 21:31
**/
public class CopyFile7Demo {
public static void main(String[] args) throws IOException {
//需求:通过字节缓冲流,将a.jpg 复制到 b.jpg 中
//1、创建字节输入流,关联数据源文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("lib/a.jpg"));
//2、创建字节输出流,关联目的地文件
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("lib/b.jpg"));
//3、定义变量,用来记录读取到的内容
//用来记录读取到的有效字节数
int len;
//4、循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
while ((len = bis.read()) != -1) {
//5、将读取到的内容写入到目的地文件中
bos.write(len);
}
//6、释放内存
bis.close();
bos.close();
}
}