我们对文件进行读写,要以内存为参照物
输出: 如果把内存中的数据保存在硬盘上
输入: 如果把硬盘中的数据读入到内存中
文件读写的相关类:InputStream和OutputStream,这两个类都是抽象类无法直接使用,该流也可以称为字节流
要使用其子类:FileInputStream和FileOutputStream
继承关系:
1.FileOutputStream
示例代码:
1.创建流对象,如果给构造方法的第二个参数指定true表示允许拼接数据
2.将要写入的字符串转换为字符数组,写入到硬盘
写数据到硬盘上:
public class TestWrite {
public static void main(String[] args) throws Exception {
//创建流对象,如果给构造方法的第二个参数指定true表示允许拼接数据
// FileOutputStream fos = new FileOutputStream(new File("d:\\world.txt"),true);
//以上代码可以简写为,即使文件不存在,也会自动创建该文件
FileOutputStream fos = new FileOutputStream("d:\\world2.txt",true);
//准备数据
String s = "下午好";
//把字符串变为字节数组
byte[] bytes = s.getBytes();
//把数据写入硬盘
fos.write(bytes);
//关闭资源
fos.close();
}
}
2.FileInputStream
继承关系
从文件读取内容到硬盘上
如何读取文件
public class TestRead {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\world.txt");
int r = 0;
while(-1 != (r = fis.read())) {
//返回一个int类型的数据,如果返回-1表示读取完毕
System.out.print((char)r);
}
fis.close();
}
}
3.字节流复制文件
此方法性能特别差,每次一个字节一个字节进行读取写入
//如何复制任意文件
public class TestCopy1 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\w.jpg");
FileOutputStream fos = new FileOutputStream("c:\\w.jpg");
int r = 0;
while(-1 != (r = fis.read())) {
fos.write(r);
}
//先开的后关闭
fos.close();
fis.close();
}
}
科普单位转换知识:
文件的单位,文件最小的单位是字节
1024字节=1kb
1024kb = 1mb
1024mb = 1G
1024g = 1T
快速复制任意文件:(面试常问)
将每次需要读写的内容保存在字节数组中,每次读取字节数组的内容,会大大加快复制速率,效果最佳!缓冲流的内部也是通过数组进行保存数据,所以此方法效率最高
如何快速复制任意文件
public class TestCopy3 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\javatool.zip");
FileOutputStream fos = new FileOutputStream("c:\\javatool.zip");
byte[] buf = new byte[1024];
int len = 0;
while(-1 != (len = fis.read(buf))) {
fos.write(buf, 0, len);
}
fos.close();
fis.close();
}
}
4.缓冲流
我们把和流打交道的流称为过滤流
我们把和文件直接打交道的流称为节点流
继承关系
缓冲流进行复制操作,内部也是字节数组的形式,所以直接定义字节数组存放元素效率最高,缓冲字节输入流与缓冲字节输出流内部还要进行和数组的相互转化,所以效率略低
带缓冲的字节流
public class TestCopy4 {
public static void main(String[] args) throws Exception {
//我们把和流打交道的流称为过滤流
//我们把和文件直接打交道的流称为节点流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:\\javatool.zip"),1024);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("c:\\javatool.zip"),1024);
int i = 0;
while(-1 != (i = bis.read())){
bos.write(i);
}
bos.close();//当关闭过滤流时,其相关的流会一并关闭
bis.close();
}
}
5.解决乱码问题
编码表
- 1.ASCII(美国标准信息交换码)只能存储英文字符 a->97 A->65
- 2.ISO-8859-1编码,不仅包含了英文字符,还包含了拉丁字符
- 3.GB2312编码只包含了简体字
- 4.GBK既包含了简体字又包含了繁体字
- 5.Unicode编码,包含了650多个国家的文字
- 6.utf-8,Unicode的压缩版
英文字符占1个字节
汉字如果在gbk编码下,占2个字节,如果在utf-8的编码下占3个字节
windows系统默认使用的是GBK编码,所以一个汉字占2个字节,如果一次性读取2个字节,就不乱码了
每次读取两个字节,就不会出现乱码,模拟字符流:
public class TestRead {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\world.txt");
byte[] buf = new byte[2];
int len = 0;
while(-1 != (len = fis.read(buf))) {
String s = new String(buf, 0, len);
System.out.println(s);
}
fis.close();
}
}
6.IO中的异常处理
处理异常的步骤:
- 1.删除throws Exception
- 2.选中除了关闭资源的代码,使用surround with try…catch
- 3.给提取出的变量赋值为null
- 4.合并异常
- 5.异常转换
- 6.添加finally块,并把关闭资源的代码放到该块中
- 7.对关闭的对象进行非空判断
- 8.对关闭资源进行异常处理
示例代码:
public class TestCopy1 {
public static void main(String[] args) {
//处理异常的步骤
//1.删除throws Exception
//2.选中除了关闭资源的代码,使用surround with try...catch
//3.给提取出的变量赋值为null
//4.合并异常
//5.异常转换
//6.添加finally块,并把关闭资源的代码放到该块中
//7.对关闭的对象进行非空判断
//8.对关闭资源进行异常处理
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("d:\\w.jpg");
fos = new FileOutputStream("c:\\w.jpg");
int r = 0;
while(-1 != (r = fis.read())) {
fos.write(r);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
try {
if(null != fos) {
fos.close();
}
if(null != fis) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
Io字节流就介绍这么多了,对字节流其他方法操作还不太熟练的小可爱们,可以看看官方API文档
记得点赞+关注👉:
本人github地址:https://github.com/Lmobject