目录
4、BufferedReader和BufferedWriter
5、BufferedInputStream和BufferedOutputStream
6、ObjectInputStream和ObjectOutputStream
7、InputStreamReader和OutputStreamWriter
一、文件
文件可以是doc、ecxel等,还可以是视频、音频......
1、文件流
文件在程序中是以流的形式,进行操作。
- 流:数据在数据源(文件)和程序(内存)之间经历的路程。
- 输入流:数据从数据源(文件)到程序(内存)的路径。
- 输出流:数据从程序(内存)到数据源(文件)的路径。
2、常见的文件操作
(1)创建文件
- new File(String pathname) //根据路径构建一个File对象
- new File(File parent, String child) //根据父目录文件+子路径构建
- new File(String parent, String child) //根据父目录+子路径构建
- createNewFile 创建新文件
import java.io.File;
import java.io.IOException;
public class FileCreat {
public static void main(String[] args) {
}
//方式1 new File(String pathname)
public void creat01(){
String filePath = "c:\\document.txt";
//这里的file对象,只是java中从一个对象,只有执行了createNewFile方法,才会在磁盘中创建该文件
File file = new File(filePath);
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
//方式2 new File(File parent, String child) //根据父目录文件+子路径构建
public void creat02(){
File parentFile = new File("e:\\");
String fileName = "news2.txt";
File file = new File(parentFile, fileName);
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
//方式3 new File(String parent, String child) //根据父目录+子路径构建
public void creat03(){
String parentPath = "e:\\";
String fileName = "news3.txt";
File file = new File(parentPath,fileName);
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(2)获取文件信息
下面列举了几个获取文件信息的方法:
import java.io.File;
public class FileInformation {
public static void main(String[] args) {
}
//获取文件信息
public void info() {
//先创建文件对象
File file = new File("c:\\document.txt");
//调用方法,得到对应的信息
System.out.println("文件名字=" + file.getName());
System.out.println("文件绝对路径=" + file.getAbsolutePath());
System.out.println("文件父级目录=" + file.getParent());
System.out.println("文件大小(字节)=" + file.length());
System.out.println("文件是否存在=" + file.exists());
System.out.println("是不是一个文件=" + file.isFile());
System.out.println("是不是一个目录=" + file.isDirectory());
}
}
(3)文件删除
下面给出三个案例:
需求1:判断文件是否存在,若存在则删除,否则提示不存在。
public void m1(){
String filePath = "d:\\document.txt";
File file = new File(filePath);
if (file.exists()){
if (file.delete()){
System.out.println("删除成功");
}else {
System.out.println("删除失败");
}
}else {
System.out.println("该文件不存在");
}
}
需求2:判断目录是否存在,若存在则删除,否则提示不存在(java中,目录被当作文件看待)。
public void m2(){
String filePath = "d:\\Android_learn";
File file = new File(filePath);
if (file.exists()){
if (file.delete()){
System.out.println("删除成功");
}else {
System.out.println("删除失败");
}
}else {
System.out.println("该目录不存在");
}
}
需求3:判断目录是否存在,若存在就提示已存在,否则就创建。
public void m3(){
String directoryPath = "d:\\Android_learn";
File file = new File(directoryPath);
if (file.exists()){
System.out.println("该目录存在");
}else {
if (file.mkdirs()){ //mkdirs就是make directories。mkdirs()是创建多级目录,mkdir()是创建一级目录。
System.out.println("创建成功");
}else {
System.out.println("创建失败");
}
}
}
二、IO流原理及分类
1、IO流原理
- I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。eg:读/写文件,网络通讯等。
- Java程序中,对于数据的输入/输出操作,以"流(stream)"的方式进行。
- Java.io包下提供了各种"流"类和接口,用以获取不同种类的数据,并通过方法输入or输出数据。
- 输入Input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
- 输出Output:将程序(内存)数据输出到磁盘、光盘等存储设备中。
Tips:上面提到的文件,也可以是网络、数据库等,因此I/O技术不只是用在文件相关的操作。
2、流的分类
- 按照操作数据单位不同,分为:字节流(一个字节是8bit)(用于操作二进制文件:声音、视频文件等,保证无损操作)、字符流(按字符)(用于操作文本文件)
- 按数据流的方向不同,分为:输入流、输出流。
- 按流的角色不同,分为:节点流、处理流/包装流。
字节流又分为字节输入流和字节输出流,字节输入流的顶级父类是InputStream,字节输出流的顶级父类是OutPutStream。以此类推。
下表中的4个类都是抽象类,使用时要创建实现子类。
Tips:(1)Java的IO流共涉及40多个类,都是从上表中4个抽象基类派生的;(2)由以上四个类派生出来的子类名称,都是以其父类名作为子类名的后缀。
3、流VS文件
通俗理解:流就是外卖小哥,文件就是物品。
三、IO流中常用的类
1、InputStream类
InputStream是字节输入流,它是抽象类,是所有字节输入流的超类。(Object类也叫做超类)
FileInputStream:文件字节输入流
BufferedInputStream:缓冲字节输入流
ObjectInputStream:对象字节输入流
下面介绍InputStream常用的子类:
(1)FileInputStream类
FileInputStream是字节输入流。即:文件 ---> 程序
FileInputStream类的构造器和方法:
下面演示一个案例,需求是:读取hello.txt文件中的内容,该文件中写的是hello,world。
//该方法是输出结果是:hello,world
public void readFile(){
String filePath = "d:\\hello.txt"; //hello.txt文件中写的内容是hello,world
int readContent = 0;
FileInputStream fileInputStream = null; //在这里定义FileInputStream对象,扩大它的作用域。
try {
//创建FileInputStream对象,用于读取文件
fileInputStream = new FileInputStream(filePath);
//从该输入流读取一个字节的数据。read()方法一次只读取一个字节。
while ((readContent = fileInputStream.read()) != -1){
System.out.print((char) readContent); //转成char显示
}
}catch (IOException e){
e.printStackTrace();
}finally {
//关闭文件流,释放资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
输出结果如下:
hello,world
由于read()方法一次只能读取一个字节,我们使用更多的是read(byte[] b)(byte数组b是设定该read方法一次读取几个字节)方法读取:
//read()方法的读取效率很低,我们一般使用read(byte[] b)方法
public void readFile2(){
String filePath = "d:\\hello.txt"; //hello.txt文件中写的内容是hello,world
int readContent = 0;
//字节数组
byte[] bytes = new byte[8]; //一次读取8个字节
FileInputStream fileInputStream = null; //在这里定义FileInputStream对象,扩大它的作用域。
try {
//创建FileInputStream对象,用于读取文件
fileInputStream = new FileInputStream(filePath);
//从该输入流读取一个字节的数据。read()方法一次只读取一个字节。
while ((readContent = fileInputStream.read(bytes)) != -1){
System.out.print(new String(bytes,0,readContent)); //转成char显示
}
}catch (IOException e){
e.printStackTrace();
}finally {
//关闭文件流,释放资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(2)FileOutputStream
FileOutputStream是文件输出流。即:程序 ---> 文件
FileOutputStream体系图:
FileOutputStream类的构造器和方法:
下面演示一个案例,需求是:将"hello,world"写入到hello.txt文件中,若该文件不存在,则创建文件该文件,然后写入。
//将数据写到文件中,如果文件不存在,则创建该文件
public void writeFile(){
//创建FileOutputStream对象
String filePath = "d:\\hello.txt";
FileOutputStream fileOutputStream = null;
try {
//得到FileOutputStream对象
fileOutputStream = new FileOutputStream(filePath);
//写入一个字节
fileOutputStream.write('H');
//写入字符串
String str = "hello,world";
//str.getBytes()可以把 字符串 ---> 字节数组
fileOutputStream.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(3)文件拷贝
需求:完成文件/音乐的拷贝
有需求,请看视频:0617_韩顺平Java_文件拷贝_哔哩哔哩_bilibili
2、Reader类
(1)FileReader
FileReader用于读取文件内容。即:文件 ---> 程序
FileReader体系图:
FileReader类中的方法:
- new FileReader(File/String):该方法指定要读取的文件。
- read():读取文件内容(每次只读取一个字符),如果读到了文件末尾(就是指文件内容读完了),就返回-1。
- read(char[]):读取文件内容(可以指定每次读取多少个字符),如果读到了文件末尾(就是指文件内容读完了),就返回-1。
- read(char[])方法效率高,read()方法的效率比较低。
下面演示一下用read()方法读取文件:
public class FileReader_ {
public static void main(String[] args) throws Exception {
String filePath = "d:\\hello.txt";
int dataContent = 0;
FileReader fileReader = new FileReader(filePath);
//循环读取,使用read()方法,该方法一次只读取一个字符,效率比较低。
//read()方法返回的是int类型数据,所以输出的时候,要强转成char类型
while ((dataContent = fileReader.read()) != -1){
System.out.println((char) dataContent);
}
if (fileReader != null){
fileReader.close();
}
}
}
下面演示一下用read(char[])方法读取文件:
public class FileReader_ {
public static void main(String[] args) throws Exception {
String filePath = "d:\\hello.txt";
int dataContent = 0;
char[] chars = new char[8];
FileReader fileReader = new FileReader(filePath);
//循环读取,使用read(char[])方法
//如果返回-1,说明到文件末尾了
while ((dataContent = fileReader.read(chars)) != -1){
//使用String的构造器,将chars转换成字符串
System.out.println(new String(chars,0,dataContent));
}
if (fileReader != null){
fileReader.close();
}
}
}
有关上面代码中String构造器的解读:
String(byte[] char,int offset,int length);将char数组拼成字符串,从char数组中第offset个char开始,一直拼接length个字符。
char[] chars = {'a','b','c','d','e','f','g','h'};
String string = new String(chars,2,5);
System.out.println(string);
输出结果是:cdefg
(2)FileWriter
FileWriter向文件中写入内容。即:程序 ---> 文件
FileWriter体系图:
FileWriter类中的方法:
写入的东西在内存,必须关闭or刷新才能到指定的文件里面
四、节点流和处理流
1、节点流
节点流是针对某一个特点的数据源(例如某个文件),读写数据。eg:FileReader、FileWriter。
2、处理流
也叫包装流,它连接在已经存在的流(节点流or处理流)之上,为程序提供更强大的读写功能,更加灵活。eg:BufferedReader、BufferedWriter。
3、节点流VS处理流
节点流和处理六的区别和联系:
- 节点流是底层流,直接跟数据源相接。
- 处理流(包装流)用于包装节点流,它既可以消除不同节点流的实现差异(例如:对文件、对数组的实现是不一样的),也可以提供更方便的方法完成输入输出。
- 处理流(包装流)的本质是对节点流进行包装,使用修饰器设计模式,它不会直接与数据源相连。它只是去调用不同的节点流,功能的扩展是靠修饰器去完成。
处理流的功能主要体现在以下两个方面:
- 性能的提高:主要通过增加缓冲的方式来提高输入输出的效率。
- 操作的便捷:处理六提供一系列便捷的方法来一次输入输出大量数据,更加灵活方便。
4、BufferedReader和BufferedWriter
BufferedReader和BufferedWriter属于字符流,是按照字符来读取数据的。
(1)BufferedReader
BufferedReader是从缓冲区中读取内容,所有的内容都先放在缓冲区中。因此,它可以接收任意长度的数据,并且可以避免产生乱码。
BufferedReader的构造器需要的参数,一般情况下是转换成字符流的字节流:
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
//更常见的是下面的写法
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
(2)BufferedWriter
关闭处理流时,只需要关闭外层流即可,因为真正进行数据读取的,其实还是节点流。
5、BufferedInputStream和BufferedOutputStream
BufferedInputStream是字节流,在创建BufferedInputStream时,会创建一个内部缓冲区数组。
6、ObjectInputStream和ObjectOutputStream
这组处理流是专门处理对象的。
注意事项:
7、InputStreamReader和OutputStreamWriter
InputStreamReader和OutputStreamWriter是转换流。
(1)InputStreamReader
InputStreamReader类是Read类的子类,可以将InputStream(字节流)包装成(转换成)Reader(字符流)
体系图如下:
上图中被框起来的构造器,参数InputStream:该参数是字节流对象,InputStream类的子类对象也可以;参数Charset:用来指定编码格式,是utf-8、ASCII等等。
(2)OutputStreamWriter
OutputStreamWriter类是Writer类的子类,可以将OutputStream(字节流)包装成(转换成)Writer(字符流)
体系图如下:
构造器和上面的解释一样。
Tips:在处理纯文本数据时,使用字符流效率更高,并且可以解决中文乱码的问题,因此建议将字节流转换成字符流。
8、PrintStream和PrintWriter
PrintStream和PrintWriter是打印流。
- PrintStream只有输入流,没有输出流。
- PrintWriter只有输出流,没有输入流。
五、Properties类
1、properties类的体系图
2、基本介绍:
该类是专门用于读写配置文件的集合类。
配置文件的格式: 键=值
注意:键值对不需要有空格,值不需要用引号引起来,默认类型是String。
3、Properties的常见方法