目录
一、IO流概述
二、IO流的分类
三、字节输出流与字节输入流
(一)字节输出流——FileOutputStream
1.FileOutputStream书写步骤
2.FileOutputStream书写细节
3.FileOutputStream写数据的3种方式
4.FileOutputStream的换行和续写
(二)字节输入流——FileInputStream
1.FileInputStream书写步骤
2.FileInputStream书写细节
(三)文件拷贝
1.使用FileInputStream和FileOutputStream拷贝文件
2.文件拷贝的弊端
3.使用FileInputStream和FileOutputStream拷贝文件改进
4.异常捕获
5.实现了AutoClosable的类使用try-with-resourses
5.1JDK7的写法
5.2JDK9的写法
一、IO流概述
IO流:存储和读取数据的解决方案。
内存中的数据,不能永久化存储,程序停止,数据就会丢失。如果将数据保存在文件中,下一次打开文件就还能够获取数据。
File类表示系统中的文件或者文件夹的路径。利用File可以获取文件信息(大小、文件名、修改时间)、判断文件类型、创建文件/文件夹、删除文件/文件夹等。但是,File类只能对文件本身进行操作,不能读写文件里面存储的数据。
因此,想要读写文件中或网络中的数据,就必须使用IO流。
写出数据:又叫output,将数据保存到文件当中。
读取数据:又叫input,将数据从文件中加载到程序中。
因此,以程序(或内存)为参照物看读写的方向。
二、IO流的分类
IO流的简单分类:
(一)按照流向分类
输出流:程序——>文件
输入流:文件——>程序
(二)按照操作文件的类型
字节流:可以操作所有类型的文件
字符流:只能操作纯文本文件
纯文本文件的概念:用windows系统自带的记事本打开并且能读懂的文件(.txt、.md、.xml、.lrc等)
三、字节输出流与字节输入流
注意:以下文件的读写都是英文,暂时不考虑中文。
(一)字节输出流——FileOutputStream
操作本地文件的字节输出流,可以把程序中的数据写到本地文件中,是字节流的基本流。
1.FileOutputStream书写步骤
(1)创建字节输出流对象;
(2)将数据写到目标文件中;
(3)释放资源
public class ByteStreamDemo1 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("chapter18\\a.txt");
fos.write(97);
fos.close();
}
}
2.FileOutputStream书写细节
3.FileOutputStream写数据的3种方式
public class ByteStreamDemo2 {
public static void main(String[] args) throws IOException {
File file = new File("chapter18\\a.txt");
FileOutputStream fos = new FileOutputStream(file);
fos.write(97);
fos.write(98);
fos.write(10); // 10在ASCII码表中表示换行
byte[] bytes = {97, 32, 98, 99, 100, 101};
fos.write(bytes); // 32在ASCII码表中表示空格
fos.write(10);
// 要写出的数组,起始索引,写出的元素个数
fos.write(bytes, 1, 3);
fos.write(10);
fos.close();
}
}
a.txt文件内容:
4.FileOutputStream的换行和续写
换行写:
再次写出一个换行符就可以了
windows: \r\n或\n
Linux: \n
Mac: \r
续写:
如果想要续写,打开续写开关即可
开关位置:创建对象的第二个参数
默认false:表示关闭续写,此时创建对象会清空文件
手动传递true:表示打开续写,此时创建对象不会清空文件
public class ByteStreamDemo3 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("chapter18\\b.txt", true); // 打开续写
// 换行
String str = "zhangsan";
byte[] bytes1 = str.getBytes();
fos.write(bytes1);
String wrap = "\n";
byte[] bytes2 = wrap.getBytes();
fos.write(bytes2);
String str2 = "999";
byte[] bytes3 = str2.getBytes();
fos.write(bytes3);
fos.close();
}
}
b.txt文件
(二)字节输入流——FileInputStream
操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中。
1.FileInputStream书写步骤
(1)创建字节输入流对象
(2)读取数据
(3)释放资源
public class ByteStreamDemo1 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("chapter18\\b.txt");
int b1;
while ((b1 = fis.read()) != -1) {
System.out.print((char) b1);
}
fis.close();
}
}
b.txt文件:
读取结果:
2.FileInputStream书写细节
(三)文件拷贝
1.使用FileInputStream和FileOutputStream拷贝文件
public class ByteStreamDemo2 {
public static void main(String[] args) throws IOException {
// 1.创建对象
FileInputStream fis = new FileInputStream("D:\\test\\aaa\\movie.mp4");
FileOutputStream fos = new FileOutputStream("chapter18\\copy.mp4");
// 2.拷贝:边读边写
long start = System.currentTimeMillis();
int b;
while ((b = fis.read()) != -1) {
fos.write(b);
}
long end= System.currentTimeMillis();
System.out.println("拷贝时间:" + copyTime + "毫秒");
// 拷贝时间:104289毫秒
// 3.释放资源
// 规则:先开的最后关闭
fos.close();
fis.close();
}
}
2.文件拷贝的弊端
上面文件拷贝方式的弊端:一次读取一个字节,时间长,效率低。
改进办法:
一次读一个字节数组的数据,每次读取会尽可能把数组装满,数组长度一般是1024的整数倍。
文件拷贝代码示例:
public class ByteStreamDemo3 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("chapter18\\b.txt");
// b 代表的是实际读取的字节数
int b;
byte[] bytes = new byte[2];
while ((b = fis.read(bytes)) != -1) {
String str = new String(bytes, 0, b);
System.out.print(str);
}
fis.close();
}
}
运行结果:
3.使用FileInputStream和FileOutputStream拷贝文件改进
public class ByteStreamDemo4 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\test\\aaa\\movie.mp4");
FileOutputStream fos = new FileOutputStream("chapter18\\copy.mp4");
long start = System.currentTimeMillis();
int len;
byte[] bytes = new byte[1024 * 1024];
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
long end = System.currentTimeMillis();
long copyTime = end - start;
System.out.println("拷贝时间:" + copyTime + "毫秒");
// 拷贝时间:43毫秒
fos.close();
fis.close();
}
}
4.异常捕获
public class ByteStreamDemo4 {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("D:\\test\\aaa\\movie.mp4");
fos = new FileOutputStream("chapter18\\copy.mp4");
int len;
byte[] bytes = new byte[1024 * 1024];
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
5.实现了AutoClosable的类使用try-with-resourses
5.1JDK7的写法
只有实现了AutoCloseable的类才能在()中创建对象,表示整个try-catch执行完之后,()中的流就会自动释放资源。
public class ByteStreamDemo4 {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("D:\\test\\aaa\\movie.mp4");
FileOutputStream fos = new FileOutputStream("chapter18\\copy.mp4")) {
int len;
byte[] bytes = new byte[1024 * 1024];
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
5.2JDK9的写法
public class ByteStreamDemo4 {
public static void main(String[] args) throws FileNotFoundException {
FileInputStream fis = new FileInputStream("D:\\test\\aaa\\movie.mp4");
FileOutputStream fos = new FileOutputStream("chapter18\\copy.mp4");
try (fis; fos) {
int len;
byte[] bytes = new byte[1024 * 1024];
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}