一、介绍
- IO 的发展历程
java.io 包早在 JDK 1.0 就已推出,其中经历过几个版本分别为 BIO ( block io,jdk1.0 ) 阻塞IO、NIO ( non-block io,jdk1.5 ) 非阻塞IO、AIO ( asynchronou io,jdk1.7 ) 异步 IO 或 叫 NIO2。
- IO 的结构体系
从大类来说 IO 分为 字符流 和 字节流 ,从方向来说分别为 输入流 和 输出流,下面又分了有种类,最常用的有:文件流、缓冲流等。
在整个 java.io 包中最重要的就是5个类和一个接口。5个类指的是File、OutputStream、InputStream、Writer、Reader;一个接口指的是Serializable,掌握了这些IO的核心操作那么对于Java中的IO体系也就有了一个初步的认识了
- 什么时候用字符流?什么时候用字节流 ?
字节流是一个万能流,什么文件都能读取,字符流只能读纯文本的文件,但是为了提高性能,纯文本文件选择字符流,非纯文本文件选择字节流。
二、IO 常用类的使用例子
可以先去看看常用类的使用方法
- 文件类(File)
用于获得操作系统文件和对文件相应的操作
运用递归获取指定目录所有文件
public static void main(String[] args) throws IOException {
String pathfile = "D:"+File.separator+"demo";
File file = new File(pathfile);
file(file);
}
public static void file(File file) throws IOException {
//1.判断文件
if(!file.exists()){
throw new FileNotFoundException("文件不存在");
}
File[] files = file.listFiles();
for (File f : files) {
if (f.isDirectory()){
file(f);
}else {
System.out.println(f);
}
}
}
上面这段代码会输出所有文件路径,看着好像有点累,想整个父子对应关系的数据,优化一下
先定义一下父子对应关系的类:点击查看类
private static List<Tree> list = new ArrayList<>();//用来存放数据
private static long id = 0;//因为测试使用,当初主键id来用
public static void file(String filepath,long parentid) throws FileNotFoundException {
File file = new File(filepath);
//1.判断文件
if(!file.exists()){
throw new FileNotFoundException("文件不存在");
}
//2.是文件该怎么执行
if(file.isFile()){
String name = file.getName();
String path = file.getAbsolutePath();
Tree tree = new Tree(id++,name,path,parentid);
list.add(tree);
return ;
}
//3.获取文件夹路径下面的所有文件递归调用;
if(file.isDirectory()){
String name = file.getName();
String path = file.getAbsolutePath();
Tree tree = new Tree(id++,name,path,parentid);
list.add(tree);
String[] list = file.list();
for (int i = 0;i<list.length;i++){
String s = list[i];
String newFilePath = path+File.separator+s;//根据当前文件夹,拼接其下文文件形成新的路径
file(newFilePath,tree.getId());
}
}
}
public static void main(String[] args) {
String filepath="D:"+File.separator+"demo";//默认路径,扫描此文件夹下面的所有文件
int parentid = 0; //初始化父节点id
try {
file(filepath,parentid);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
for (int i = 0; i < list.size(); i++) {
Tree tree = list.get(i);
System.out.println("id:"+tree.getId()+" parentId:"+tree.getPid()+"=="+tree.getName());
}
}
这个函数有三个很重要部分:两个静态参数(list、id)、文件路径、父id(和id是对应的,id是没有重复的,每次都是 i++ 操作)
id:0 parentId:0==demo
id:1 parentId:0==demo1.txt
id:2 parentId:0==test
id:3 parentId:2==demo.txt
id:4 parentId:2==import.txt
Process finished with exit code 0
但我们还想要一个树形结构的数据,我们转换一下,可以看我写的这篇:转换树形
--demo
--demo1.txt
--test
--demo.txt
--import.txt
Process finished with exit code 0
读取文件之后,我们还想要输入输出里面的东西,io 包下有输出输入流
- 输入输出流(InputStream、OutputStream)
InputStream、OutputStream 都是抽像类而我们要用的是它的实现类文件输入输出流(FileInputStream、FileOutputStream)
FileInputStream 类有三个构造用来读取文件,常用的有两个
//可接受一个 String 类型的路径
public FileInputStream(String name) throws FileNotFoundException
// 可接受一个 文件类
public FileInputStream(File file) throws FileNotFoundException
FileOutputStream 类有五个构造用来读取文件,常用的有四个
//可接收一个String类型的路径
public FileOutputStream(String name) throws FileNotFoundException
//可接收一个String类型的路径和一个是否可追加的布尔类型,true代表追加,false代表覆盖
public FileOutputStream(String name, boolean append) throws FileNotFoundException
//可接收一个文件对象
public FileOutputStream(File file) throws FileNotFoundException
//可接收一个文件对象和一个是否可追加的布尔类型,true代表追加,false代表覆盖
public FileOutputStream(File file, boolean append) throws FileNotFoundException
下面讲一个读取和写入的例子
public static void demo1(){
String pathfile = "D:"+File.separator+"demo"+File.separator+"test"+File.separator+"demo.txt";
File file = new File(pathfile);
try {
if (file.exists()){
InputStream fis = new FileInputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes)) > 0){
System.out.println(new String(bytes));
}
}else {
file.createNewFile();
OutputStream fos = new FileOutputStream(file);
fos.write(new String("这是一个纯文本文件").getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
逻辑很简单就是先构造一个文件,文件存在输出文件里面的内容,不存在则创建文件,再写入内容。
再看一个例子:复制字节码
public static void copyBytes(String from,String to) throws IOException {
FileInputStream inputStream = null;
FileOutputStream outputStream = null;
try {
inputStream = new FileInputStream(from);
outputStream = new FileOutputStream(to);
byte[] b = new byte[1024];
int i = -1;
while ((i = inputStream.read(b)) != -1){
outputStream.write(b);
}
}finally {
if (inputStream != null){
inputStream.close();
}
if (outputStream != null){
outputStream.close();
}
}
}
- Writer、Reader
用法和字节流差不多
public static void copyCharacters(String from,String to) throws IOException{
Reader reader = null;
Writer writer = null;
try {
reader = new FileReader(from);
writer = new FileWriter(to);
char[] c = new char[50];
int i = -1;
while ((i = reader.read(c)) != -1){
System.out.println(c);
writer.write(c);
}
}finally {
if (reader != null){
reader.close();
}
if (writer != null){
writer.close();
}
}
}
- 序列化(Serializable)
序列化是一个空接口,或者说它是一个标识,实现了 Serializable 接口的类就可以序列化,序列化指读写硬盘操作。