一篇快速理解JavaIO流
节点流
在这里讲一讲直接操作文件的节点流。
抽象基类 | 节点流(文件流) |
InputStream | FileInputStream |
outputStream | FileOutputStream |
Reader | FileReader |
Writer | FileWriter |
前置知识:java中IO流File类
FileInputStream 和FileOutputStream 分别是字节输入流和字节输出流,一般用来处理非文本文件(.jpg,.mp4,.mp3,.abi,.doc,.ppt,…)
FileReader 和 FileWriter 分别是字符输入流和字符输出流,更多的是用来处理文本文件(.txt,.java,.c,.cpp)的数据。
下面首先来介绍一下字符输入输出流来处理文本数据。
FileReader
在我的工程下有一个helloworld.txt
的文件并且里面写了内容。用流去读文件之前要确保文件存在。
对相对路径(文件位置)很迷的小伙伴可以用System.out.println(file.getAbsolutePath());
来查看一下这个文件的绝对路径。
@Test
public void FileReader() throws IOException {
//实例化File对象,指明要操作的文件
File file = new File("helloworld.txt");//相较于当前module
//提供具体的流
FileReader fr = new FileReader(file);
//数据的读入
//read():返回读入的一个字符,如果到达文件末尾则返回-1
int data;
while((data = fr.read()) != -1){
System.out.print((char)data);
}
//流的关闭操作
fr.close();
}
注:一定要注意流的关闭,JVM垃圾回收机制对于物理连接,如数据库连接,输入输出流,Socket连接,无能为力。
为了保证流资源一定能执行关闭操作,使用try-catch-finally处理。
@Test
public void FileReader(){
FileReader fr = null;
try {
//实例化File对象,指明要操作的文件
File file = new File("helloworld.txt");//相较于当前module
System.out.println(file.getAbsolutePath());
//提供具体的流
fr = new FileReader(file);
//数据的读入
//read():返回读入的一个字符,如果到达文件末尾则返回-1
int data;
while((data = fr.read()) != -1){
System.out.print((char)data);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//流的关闭操作
if(fr != null) fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
read()方法操作升级,不再一个一个字符的读取,一次读入char[](多个)。在数据量大的情况下,这种方法效率明显更高。
代码如下:
@Test
public void FileReader1(){
FileReader fr = null;
try {
//实例化File对象,指明要操作的文件
File file = new File("helloworld.txt");//相较于当前module
System.out.println(file.getAbsolutePath());
//提供具体的流
fr = new FileReader(file);
//数据的读入
//read(char[] cbuf):返回每次读入到数组中的字符个数。如果达到文件末尾,返回-1.
int data;
char[] buffer = new char[1024];
while((data = fr.read(buffer)) != -1){
//取数据的时候注意,这里是data,不是buffer.length。原因嘛,自然是读多少个就取多少个,取多了自然就错了。
System.out.println(new String(buffer,0,data));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//流的关闭操作
if(fr != null) fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileWriter
- 输出的操作,对应的File可以不存在。
如果不存在,输出的过程中会创建此文件。
如果存在,FileWriter fw = new FileWriter(file,true);
true表示追加,如果不写true则默认false,默认对文件的覆盖。
@Test
public void FileWriter() {
FileWriter fw = null;
try {
//提供File对象,指明写入到的文件。
File file = new File("hello1.txt");
//提供FileWriter对象,用于数据的写出。
fw = new FileWriter(file,true);
//写入数据
//write参数的数据类型多样,可以自己去看看源码,很多重载方法。
fw.write("I hava a dream \n".toCharArray());
fw.write("你呢");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//流的关闭
if (fw != null) fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileInputStream & FileOutputStream
字符流更多的是用来处理文本文件(.txt,.java,.c,.cpp)的数据,如果用来处理非文本文件(.jpg,.mp4,.mp3,.abi,.doc,.ppt,…)的话就会出错,这个时候就需要字节流来处理了。同样的使用字节流去处理文本文件,也很容易出现乱码的现象。
下面用一个例子演示一下节点流中的字节流:
eg:把D:/团圆照.jpg (已经存在),这张d盘下的团圆照图片,复制(write)到F盘下,命名为:合家欢喜.jpg(还不存在):
@Test
public void FileInputStreamTest(){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
//提供file对象
File file1 = new File("D:\\团圆照.jpg");
File file2 = new File("F:\\合家欢喜.jpg");
//创建字节输入输出流
fileInputStream = new FileInputStream(file1);
fileOutputStream = new FileOutputStream(file2);
//复制的过程
int len;
byte[] data = new byte[1024];
while((len = fileInputStream.read(data)) != -1){
fileOutputStream.write(data,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//流的关闭
try {
if(fileInputStream != null) fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fileOutputStream != null) fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}