Java IO有这么难吗?
1. IO流
1.1 IO流简介
I 是 input,表示输入。o 是output,表示输出。流指的就是数据的传输。
Java IO 的字面意思:通过 java 编程语言实现数据的输入和输出。在这里指的就是文件的读和写操作。
那么,关于读,数据从哪里来?关于写,数据写到那里去?
读:将数据从硬盘加载到内存中,例如通过 java 程序查看 txt 文档。
写:将数据从内存写入到硬盘中,例如通过 java 程序给 txt 文档添加几个字符。
所以呢,读写操作就是数据在内存和硬盘之间的传输。
作者:一颗雷布斯
链接:https://juejin.cn/post/6965667083648499726
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1.2 IO流分类
1)按照数据的流向
输入流:其实就是文件的读操作
输出流:其实就是文件的写操作
2)按照数据的传输类型
1.3 IO流的常用场景
文件上传
文件下载
复制文件
注意:如果我们操作的是图片、视频等二进制文件,优先使用字节流。如果操作的是文本文件,优先使用字符流。如果不知道文件的类型,优先使用字节流。
2. 文件操作:File类
无论是文件的读操作还是文件的写操作归根结底都是和文件打交道,所以呢在学习 java io 之前我们要先学习如何处理文件。
File 类是 java 中处理文件的核心类,这里讲解其中一些常见的方法。
1)创建文件
//我要在D盘eclipse目录下创建一个hello.txt的文件
File file = new File(“D:\eclipse\hello.txt”);
//创建文件
file.createNewFile();
2)创建文件夹
//在D盘eclipse文件夹下创建一个名为idea的文件夹
File file = new File(“D:\eclipse\idea”);
//创建文件夹
file.mkdir();
3)创建多级文件夹
//在D盘eclipse文件夹下创建多级文件夹:\hello1\hello2
File file = new File(“D:\eclipse\hello1\hello2”);
//创建文件夹
file.mkdirs();
4)判断该路径下是不是文件?
File file = new File(“D:\eclipse\hello.txt”);
//判断该路径下是不是文件?
file.isFile();//true
5)判断该路径下是不是文件夹?
File file = new File(“D:\eclipse\hello”);
//判断该路径下是不是文件夹?
file.isDirectory();//true
6)判断该路径下的文件或者文件夹是否存在?
File file = new File(“D:\eclipse\hello.txt”);
//判断该路径下的文件或者文件夹是否存在?
System.out.println(file.exists());
7)删除文件/文件夹
File file = new File(“D:\eclipse\hello.txt”);
//删除文件或者文件夹
file.delete();
3. 字节流
3.1 字节输出流
字节输出流使用步骤:
- 创建字节输出流对象,参数是输出到硬盘的位置。
- 调用写数据的方法
- 释放资源(切记)
下面讲解字节输出流常用方法:
1)一次写一个字节数据 write(int byte)
//创建字节输出流对象,将数据写入到指定文件里面
FileOutputStream outputStream = new FileOutputStream(“D:\eclipse\hello.txt”);
//一次写入一个字节的数据,97代表 a
outputStream.write(97);
//释放资源
outputStream.close();
执行结果:
2)一次写一个字节数组数据 write(byte[] bytes)
//创建字节输出流对象,将数据写入到指定文件里面
FileOutputStream outputStream = new FileOutputStream(“D:\eclipse\hello.txt”);
//一次写入一个字节数组的数据
String str=“helloworld”
byte[] bytes = str.getBytes();
outputStream.write(bytes);
//释放资源
outputStream.close();
执行结果:
3)根据指定长度写字节数组的长度 write(byte[] bytes, int from, int len)
//创建字节输出流对象,将数据写入到指定文件里面
FileOutputStream outputStream = new FileOutputStream(“D:\eclipse\hello.txt”);
//写入指定长度的字节数组的数据
String str=“helloworld”
byte[] bytes = str.getBytes();
//只要前两个字节
outputStream.write(bytes,0,2);
//释放资源
outputStream.close();
执行结果:
4)写入数据换行处理
不同操作系统的处理方式:
- windows系统:\r\n
- linux系统:\n
- mac系统:\r
这里以windows系统为例:
//创建字节输出流对象,将数据写入到指定文件里面
FileOutputStream outputStream = new FileOutputStream(“D:\eclipse\hello.txt”);
String str=“hello”;
byte[] bytes = str.getBytes();
//遍历字节数组的数据
for (byte b : bytes) {
outputStream.write(b);
//换行
outputStream.write("\r\n".getBytes());
}
//释放资源
outputStream.close();
执行结果:
3.2 字节输入流
字节输入流使用步骤:
- 创建字节输入流对象
- 调用读数据的方法
- 释放资源(切记)
下面讲解字节输入流常用的方法:
1)一次读一个字节的数据
//创建字节输入流对象,获取指定位置的文件
FileInputStream inputStream = new FileInputStream(“D:\eclipse\hello.txt”);
int charStr ;
//inputStream.read() 读数据
//charStr = inputStream.read() 将读到的数据赋值给charStr
//charStr != -1 判断读取到的数据是否为空
while (( charStr = inputStream.read())!=-1){
System.out.print((char)charStr);
}
//释放资源
inputStream.close();
执行结果:
2)一次读一个字节数组的数据
//创建字节输入流对象,获取指定位置的文件
FileInputStream inputStream = new FileInputStream(“D:\eclipse\hello.txt”);
int charStr ;
byte[] bys = new byte[1024];
//inputStream.read(bys) 一次读一个字节数组的数据
//charStr = inputStream.read(bys) 将读到的数据赋值给charStr
//charStr != -1 判断读取到的数据是否为空
while (( charStr = inputStream.read(bys))!=-1){
System.out.print(new String(bys,0,charStr));
}
//释放资源
inputStream.close();
执行结果:
3.3 字节流应用:复制文件
思考:想一下,你要复制文件你是不是得知道这个文件在哪里?拿到这个文件后是不是要先读取文件的内容?读的同时再把文件的内容写入到另一个文件里?
步骤:
- 创建字节输入流对象,读文件内容
- 创建字节输出流对象,写文件内容
- 一边读一边写
- 释放资源(切记)
//创建字节输入流对象,我从哪个文件复制?就是文件初始地
FileInputStream fileFrom = new FileInputStream(“D:\eclipse\hello.txt”);
//创建字节输出流对象,我要复制到哪个文件里面?就是文件目的地
FileOutputStream fileTo = new FileOutputStream(“D:\eclipse\world.txt”);
//读写数据,(一次读取一个字节数组,一次写入一个字节数组)
byte[] bytes = new byte[1024];
int len;
while ((len=fileFrom.read(bytes))!=-1) {
fileTo.write(bytes,0,len);
}
//释放资源
fileFrom.close();
fileTo.close();
执行结果: 多了个world.txt文件,并且里面的内容和hello.txt内容一样
3.4 字节缓冲流
3.4.1 缓冲流介绍
就是当我们读取数据量特别大的文件时,读取的速度会超级慢,非常影响我们的心情。所以呢Java为我们提高了一套缓冲流机制,它可以大大的提高文件的读写速率。
3.4.2 字节缓冲流
-
BufferedOutputStream:字节缓冲输出流
-
BufferedInputStream:字节缓冲输入流
它们的内部有一个缓冲区,通过缓冲区读写,大大提高IO流的读写速度。
1)字节缓冲输出流
FileOutputStream fos=new FileOutputStream(“D:\eclipse\hello.txt”);
//字节缓冲输出流
BufferedOutputStream bos=new BufferedOutputStream(fos);
//写数据 98表示b
fos.write(98);
//释放资源
bos.close();
2)字节缓冲输入流
FileInputStream fis=new FileInputStream(“D:\eclipse\hello.txt”);
//创建字节缓冲输入流
BufferedInputStream bis=new BufferedInputStream(fis);
int len;
while((len=bis.read())!=-1){
System.out.println((char)len);
}
//释放资源
bis.close();
3)使用字节缓冲流复制大文件
//我要复制的文件来自哪里?
FileInputStream fis=new FileInputStream(“D:\eclipse\oracle.zip”);
//创建字节输入缓冲流
BufferedInputStream bis=new BufferedInputStream(fis);
//我要复制到哪里去?
FileOutputStream fos=new FileOutputStream(“D:\eclipse\idea.zip”);
//创建字节输出缓冲流
BufferedOutputStream bos=new BufferedOutputStream(fos);
int len=0;
byte[] ch=new byte[1024];
//复制文件 边读边写
while((len=bis.read(ch))!=-1){
bos.write(ch,0,len);
}
//释放资源
bos.close();
bis.close();
4. 字符流
在说起字符流之前先说一下编码与解码。
编码:GBK、UTF-8等,你就把它理解为一种数据格式,数据可以从一个格式转换为另一种格式。
乱码:编码与解码不一致,就会导致乱码。例如一个文档你用 UTF-8 编码,但是用 GBK 解码,就会出现字符与码值不匹配的情况,从而导致乱码。如下所示:
String tips=“我爱你中国”;
//使用指定的字符集将该String编码为字节数据
byte[] bys = tips.getBytes(“GBK”);
//通过指定的字符集解码指定的字节数组来创建字符串
String ss = new String(bys,“UTF-8”);
System.out.println(":"+ss);
执行结果:
因为使用字节流操作字符时,可能会因为中文字符导致乱码的情况,所以java就提供了字符流。
字符流:在字节流的基础上加上编码(GBK、UTF-8等),形成新的数据流。字符流 = 字节流 + 编码
字符流与字节流的区别:字节流支持声音、视频、图片、文本等所有文件类型,而字符流只支持文本文件。
4.1 字符输出流
字符输出流使用步骤:
- 创建字符输出流对象
- 调用写数据的方法
- 释放资源(切记)
//创建字符输出流,将数据写入到指定位置的文件里面
FileWriter fileWriter = new FileWriter(new File(“D:\eclipse\hello.txt”));
//写入数据
fileWriter.write(“禾下乘凉梦一定会实现!”);
//释放资源
fileWriter.close();
执行结果:
4.2 字符输入流
字符输入流使用步骤:
- 创建字符输入流对象
- 调用写数据的方法
- 释放资源(切记)
//创建字符输入流
FileReader fileReader = new FileReader(new File(“D:\eclipse\hello.txt”));
char[] bytes = new char[1024];
int len;
//读取数据
while ((len = fileReader.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
//释放资源
fileReader.close();
执行结果:
4.3 字符缓冲流
字符缓冲流:如果一个文件里面的字符太多,文件太大,可以用它来提高效率。
- BufferedReader:字符缓冲输入流
- BufferedWriter:字符缓冲输出流
1)字符缓冲输出流
//创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter(“D:\eclipse\haha.txt”));
bw.write(“我爱你中国”);
//自动换行方法,会自适应不同的操作系统
bw.newLine();
bw.write(“哈哈哈哈哈”);
//释放资源
bw.close();
执行结果:
2)字符缓冲输入流
//创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader(“D:\eclipse\other.txt”));
//读取文件
String value;
//每次读一行数据,以字符串形式返回这一行的数据
while ((value = br.readLine()) != null) {
System.out.println(value);
}
br.close();
执行结果:
3)字符缓冲流复制文件
BufferedWriter bw=new BufferedWriter(new FileWriter(“D:\eclipse\student.txt”));
BufferedReader br=new BufferedReader(new FileReader(“D:\eclipse\teacher.txt”));
String value="";
while((value=br.readLine())!=null) {
bw.write(value);
bw.newLine();
}
bw.close();
br.close();
4.4 转换流
- InputStreamReader: 将字节输入流转换成字符输入流
- OutputStreamWriter:将字节输出流转换成字符输出流
1)字节输入流转换成字符输入流
InputStreamReader isr = new InputStreamReader(new
FileInputStream(“D:\eclipse\haha.txt”),“GBK”);
//一次读取一个字符数据
int str;
while ((str=isr.read())!=-1) {
System.out.print((char)str);
}
isr.close();
2)字节输出流转换成字符输出流
OutputStreamWriter osw = new OutputStreamWriter(new
FileOutputStream(“D:\eclipse\haha.txt”),“GBK”);
osw.write(“中国加油”);
osw.close();