JAVA IO 学习笔记
IO简介
Java IO 体系看起来类很多,感觉很复杂,但其实是 IO 涉及的因素太多了。在设计 IO 相关的类时,编写者也不是从同一个方面考虑的,所以会给人一种很乱的感觉,并且还有设计模式的使用,更加难以使用这些 IO 类,所以特地对 Java 的 IO 做一个总结。
IO 类设计出来,肯定是为了解决 IO 相关的操作的,想一想哪里会有 IO 操作?网络、磁盘。网络操作相关的类是在 java.net 包下,不在本文的总结范围内。提到磁盘,你可能会想到文件,文件操作在 IO 中是比较典型的操作。在 Java 中引入了 “流” 的概念,它表示任何有能力产生数据源或有能力接收数据源的对象。数据源可以想象成水源,海水、河水、湖水、一杯水等等。数据传输可以想象为水的运输,古代有用桶运水,用竹管运水的,现在有钢管运水,不同的运输方式对应不同的运输特性。
流的分类:
节点流:程序直接连接到实际的数据源,进行读写。 FileInputStream直接连接到文件,节点流。
处理流:又称高级流或包装流,处理流对一个已存在的流进行连接,通过封装后的流来进行读写。
BufferedInputStream这就是处理流或者包装流,对原始流进行包装: 具备缓冲功能。普通水管节点流,热水器的水管就是对原始的水管进行包装: 出来的热水。
Java使用处理流来包装节点流是一种典型的装饰器设计模式。
流的总体结构图:
File类
File是描述文件的一个工具类,磁盘上的所有文件和目录都被抽象为文件;在新IO体系中目录单独有一个Path接口描述。它的实现类是Paths,提供静态方法获取Path对象。看一下File类的常用方法:
构造方法:
File(File parent, String child) Creates a new File instance from a parent abstract pathname and a child pathname string. |
---|
File(String pathname) Creates a new File instance by converting the given pathname string into an abstract pathname. |
File(String parent, String child) Creates a new File instance from a parent pathname string and a child pathname string. |
File(URI uri) Creates a new File instance by converting the given file: URI into an abstract pathname. |
package javaIO;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Path;
public class DemoFile {
public static void main(String[] args) {
test1();
test2();
test3();
test4();
test5();
}
private static void test5() {
// 递归列举目录内容
// 查看磁盘的根目录,总空间,已用空间,剩余空间
// 文件重命名
File aa = new File("aa.txt");
aa.renameTo(new File("迪丽热巴.txt"));
// 转成Path
File dir = new File("aaa");
Path path = dir.toPath();
System.out.println("路径名称:" + path.getFileName());
int count = path.getNameCount();
System.out.println("文件数量:" + count);
}
private static void test4() {
// 列举目录内容
File dir = new File(".");// .表示当前目录。
String files[] = dir.list();
for (String file : files) {
System.out.println(file);
}
// 文件名称过滤器:FilenameFilter
/*
* boolean accept(File dir, String name)测试指定文件是否应包含在文件列表中。 参数 dir - 找到该文件的目录。
* name - 文件的名称。 结果 true当且仅当该名称应包含在文件列表中时; false否则。
*/
//new FilenameFilter() {}是自定义类的对象。
String[] txts = dir.list(new FilenameFilter() {
// dir表示操作的路径,这里是当前目录,name所有的文件名和目录名
public boolean accept(File dir, String name) {
// dir的绝对路径输出行数与dir.list()文件名个数相等。因为dir.list()的原因,list()方法把文件和目录一一列举了。
System.out.println("dir====" + dir.getAbsolutePath());
// name.endsWith(".txt")如果是文本文件返回true如果不是返回false
// 过滤的结果是返回true的文件名
return name.endsWith(".txt");// 返回的匹配的文件名
}
});
for (String txt : txts) {
System.out.println("所有的txt文件:" + txt);
}
}
private static void test3() {
// 创建目录
File dir = new File("aaa");
boolean result = dir.mkdir();
System.out.println("创建一级目录:" + result);
dir = new File("xx/yy/zz");
result = dir.mkdirs();
System.out.println("创建多级目录:" + result);
// 删除目录:注意如果是多级目录就删除最底层的
result = dir.delete();
System.out.println("删除目录:" + result);
}
private static void test2() {
// 删除文件也可以加上判断文件是否存在
File file = new File("president.obj");
if (file.exists()) {
boolean result = file.delete();
System.out.println("文件删除结果:" + result);
} else {
System.out.println(file.getAbsolutePath() + "文件不存在...");
}
}
private static void test1() {
// 最好用相对路径,开发在Windows服务器和Linux上。
File file = new File("aaa.txt");
// 路径可以用/或者\\
// File file =new File("E:/eclipse-workspace/javaIO/src/javaIO/aaa.txt");
// 访问文件的基本属性
String fileName = file.getName();
String path = file.getAbsolutePath();
String path2 = file.getPath();
long fileLength = file.length();
boolean exists = file.exists();
boolean isFile = file.isFile();
boolean isDir = file.isDirectory();
System.out.println("文件名称:" + fileName + "\n相对路径:" + path2 + "\n绝对路径:" + path + "\n文件大小:" + fileLength
+ "\n是否存在:" + exists + "\n是否文件:" + isFile + "\n是否目录:" + isDir);
// 创建文件,可以执行程序,却刷新目录发现不了新创建的文件,就需要调用file.createNewFile()方法了。
try {
// 如果文件不存在才创建文件
if (!file.exists()) {
boolean result = file.createNewFile();
System.out.println("文件创建结果:" + result);// false因为文件已经存在
} else {
System.out.println(file.getName() + "已经存在,创建失败.");
}
} catch (IOException e) {
e.printStackTrace();
}
// 创建文件也可以指定路径
File file2 = new File("E:\\eclipse-workspace\\JavaIO.txt");
String file2Name = file2.getName();
System.out.println("创建的第二个文件名称:" + file2Name);// 没有创建成功,却依然执行程序无误。
}
}
字节流
package javaIO;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class DemoStream {
// 处理异常:1.自己处理:try-catch-finally 2.自己不能处理,抛出给上级,如果还是不能解决,继续向上级抛出。
// main方法是最顶层的,再向上级抛,就抛给虚拟机。
public static void main(String[] args) throws FileNotFoundException, IOException {
test4();
/*
* try { test4(); } catch (FileNotFoundException e) { e.printStackTrace(); }
* catch (IOException e) { e.printStackTrace(); }
*/
}
private static void test4() throws FileNotFoundException, IOException {
//文件复制:边读取文件边写入文件
FileInputStream fis = new FileInputStream("note.txt");
FileOutputStream fos = new FileOutputStream("迪丽热巴.txt");
int len = 0;
byte[] b = new byte[1024];
while ((len = fis.read(b)) != -1) {
fos.write(b, 0, len);
}
// 最后打开的,最先关闭,通常是这样的原则。
fos.close();
fis.close();
}
private static void test3() {
File file = new File("迪丽热巴.txt");
FileOutputStream fos = null;
try {
// FileOutputStream(File file,boolean append)表示追加模式,否则会覆盖文件已有数据。
fos = new FileOutputStream(file);
fos.write("新疆妹子迪丽热巴".getBytes());
fos.write("今年28岁。".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//fos!=null 判断创建对象fos不为空,与写数据没有关系,如果为空,就会空指针异常报错。
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void test2() {
// 首先明确一点是什么时候读取结束:读取到的数据长度是-1
FileInputStream fis = null;
try {
fis = new FileInputStream("note.txt");
byte[] b = new byte[1024];
int len = 0;
// 第一步: len =fis.read(b) 读取数据并返回长度
// 第一步:len != -1 和-1比较
while ((len = fis.read(b)) != -1) {
// println第一次循环之后会换行,不会和原来内容换行一样。
System.out.print(new String(b, 0, len));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void test1() {
FileInputStream fis = null;
try {
// 基于当前文件创建输入流
fis = new FileInputStream(new File("note.txt"));// 建立管道
byte[] b = new byte[1024];// 蓄水池,洗碗池
// len是读取到的数据长度,水杯接水:500ML
int len = fis.read(b);// 读取到字节数组,数组是个容器
System.out.println("读取到的数据:" + new String(b, 0, len));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符流
package javaIO;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class DemoStream2 {
public static void main(String []args)throws Exception{
//以带缓冲的字符流实现文件复制:节点流---直接连接文件
FileReader reader =new FileReader("note.txt");
FileWriter writer =new FileWriter("hehe.txt");
//包装流--连接节点流的
BufferedReader br =new BufferedReader(reader);
BufferedWriter bw =new BufferedWriter(writer);
String line=null;
while(br.ready()) {
line=br.readLine();//读取一行
bw.write(line);//写一行字符
bw.newLine();//写一个换行符,到文件。而sout换行符是到控制台,不一个目的地。
}
bw.close();
br.close();
}
}