1. IO流
1.1 IO流简介
I 是 input,表示输入。o 是output,表示输出。流指的就是数据的传输。
Java IO 的字面意思:通过 java 编程语言实现数据的输入和输出。在这里指的就是文件的读和写操作。
那么,关于读,数据从哪里来?关于写,数据写到那里去?
读:将数据从硬盘加载到内存中,例如通过 java 程序查看 txt 文档。
写:将数据从内存写入到硬盘中,例如通过 java 程序给 txt 文档添加几个字符。
所以呢,读写操作就是数据在内存和硬盘之间的传输。
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 字节输出流
//创建字节输出流的类
FileOutputStream(String pathName)
复制代码
字节输出流使用步骤:
- 创建字节输出流对象,参数是输出到硬盘的位置。
- 调用写数据的方法
- 释放资源(切记)
下面讲解字节输出流常用方法:
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 字节输入流
//创建字节输入流的类
FileInputStream(String pathName)
复制代码
字节输入流使用步骤:
- 创建字节输入流对象
- 调用读数据的方法
- 释放资源(切记)
下面讲解字节输入流常用的方法:
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(String pathName)
复制代码
字符输出流使用步骤:
- 创建字符输出流对象
- 调用写数据的方法
- 释放资源(切记)
//创建字符输出流,将数据写入到指定位置的文件里面
FileWriter fileWriter = new FileWriter(new File("D:\\eclipse\\hello.txt"));
//写入数据
fileWriter.write("禾下乘凉梦一定会实现!");
//释放资源
fileWriter.close();
复制代码
执行结果:
4.2 字符输入流
//创建字符输入流的类
FileReader(String pathName)
复制代码
字符输入流使用步骤:
- 创建字符输入流对象
- 调用写数据的方法
- 释放资源(切记)
//创建字符输入流
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();
复制代码
5. Properties介绍
Properties介绍:
- Properties 是一个 Map 体系的集合类
- Properties 可以保存/加载数据
- Properties 属性列表中的键值对都是一个字符串
1)Map集合
Properties properties = new Properties();
properties.setProperty("name", "jay");
properties.setProperty("age", "18");
Set<String> keys = properties.stringPropertyNames();
for (String key : keys) {
System.out.println(key);
String value = properties.getProperty(key);
System.out.println(key + "," + value);
}
复制代码
执行结果:
2)从数据流中加载数据
Properties prop = new Properties();
FileReader fileReader = new FileReader("D:\\resources\\jdbc.properties");
prop.load(fileReader);
System.out.println(prop);
System.out.println(prop.getProperty("username"));
System.out.println(prop.getProperty("password"));
System.out.println(prop.getProperty("driver"));
fileReader.close();
复制代码
执行结果:
6. 对象序列化&&反序列化
6.1 对象序列化
对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象。
对象序列化流: ObjectOutputStream
注意:一个对象要想被序列化,该对象所属的类必须实现 Serializable 接口
下面是对象序列化的示例代码:
用户类:
public class User implements Serializable {
private String username;
private int age;
public User(String username, int age) {
this.username = username;
this.age = age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
复制代码
序列化方法:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\resources\\user.txt"));
//创建对象
User user = new User("zhangsan",12);
//将指定的对象写入ObjectOutputStream
oos.writeObject(user);
//释放资源
oos.close();
复制代码
6.2 对象反序列化
对象反序列化:就是将文件转化为对象。说白了就是读数据,然后再转化为对象。
对象反序列化流: ObjectInputStream
示例代码:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\resources\\user.txt"));
//Object readObject():从ObjectInputStream读取一个对象
Object object = ois.readObject();
User user = (User) object;
System.out.println(user.getUsername() + "," + user.getAge());
//释放资源
ois.close();
复制代码
执行结果:
微信公众号:eclipse编程。专注于编程技术分享,坚持终身学习。