1)文笔有限,如果发现博客有书写有误的地方恳请读者直言不讳,我一定会第一时间改正。
2)代码的具体实现可以参考代码中的注释,如果由于注释不清楚而不明白相应原理,可以与作者私聊。码字不易,有兴趣的小伙伴点个赞呗,大家相互学习。
3)本篇博客为Java高级特性之 IO流,如需了解 Java 的其它部分,欢迎点击链接。
1 File类
1.1 定义
java .io.File 类是文件和文件目录路径的抽象表示形式,使得它们与平台无关。File 类可以新建、删除、重命名文件和目录,但 File 类不能访问文件内容本身,如果需要访问文件内容本身,则需要使用输入输出流。
1.2 路径分隔符
因为Java程序是支持跨平台运行的,然而对于不同的操作系统,路径分隔符是不同的,比如 windows 和 DOS 系统默认使用 “\” 来表示,而 UNIX 和 URL 使用 “/” 来表示,为了解决这个隐,,Java 为 File 类提供了一个常量(public static final String separator),它2可以根据操作系统动态地提供分隔符。
示例:
File file== new File(File(" d:"+ FIle.separator + " sharm"+ File.separator + "hello.java";
2 Java IO流的定义与体系
2.1 定义
I/O 是 Input/Output 的缩写, I/O 技术常用于处理设备之间的数据传输,如读、写文件以及网络通讯等。要注意的是,在Java 程序中,对于数据的输入以及输出操作是以“流 stream”的方式进行的。
2.2 IO流的分类
分类标准 | 类别一 | 类别二 |
---|---|---|
数据单位 | 字节流(8 bit,即通过0101……来传) | 字符流(16 bit,即通过char来传) |
数据的流向(输入与输出是相对的) | 输入流 | 输出流 |
流的角色 | 节点流(节点流指的就是两个流的对象直接相连的过程) | 处理流(处理流就是“套接”在已有的节点流的基础上的流) |
2.3 IO流的体系
从IO流的体系图中可以看到,IO流其实是非常的多的。但这并不意味着IO流的使用是麻烦的,实际上,IO流的使用其实是有一定的模板的,这一点可以在下面的FileReader中详解,比如read()表示读入、write()表示写出。
IO流代码的书写模板:
- 实例化File类的对象,指明要操作的文件。文件的位置可以使用右键获得;
- 提供具体的流;
- 数据的读入;
- 流的关闭操作。
3 节点流
抽象基类 | 节点流 | 缓冲流(处理流的一种) |
---|---|---|
InputStream | FileInputStream (read(byte[ ] buffer)) | BufferedInputStream (read(byte[ ] buffer)) |
OutputStream | FileOutputStream (write(byte[ ] buffer,0,len) | BufferedOutputStream (write(byte[ ] buffer,0,len) / flush() |
Reader | FileReader (read(char[ ] cbuf)) | BufferedReader (read(char[ ] cbuf) / readLine()) |
Writer | FileWriter (write(char[ ] cbuf,0,len) | BufferedWriter (write(char[ ] cbuf,0,len) / flush() |
其中,
- 对于文本文件(.txt,.java,.c,.cpp),使用字符流处理
- 对于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,…),使用字节流处理
- 实际工作中,因为缓冲流的处理速度会比节点流快,所以一般都会使用缓冲流来运行。
3.1 FileReader类、FileWriter类
接下来的内容在代码中说明会更显清晰,然后代码的需求和思路我都会注释在其中。
有一点要注意的是:像类似于流、socket这种物理连接,jvm的垃圾回收机制是不会起作用的,所以我们要手动关闭socket与流。
3.1.1 FileReader类
import org.junit.Test;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileReadWriterTest{
/*
需求:将test/resources下的helloworld.txt文档的文件内容读入到程序中,并输出到控制台
分析:
1)test/resources→硬盘 程序、控制台→内存
2)read()方法的理解:返回读入的一个字符。如果达到文件末尾,返回-1。
3)必须进行异常的处理,因为像流、socket这类物理连接,jvm的垃圾回收机制是不会起作用的,所以需要使用try-catch-finally处理。
4)读入的文件一定要存在,否则就会报FileNotFoundException。
*/
@Test
public void testFileReader(){
FileReader fr = null;
try {
//1.实例化File类的对象,指明要操作的文件。文件的位置可以使用右键获得。
File file = new File("src/test/resources/helloworld.txt");
//2.提供具体的流
fr = new FileReader(file);
//3.数据的读入
//方式一:不使用重载的方法
//因为字符串和int是可以相互转换的。
// int data;
// while((data = fr.read()) != -1){
// System.out.print((char)data);
//方法二:使用read重载的方法
char[] cbuf=new char[5];
int len;
//将fr流中的数据依次装入到cbuf数组中,装满了,看长度为5不等于-1,在等于3装入之后,再下一次就是-1了。但是3的时候数组中还是存放5个数
while((len = fr.read(cbuf)) != -1){
//正确的写法一
// for(int i = 0;i < len;i++){
// System.out.print(cbuf[i]);
// }
//正确的写法二
String str = new String(cbuf,0,len);//char数组到字符串的转换,用构造器。
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.流的关闭操作。因为如果在第二步出错的时候,文件读取都没有打开所以,要先判断其是否为null。
// try {
// if(fr != null)
// fr.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
//或
if(fr != null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3.1.2 FileWriter类
只不过之前用的是char数组,现在用的是byte数组。