什么是流?流可以理解为一系列的数据。在实际应用中分为输入流InputStream 和输出流OutputSteam。
文件输入流:将数据从磁盘上的文件读取到JVM中来;
文件输出流:将程序中的数据写到磁盘上的文件中去。
流下面对应两种不同的形式,分别是 字节流和字符流。
字节流
以 字节 的形式进行进行读取和写入数据,一切都是以二进制数字保存。对ASCII 码来说,一个字节对应8位,共128种组合 。例如65对应大写 A ,97对应小写 a 。下面一段代码运用字节流,通过 FileInputStream和 FileOutputStream (分别为 InputStream和 OutputStream的子类),将一个文本的内容复制到另外一个文本中:
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建文件对象f1,该文件存在且有内容
File f1 = new File("src/package_file/file_1");
//声明输入流
FileInputStream fis = null;
//接收输入流fis进来的字符
byte[] all = {};
try {
//创建文件输入流对象fis,用来得到文件f1的内容
fis = new FileInputStream(f1);
//all根据文件的大小开辟空间
all = new byte[(int)f1.length()];
//将输入流fis中的数据传入数组all中
fis.read(all);
}catch(IOException e) {
e.printStackTrace();
}finally {
//关闭输入流
if(fis != null) {
try {
fis.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
//创建文件对象f1,该文件不存在
File f3 = new File("src/package_file/file_3");
//定义输出流
FileOutputStream fos = null;
try {
//创建文件输出流对象fos,用来将数据输出给文件f3
fos = new FileOutputStream(f3);
//将all数组写入fos
fos.write(all);
}catch(IOException e) {
e.printStackTrace();
}finally {
//关闭输出流
if(fos != null) {
try {
fos.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
}
上面的代码通过文件输入流 FileInputStream,和文件输出流FileOutput Stream,实现了将文件f1的内容读取到JVM(内存)中,并将程序中的内容写到磁盘上文件的操作。
注意:所有的流,无论是输入流还是输出流,在使用完毕之后,都要关闭,不然会造成资源的浪费。
那么为什么要在finally中关闭字节流呢?如果在try中关闭会怎么样?如果在try中close字节流,那么有可能在前面就出现异常,导致最后面的close操作无法执行,因此很可能会造成资源的浪费。因此选择在finally 中进行字节流的关闭。
字符流
对于中文等一些特殊符号来说,字节流无法对其进行传输。因为一个汉子占用的字节数不止一个,因此Java中还支持以字符为单位传输的字符流。其中字符输入流为 Reader,字符输出流为 Writer。常用的子类文件字符输入流为 FileReader,文件字符输出流为 FileWriter,专门用于以字符的形式来读取写入数据。
与上面功能相仿的代码如下:
public static void main(String[] args) {
// TODO Auto-generated method stub
File f = new File("src/package_file/file_1");
char[] all = {};
try {
FileReader fr = new FileReader(f);
all = new char[(int)f.length()];
fr.read(all);
fr.close();
}catch(Exception e) {
e.printStackTrace();
}
for(char x: all)
{
System.out.println(x);
}
File f2 = new File("src/package_file/file_4");
try {
FileWriter fw = new FileWriter(f2);
fw.write(all);
fw.close();
}catch(Exception e) {
e.printStackTrace();
}
}
可见代码和之前使用字节流的代码有些相似。值得一提的是,使用字符流可以对中文进行传输,而字节流如果传输中文,会出现乱码的情况。