1.文件流
Java中,文件的输入和输出是通过流(Stream)来实现的。流按照处理数据的单位,可以分为字节流和字符流。字节流的处理单位是字节,通常用来处理二进制文件,例如音乐、图片文件等。而字符流的处理单位是字符,通常用来处理文本文件。
2.文件流的继承关系
字节流:以输入流(InputStream)、输出流(OutputStream)为基类,所有的字节流类都直接或间接继承InputStream或OutputStream 这两个抽象类,如直接继承InputStream的有:FileInputStream、ByteArrayInputStream、ObjectInputStream、PipeInputStream、SequenceInputStream;字节缓冲流BufferedInputStream,BufferedOutputStream分别间接继承nputStream或OutputStream。
字符流:以字符输入流(Reader)、字符输出流(Writer)为基类,所有的字符流类都都直接或间接继承Reader或 Writer 这两个抽象类,其中Reader是用于读取字符流的抽象类,Writer是用于写入字符流的抽象类。如:FileReader、CharArrayReader、PipedReader、StringReader。字符缓冲流BufferedReader和BufferedWriter间接继承Reader或 Writer。
3.文件读写的基本流程
步骤1.使用File类;
步骤2.使用字节流或者字符流的子类;
步骤3.进行读/写操作;
步骤4.关闭输入/输出。
如:
InputStream in = null;
// 1.使用File类
File f = new File("F:\\Temp\\1.txt");
int totalLen = 0;
try {
// 2.指定字节流
in = new FileInputStream(f);
// 临时的字节数组,每次最多读取1024字节
byte[] b = new byte[1024];
// 实际每次读取的字节数
int temp = 0;
// 3.进行读操作
while ((temp = in.read(b)) != -1) {
totalLen = totalLen + temp;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("字节读取文件:" + totalLen);
4.Demo演示
文件简单拷贝(分别以字节流,字符流,字节缓冲流,字符缓冲流实现文件拷贝)。
package com.yx.filedemo;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
/**
* FileReadWrite
*
* @author yx
* @date 2019/12/7 10:40
*/
public class CopyFile {
public static void main(String[] args) {
copyFile1("F:\\Temp\\a.txt", "F:\\Temp2\\1.txt");
copyFile2("F:\\Temp\\a.txt", "F:\\Temp2\\2.txt");
copyFile3("F:\\Temp\\a.txt", "F:\\Temp2\\3.txt");
copyFile4("F:\\Temp\\a.txt", "F:\\Temp2\\4.txt");
}
/**
* 以字节流方式实现文件的拷贝
*
* @param src 源文件
* @param dest 目标文件
*/
private static void copyFile1(String src, String dest) {
InputStream in = null;
OutputStream out = null;
// 1.使用File类
File fa = new File(src);
if (!fa.exists() || !fa.isFile()) {
return;
}
File fb = new File(dest);
if (fb.getParentFile() != null && !fb.getParentFile().exists()) {
fb.getParentFile().mkdirs();
}
int totalLen = 0;
try {
// 2.指定字节流
in = new FileInputStream(fa);
out = new FileOutputStream(fb);
// 临时的字节数组,每次最多读取1024字节,可适当修改加快读写性能
byte[] b = new byte[1024];
// 实际每次读取的字节数
int temp = 0;
// 3.进行读操作
while ((temp = in.read(b)) != -1) {
totalLen = totalLen + temp;
out.write(b, 0, temp);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("以字节流方式实现文件的拷贝,拷贝字节数:" + totalLen);
}
/**
* 以字符流方式实现文件的拷贝
*
* @param src 源文件
* @param dest 目标文件
*/
private static void copyFile2(String src, String dest) {
Reader reader = null;
Writer writer = null;
// 1.使用File类
File fa = new File(src);
File fb = new File(dest);
if (!fa.exists() || !fa.isFile()) {
return;
}
if (fb.getParentFile() != null && !fb.getParentFile().exists()) {
fb.getParentFile().mkdirs();
}
try {
// 2.指定字节流
reader = new FileReader(fa);
writer = new FileWriter(fb);
char[] chars = new char[50];
int i;
// 3.进行读写操作
while ((i = reader.read(chars)) != -1) {
writer.write(chars, 0, i);
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("以字符流方式实现文件的拷贝");
}
/**
* 以字节缓冲流实现文件的拷贝
*
* @param src 源文件
* @param dest 目标文件
*/
private static void copyFile3(String src, String dest) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
// 1.使用File类
File fa = new File(src);
if (!fa.exists() || !fa.isFile()) {
return;
}
File fb = new File(dest);
if (fb.getParentFile() != null && !fb.getParentFile().exists()) {
fb.getParentFile().mkdirs();
}
int totalLen = 0;
try {
// 2.指定字节流
bis = new BufferedInputStream(new FileInputStream(fa));
bos = new BufferedOutputStream(new FileOutputStream(fb));
// 临时的字节数组,每次最多读取1024字节,可适当修改加快读写性能
byte[] b = new byte[1024];
// 实际每次读取的字节数
int temp = 0;
// 3.进行读操作
while ((temp = bis.read(b)) != -1) {
totalLen = totalLen + temp;
bos.write(b, 0, temp);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("以字节缓冲流实现文件的拷贝:" + totalLen);
}
/**
* 以字符缓冲流方式实现文件的拷贝
*
* @param src 源文件
* @param dest 目标文件
*/
private static void copyFile4(String src, String dest) {
BufferedReader reader = null;
BufferedWriter writer = null;
// 1.使用File类
File fa = new File(src);
File fb = new File(dest);
if (!fa.exists() || !fa.isFile()) {
return;
}
if (fb.getParentFile() != null && !fb.getParentFile().exists()) {
fb.getParentFile().mkdirs();
}
try {
// 2.指定字节流
reader = new BufferedReader(new FileReader(fa));
writer = new BufferedWriter(new FileWriter(fb));
char[] chars = new char[50];
int i;
// 3.进行读写操作
while ((i = reader.read(chars)) != -1) {
writer.write(chars, 0, i);
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("以字符缓冲流方式实现文件的拷贝");
}
}
代码示例中虽然使用字符流进行文件拷贝,实际中推荐使用字节流进行文件拷贝,因为字符流对二进制字节文件拷贝会有问题。
5.小结
a.字节流的处理单位是字节,通常用来处理二进制文件,而字符流的处理单位是字符,通常用来处理文本文件。
b.不管是字节流还是字符流处理文件操作后,及时关闭打开的流。
c.推荐使用缓冲流对文件进行操作。