文章目录
前言
还在为BufferedReader和Scanner的用法而困苦吗?为什么BufferedReader就比Scanner快呢?IO流是个啥?怎么用呢?这些问题本篇博客都会详细介绍,若读者朋友想直接了解BufferedReader和Scanner的区别可直接根据目录查阅,若读者朋友想对IO流也一探究竟,那建议从头开始,认真阅读!
什么是IO流呢?
I指的是输入(Input),O指的是输出(Output),即数据像流体一样进行传输。它可以进行对文件的读、写、拷贝等等一些列操作。那么说到文件,我们就先来了解一下File类。
File类
概念
File的中文意思有文件,文件夹的意思,那么使用File类实例化的对象即代表了磁盘上的某个文件或文件夹。
构造方法
- File的包为java.io.File,使用时不要忘记导包。
- File(String pathname)根据字符串类型的路径,创建File对象。
- File(String parent,String child)根据父目录以及子目录来创建File对象。
- File(File parent,String child)先将父目录封装成File对象,结合字符串形式的子目录来形成新的File对象。
import java.io.File;
public class Test {
public static void main(String[] args) {
//任务:将F:\IDEA\1.txt 封装成File对象
//构造方法一:
//路径赋值过来之后,发现\变成了\\,因为\有特殊含义,所以需要前面加\来转义一下
File file1 = new File("F:\\IDEA\\1.txt");
//如果觉得写两个右斜线太麻烦,那么就可以写一个左斜线来代替
File file2 = new File("F:/IDEA/1.txt");
System.out.println("file1:" + file1);
//构造方法二:
File file3 = new File("F:/IDEA/","1.txt");
System.out.println("file3:" + file3);
//构造方法三:
File fileParent = new File("F:/IDEA/");
File fileChild = new File(fileParent,"1.txt");
System.out.println("fileChild:" + fileChild);
}
}
成员方法
方法名 | 返回值 | 作用 |
---|---|---|
createNewFile() | boolean | 创建文件(如果不存在就创建,返回true,否则不创建,返回false) |
mkdir() | boolean | 创建单级目录 |
mkdirs() | boolean | 创建多级目录 |
isDirectory() | boolean | 判断File对象是否为目录 |
isFile() | boolean | 判断File对象是否为文件 |
exists() | boolean | 判断File对象是否存在 |
getAbsolutePath() | String | 获取绝对路径,绝对路径:以盘符开头的路径,例如:F:/IDEA/1.txt |
getPath() | String | 获取文件的相对路径,相对路径:一般是相对于当前目录来讲的,例如:1.txt |
getName() | String | 获取文件名 |
list() | String[] | 获取指定目录下所有文件(夹)名称数组 |
listFiles() | File[] | 获取指定目录下所有文件(夹)File数组 |
调用file的成员方法时,有可能我们输入的路径本身就是错误的,然而编写代码的时候编译器又无法识别,所以在使用对象调用方法时就有可能出现异常IOException,那么这个时候就需要我们去处理这个异常,可以选择捕获或者抛出,这里我们选择抛出。那么,接下来就带大家举例使用几个成员方法吧。
import java.io.File;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
//任务:在F:/IDEA/目录下创建文件
File file4 = new File("F:/IDEA/2.txt");
boolean flag1 = file4.createNewFile();
System.out.println("file5:"+flag1);
//任务:在F:/IDEA/下创建目录,也就是文件夹abc
File file5 = new File("F:/IDEA/abc");
boolean flag2 = file5.mkdir();
System.out.println("flag2:"+flag2);
//任务:在刚才创建的abc下继续创建子目录/d/e(多级目录)
File file6 = new File("F:/IDEA/abc/b/c");
boolean flag3 = file6.mkdirs();
System.out.println("flag3" + flag3);
//任务:判断File7对象是否为目录
File file7 = new File("F:/IDEA/abc/b/c");
boolean flag4 = file7.isDirectory();
System.out.println("flag4"+flag4);
}
}
IO流体系
-
按数据流向分:
- 输入流
- 输出流
-
按操作方式分:
注:使用抽象类时需要调用其子类!
-
字节流:按照字节输入输出数据
-
InputStream(字节输入流的顶层抽象类)
FileInputStream:普通的字节输入流
BufferedInputStream:高效的字节输出流(也叫:字节缓冲输入流)
-
OutputStream(抽象类)
FileOutputStream: 普通的字节输出流
BufferedOutputStream:高效的字节输出流(也叫:字节缓冲输出流)
-
-
字符流:按照字符输入输出数据
-
Reader(抽象类)
FileReader:普通的字符输入流
BufferedReader:高效的字符输入流(也叫:字符缓冲输入流)
-
Writer(抽象类)
FileWriter:普通的字符输出流
BufferedWriter:高效的字符输出流(也叫:字符缓冲输出流)
-
-
IO流的使用
对于这些IO流体系中的类的使用步骤其实都是大同小异的,对于读或写操作可分为:创建操作对象、调用方法读或写数据、关闭资源、异常处理。对于普通的操作,我选择用文字大概描述,而高效操作用代码演示。
字符流使用
-
FileReader
-
创建字符流读文件对象:Reader reader = new FileReader(“readme.txt”);
-
调用方法读取数据:
按单个字符读取:
int data = reader.read();
读取一个字符,返回该字符代表整数,若到达流的末尾,返回-1。
read()方法每次被调用之后都会往下一个走!!!所以在循环中调用时一定要注意!
while((ch = reader.read()) != -1),若之前未调用read方法,则该循环就意味着从头读到尾。
按字符数组读取:
char[] chs = new char[2048];
int len = reader.read(chs);
读取字符到数组中,返回读取的字符数,若到达流的末尾,返回-1。
-
关闭资源:reader.close();
-
异常处理:throws IOException
注:在关闭资源的时候会出现异常FileNotFoundException,而在new FileReader时会出现异常IOException,因为IOException是FileNotFoundException的父类,所以只需要抛出IOException即可!
-
-
FileWriter
-
创建字符流写文件对象:Writer writer = new FileWriter(“1.txt”);
-
调用方法写入数据:
按单个字符写入:
int x = ‘中’;
writer.write(x);
按字符数组写入:
char[] chs = {‘你’,‘好’,‘朋’,‘友’};
writer.write(chs);
按字符串写入:
writer.write(“你好朋友”);
-
异常处理:throws IOException
-
关闭资源:writer.close();
那么如何进行字符流拷贝文件呢?那就是将读操作和写操作相结合!
-
字符缓冲流拷贝文件(重要)
import java.io.*;
//使用字符缓冲流完成对文件的拷贝
//BufferedReader 构造方法:BufferedReader(Reader reader);
//BufferedWriter 构造方法:BufferedWriter(Writer Writer);
//特点:字符缓冲流自带有缓冲区,大小为8192个字符,也就是16KB
public class CopyFile1 {
public static void main(String[] args) throws IOException {
//任务:通过字符缓冲流:将1.txt文件中的内容拷贝到2.txt文件中
//注:1.txt在F:/IDEA/1.txt
//1.创建字符缓冲输入流对象,关联数据源文件
//这里我们直接使用匿名对象来构建
BufferedReader br = new BufferedReader(new FileReader("F:/IDEA/1.txt"));
//2.创建字符缓冲输出流对象,关联目的地文件,如果该文件不存在即会自动创建文件
BufferedWriter bw = new BufferedWriter(new FileWriter("F:/IDEA/2.txt"));
//3.定义变量记录读取到的数据
int len;
//4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
while((len = br.read()) != -1){
//5.将读取到的数据写入到目的地文件中
bw.write(len);
}
//6.释放资源
br.close();
bw.close();
}
}
字符缓冲流成员方法使用(重要)
import java.io.*;
//BufferedReader 中的成员方法:
// public String readLine();一次读取一行数据并返回读取到的内容,读不到返回null
//BufferedWriter 中的成员方法:
// public void newLine();根据当前操作系统给出对应的换行符
public class CopyFile2 {
public static void main(String[] args) throws IOException {
//以一次一行的方式,将1.txt文件中的内容拷贝到2.txt中
BufferedReader br = new BufferedReader(new FileReader("F:/IDEA/1.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("F:/IDEA/2.txt"));
String str;
while((str = br.readLine()) != null){
bw.write(str);
//千万要注意,要自己补充换行符
bw.newLine();
}
br.close();
bw.close();
}
}
字节流使用
思考:刚才我们拷贝的txt文件是文本文件,那么对于图片的拷贝,你还可以使用字符流吗?读者可以自行尝试!那么,接下来我们尝试一下用字节流拷贝。
单字节拷贝图片
/*FileInputStream:
构造方法:
public FileInputStream(String pathname);
成员方法:
public int read():一次读取一个字节,并返回读取到的内容,读不到返回-1
FileOutoutStream:
构造方法:
public FileOutputStream(String pathname);
成员方法:
public void write(int len):一次写入一个字节*/
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFile3 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("F:/IDEA/1.jpg");
FileOutputStream fos = new FileOutputStream("F:/IDEA/2.jpg");
int len;
while((len = fis.read()) != -1){
fos.write(len);
}
fis.close();
fos.close();
}
}
BufferedInputStream:
构造方法:public BufferedInputStream(InputStream is);
成员方法:public int read();一次读取一个字节,并返回读取到的内容,读不到返回-1;
BufferedOutputStream:
构造方法:public BufferedOutputStream(OutoutStream os);
成员方法:public void write(int len); 一次写入一个字节
请读者自己尝试以刚才类似于字符流的代码,使用字节缓冲流写关于图片拷贝的代码!
BufferedReader和Scanner
- Scanner是一个可以使用正则表达式来分析基本类型和字符串的简单文本扫描器。
- BufferedReader从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。
- BufferedReader的构造方法需要传入一个Reader,可以通过InputStreamReader和FilerReader进行包装后传入
//刷题一般使用第一种
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedReader br = new BufferedReader(new FileReader("F:/IDEA/1.txt"));
- BufferedReader是支持同步的,而Scanner不支持。
- BufferedReader的read方法都加了synchronized关键字,无论是同步的方法还是同步的代码块,都会先把主内存的数据拷贝到工作内存中,同步代码块结束,会把工作内存中的数据更新到主内存中,这样主内存中的数据一定是最新的。