何为IO?
首先,我们看看百度给出的解释。
I/O输入/输出(Input/Output),分为IO设备和IO接口两个部分。
i是写入,Input的首字母。o是输出,Output的首字母。
IO分类
IO流主要分为两大类,字节流和字符流。而按照作用分类,可以分为输入流和输出流。
流?
我们可以将这个整个看成一个水池。水池里面连接了出水口管与注水管。出水相当于我们的输出流。注水相当于我们的输入流。
File(文件类)
首先我们如果需要用IO流的话,我们肯定是需要创建一个我们所谓的**“水池”**的。
怎么创建呢?我们直接创建一个File类对象。
package IoDemo;
import java.io.*;
public class IoDemo {
public static void main(String[] args) {
//创建File对象
File file = new File("D:\\test.txt");
}
}
实际上这个对象,说白了就是用来储存一个IO流的文件地址的。
创建了对象后,它也没有任何什么操作,操作得使用这个对象调用方法。
我们先使用createNewFile()
方法创建我们上面那个路径的文件。
file.createNewFile();
注意定义文件路径时,可以用“/”或者“\”。
并且在创建一个文件时,如果目录下有同名文件将被覆盖。
因为有时候,可能我们的路径下已经存在了相对应的同名文件,所以我们要使用exists()
方法判断文件是否已经存在。
//创建File对象
File file = new File("D:\\test.txt");
//创建文件
try {
//判断文件是否存在
if(!file.exists()){
file.createNewFile();
}
} catch (IOException e) {
e.printStackTrace();
}
其实,File类里面还存在许多方法,用法都是可以直接调用的,作为一个合格的程序员,我们可以直接阅读相关说明而在合适的时候使用对应方法。
下面列举一些常用方法。
字节流的使用
我们现在已经建好这个**“水池”了,同时还可以使用方法来获取到“水池”**的一些信息。
那接下来,我们可以试着创建一套流。
字节流,相当于一滴滴的水在一个管道里运输。这个管道我们可以抽象的称之为流。
我们还是先看看知乎上,某些大佬的解释。
大佬的解释
对于不完全学透的看法
听起来有些难度哈,这些高级用法我们先不管。我们先来看看它到底怎么用的。
OutputStream(字节输出流)
!!!这里的输出可不是我们正常的输出,它反而想法,是将字节写入到文件,可以理解为将字节输出到文件。
看看里面有些啥常用方法。
我们先演示一下,字节输出流如何使用?
//定义一个String值
String str = "Hello World";
等下我们利用字节流将这个String写入我们的文件里面。
等等!这里是字节流,我怎么可以直接写入**String
**?
//将String值转换成字节数组
byte[] bytes = str.getBytes();
整个代码是这样的:
package IoDemo;
import java.io.*;
public class IoDemo {
public static void main(String[] args) {
//创建File对象
File file = new File("D:\\test.txt");
//创建文件
try {
//判断文件是否存在
if(!file.exists()){
file.createNewFile();
}
} catch (IOException e) {
e.printStackTrace();
}
//定义一个String值
String str = "Hello World";
//创建字节流
FileOutputStream fos = null;
try {
//将File对象(即地址)给到FileInputStream
fos = new FileOutputStream(file);
//将String值转换成字节数组
byte[] bytes = str.getBytes();
//循环将字节数组写入到文件中
for (int i = 0; i < bytes.length; i++) {
//将bytes写入文件
fos.write(bytes[i]);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
我们进我们的文件看看输出效果。
就已经写入了我们的String里面的内容了。
InputStream(字节输入流)
//创建字节输入流
FileInputStream fis = null;
try {
//将File对象(即地址)给到FileInputStream
fis = new FileInputStream(file);
//创建字节数组
byte[] bytes = new byte[1024];
//输出字节数组
int len = 0;
while ((len = fis.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
在上文,我们已经写入了一个Hello Word
我们现在这段代码,我们将会输出文件中的内容。
len = fis.read(bytes)) != -1
我现在还是先讲解一下这一段。
而我们字节流呢,一般是用于读取二进制文件,如音频、图片这些,大片的文字内容还是交给字符流吧。
字符流的使用
上面的字节流,它是一个个的输出的,而我们现在的字符流,是大水管输出,一次可以运输一段。
FileWriter(字符输出流)
老规矩哈,方法自己看看。
先写入一个String
试试。
package IoDemo;
import java.io.*;
public class IoDemo {
public static void main(String[] args) {
String str = "嘿嘿!我是字符流·········";
//创建File对象
File file = new File("D:\\test.txt");
try {
//将str用writer写入文件
FileWriter fw = new FileWriter(file);
fw.write(str);
//关闭流,字符流必须关闭流才可以输出
fw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
写入效果如下:
实际上,写入字符串就几个步骤。
//1.将str用writer写入文件
FileWriter fw = new FileWriter(file);
//2.使用write()方法写入字符串
fw.write(str);
//3.关闭流,字符流必须关闭流才可以输出
fw.close();
FileReader(字符输出流)
//输出文件内容
try {
//创建输入字符流
FileReader fr = new FileReader(file);
//输出文件内容
int ch = 0;
while ((ch = fr.read()) != -1){
System.out.print((char)ch);
}
//关闭流
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
包装流
缓冲流
为什么使用缓冲流呢?
缓冲流,也叫高效流。 能够高效读写缓冲流,能够转换编码的转换流,能够持久化存储对象的序列化对象等等。 它是四个基本File流的增强,所以也是4个流,按照数据类型分类。 缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO读取次数,从而提高读写的效率。
package IoDemo;
import java.io.*;
public class IoDemo {
public static void main(String[] args) {
//创建File对象
File file = new File("D:\\test.txt");
//创建缓冲流
BufferedWriter bw = null;
try {
//创建FileWriter对象
FileWriter fw = new FileWriter(file);
//创建BufferedWriter对象
bw = new BufferedWriter(fw);
//写入一首诗分四次写入
bw.write("窗前明月光,");
bw.write("疑是地上霜。");
bw.write("举头望明月,");
bw.write("低头思故乡。");
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这个很简单,自己看就可以看懂。
转换流
我就不写示范了,网上找了一段。
//转换流实现将 a.txt 文件 复制到 b.txt 中
//1、创建源和目标
File srcFile = new File("io"+File.separator+"a.txt");
File descFile = new File("io"+File.separator+"b.txt");
//2、创建字节输入输出流对象
InputStream in = new FileInputStream(srcFile);
OutputStream out = new FileOutputStream(descFile);
//3、创建转换输入输出对象
Reader rd = new InputStreamReader(in);
Writer wt = new OutputStreamWriter(out);
//3、读取和写入操作
char[] buffer = new char[10];//创建一个容量为 10 的字符数组,存储已经读取的数据
int len = -1;//表示已经读取了多少个字符,如果是 -1,表示已经读取到文件的末尾
while((len=rd.read(buffer))!=-1){
wt.write(buffer, 0, len);
}
//4、关闭流资源
rd.close();
wt.close();
扩展
然后,找相关资料时,还涨了个知识。大家可以看看。
合并流
合并流:把多个输入流合并为一个流,也叫顺序流,因为在读取的时候是先读第一个,读完了在读下面一个流。
SequenceInputStream seinput = new SequenceInputStream();
new FileInputStream("io/1.txt"), new FileInputStream("io/2.txt"));
byte[] buffer = new byte[10];
int len = -1;
while((len=seinput.read(buffer))!=-1){
System.out.println(new String(buffer,0,len));
}
seinput.close();
这里先是创建了一个SequenceInputStream
对象,然后new
了两个FileInputStream
对象,我们使用合并流读取,先使用**seinput.read方法
**读取1.txt
的内容,然后再对其2.txt
的内容。