流的概念
流(stream)将字节数据读写,抽象成数据在管道中流动。从头到尾顺序流动。流是单向的,流动过去的数据,不能重复流动。
输入流,只能用来读取。
输出流,只能用来输出。
InputSream/OutputStream
java.io.InputSream/OutputStream 是字节流的抽象父类,是各种输入输出字节流的基类,所有字节流都继承这两个基类
方法
OutputStream
write(int b)
write(byte[] buff)
write(byte[] buff,int from,int length)
flush()//刷出缓存数据
InputStream
read()//读1个字节补3个0
read(byte[] buff)
available()//获得剩余的可读取的字节量
FileInputStream/FileOutputStream
直接与文件相接,直接读取文件数据。我们上一章学的 RandomAccessFile 能读取文件任意位置,而流不能,只能顺序访问。
FileInputStream 可以以字节流的形式读取文件内容。FileInputStream 是 InputStream 的子类,这意味着你可以把 FileInputStream 当做 InputStream 使用(FileInputStream 与 InputStream 的行为类似)。
创建对象
FileOutputStream out = new FileOutputStream(文件)
文件可以是字符串和 File 对象。不论文件是否存在,都会创建空文件。
FileOutputStream out = new FileOutputStream(文件,true)
文件不存在,新建;文件已经存在,追加
栗子1:输出
/*
*文件不存在会新建
*目录不存在会出现异常
*/
FileOutputStream out = new FileOutputStream("d:/abc/f3");
out.write(97);
out.write(98);
out.write(99);
byte[] buff = {
100, 101, 102, 103, 104,
105, 106, 107, 108, 109
};
out.write(buff);
out.write(buff, 5, 4);
运行程序,如果 D 盘下没有 abc 文件夹会报错:
创建 abc 文件夹后重新运行程序,D 盘下 abc 文件夹内会新建 f3 文件,内容为:
栗子2:读取
FileInputStream in;
in = new FileInputStream("d:/abc/f3");
//单字节读取
int b;
while ((b = in.read()) != -1) {
System.out.println(b);
}
in.close();
in = new FileInputStream("d:/abc/f3");
//批量读取
byte[] buff = new byte[5];
int n;
while ((n = in.read(buff)) != -1) {
System.out.println(n + "-" + Arrays.toString(buff));
}
in.close();
运行结果:
栗子3:复制文件
public class Main {
public static void main(String[] args) {
System.out.println("请输入文件路径");
String s = new Scanner(System.in).nextLine();
File from = new File(s);
if (!from.isFile()) {
System.out.println("请输入正确的文件路径");
return;
}
System.out.println("请输入目标文件路径");
String s2 = new Scanner(System.in).nextLine();
File to = new File(s2);
if (to.isDirectory()) {
System.out.println("不是目录路径,是目标文件路径");
return;
}
try {
copy(from, to);
System.out.println("复制成功");
} catch (Exception e) {
System.out.println("复制失败");
e.printStackTrace();
}
}
private static void copy(File from, File to) throws IOException {
FileInputStream in = new FileInputStream(from);
FileOutputStream out = new FileOutputStream(to);
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
in.close();
out.close();
}
}
运行结果
请输入文件路径
d:/abc/headimg.jpg
请输入目标文件路径
d:/abc/copy.jpg
复制成功
刚才的栗子是单字节读取,如果复制大文件是很慢的,现在改成批量读取,其他代码不变,修改 copy 方法:
private static void copy(File from, File to) throws IOException {
FileInputStream in = new FileInputStream(from);
FileOutputStream out = new FileOutputStream(to);
byte[] buff = new byte[8192];
int n;
while ((n = in.read(buff)) != -1) {
out.write(buff, 0, n);
}
in.close();
out.close();
}
Java 提供的 FileInputStream 类适合于读取二进制文件,而不太适合读取文本文件。当然也可以读取文本文件,不过需要做相应地读取处理,否则遇到中文就会出现乱码。