1. 在IO流中,我们如果要想操作文件,需要用到哪个类?
答:File类。
2. 对于File类的用法,我们通常会用File类来封装一个文件的绝对路径,代码怎么实现的?
答:File file = new File(“e://a.txt”);
3. Java中IO流的分类?
答:按流向分,可分为输入流和输出流;按数据类型分,可以分为字节流和字符流。
4. Java IO类在设计时采用了Decorator(装饰者设计模式)。
5. Java中有几种类型的流?
答:按数据类型分,可分为字节流和字符流;按流向分,可分为输入流和输出流。
6. 管理文件和目录的类叫什么?
答:File类。
7. 字节流继承于InputStream和OutputStream,我们通常会用FileInputStream来读取数据,用FileOutputStream类写出数据,为了能更快的读取和写出数据,我们用BufferedInputStream将FileInputStream包装一下,用BufferedOutputStream将FileOutputStream来包装一下。我们可以用字节流从一个文件读取文本信息,并写入另一个文件中去,以实现文件复制的目的。
字节流复制文件(适用于文本、图片、音频、视频等各种类型的文件)
/** * 字节流复制文件(适用于文本、图片、音频、视频等各种类型的文件) */ @Test public void copyFileDemo() throws Exception{ FileInputStream fis = new FileInputStream("d://1.jpg"); FileOutputStream fos = new FileOutputStream("d://2.jpg"); byte[] bytes = new byte[1024]; int len; while((len=fis.read(bytes))!=-1){ fos.write(bytes,0,len); fos.flush(); } fos.close(); fis.close(); } |
字节缓冲流复制文件(适用于文本、图片、音频、视频等各种类型的文件)
/** * 字节缓冲流复制文件(适用于文本、图片、音频、视频等各种类型的文件) */ @Test public void IOTest() throws Exception{ BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d://1.jpg")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d://2.jpg")); byte[] bytes = new byte[1024]; int len; while((len=bis.read(bytes))!=-1){ bos.write(bytes,0,len); bos.flush(); } bos.close(); bis.close(); } |
如果是复制文件,我们用字节流就足以胜任了,那为什么我们还要学习字符流呢?
答:因为字节流操作中文不是特别方便。注意,是 不是特别方便,而不是 不行。
如果用字节流来复制文件,即从一个文件读取,并写入到另一个文件中去,不管文件中有没有中文,都没有任何问题。
问题出在你只是从文件中读取数据时,如果有中文,字节流就会出问题,什么问题?
当你从文件中读取文本信息到控制台时,如果文件中包含中文,显示到控制台上时会出现乱码。原因在于,一个字符由两个字节组成,中文字符的第一个字节表示负数,第二个字节才表示该中文字符对应的编码表中的数字,字节流读数据是一个字节一个字节的读,它读到负数时就不知道这是什么意思了,就会在控制台上显示一个问号?。我们就像,如果能两个字节一块读,一次读一个字节,那就不会出现以上的问题了。所以我们要学习字符流。
什么是字符流呢?
答:字符流就是字节转换流。字符流 = 字节流 + 编码表
字节转换流有两种,InputStreamReader和OutputStreamWriter。
为了简化书写, 用FileWriter代替OutputStreamWriter
用FileReader代替InputStreamReader
最原始的字符流是InputStreamReader和OutputStreamWriter,但在使用默认编码和图方便的情况下,可以用FileReader和FileWriter来替换。为了进一步提高流的效率,我们会用BufferedReader和BuffferedWriter把FileReader和FileWriter包装一下,当然,也可以是InputStreamReader和OutputStreamWriter。
1. 字符流和字节流有什么关系?用代码怎么来体现一下?
答:字符流 = 字节流 + 编码方式。
代码如下:
根据指定的编码读取数据
InputStreamReader isr = new InputStreamReader(new FileInputStream(“d://1.txt”),”GBK”);
如果采用本地默认编码,编码方式可以省略。
根据指定编码把字节流数据转换为字符流
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "GBK");
如果采用本地默认编码,编码方式可以省略。
2. 你说字符流 = 字节流 + 编码方式,那我有一个问题想问一下你,我们在用字符流读取数据的时候,经常会这样写:FileReader fr = new FileReader(“d://1.txt”);
从这句代码中,我并没有看出来字符流和字节流有什么关系啊?你能给我解释一下为什么吗?
答:这句代码是字符流的一种简写方式。它等价于:
InputStreamReader isr = new InputStreamReader(new FileInputStream(“d://1.txt”));
这里的编码方式采用的是本地默认编码,所以省略了。
2. InputStreamReader和OutputStreamWriter可以直接封装文件路径吗?
答:不可以。
3. FileReader和FileWriter可以直接封装文本路径吗?
答:可以。
4. 我们在使用FileReader和FileWriter的时候,我们经常这么用:
FileReader fr = new FileReader(“d://1.txt”);
FileWriter fr = new FileWriter(“d://2.txt”);
直接封装文件路径,那如果我不想直接封装文件路径,而是这么用:
FileReader fr = new FileReader(new FileInputStream(“d://1.txt”));
FileWriter fr = new FileWriter(new FileOutputStream(“d://2.txt”));
这样可以吗?为什么?
答:不可以。因为FileReader和FileWriter只提供了一种构造方式,就是直接接收一个字符串,而不能接收一个流。
5. 在用字符流读取数据的时候,默认的编码方式出现乱码,我们需要指定编码方式,这个时候,能够用FileReader来替换InputStreamReader吗?
答:不可以。FileReader没有办法指定编码方式,只能使用默认的编码方式。
6. 在用字符流读取、复制文件的时候,你会选用使用InputStreamReader和OutputStreamWriter,还是使用FileReader和FileWriter,为什么?
答:选择使用FileReader和FileWriter。因为一般情况下,我们常见的操作都是使用本地默认编码,所以,不用指定编码,而且FileReader和FileWriter可以直接封装路径,方便。
但是,如果使用FileReader和FileWriter在读取、复制文件的时候出现了乱码问题,那我就要考虑使用InputStreamReader和OutputStreamWriter试试看了。
使用字符流读取文本文件(法一)
/** * 使用字符流读取文本文件 * * @throws Exception */ @Test public void ReadFileDemo() throws Exception{ //FileReader isr = new FileReader("d://1.txt");//出现乱码 //InputStreamReader isr = new InputStreamReader(new FileInputStream("d://1.txt"));//出现乱码 InputStreamReader isr = new InputStreamReader(new FileInputStream("d://1.txt"),"GBK"); // 一次读取一个字符数组 char[] chs = new char[1024]; int len = 0; while ((len = isr.read(chs)) != -1) { System.out.print(new String(chs, 0, len)); }
// 释放资源 isr.close(); } |
法二:(推荐)
package 字符流读取文本文件;
import java.io.BufferedReader; import java.io.FileReader;
public class Test { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new FileReader("d://1.txt")); String s = null; while((s = br.readLine())!=null){ System.out.println(s); } br.close(); } } |
字符流复制文本文件(只能复制文本文件,图片、视频等不可以)
/** * 字符缓复制文本文件(只能复制文本文件,对于图片、视频等不可以) * * @throws Exception */ @Test public void copyFileDemo() throws Exception{ // 封装数据源 //InputStreamReader isr = new InputStreamReader(new FileInputStream("d://1.txt"),"GBK"); //可以通过指定编码来解决复制中可能出现的乱码问题 FileReader fr = new FileReader("d://1.txt"); // 封装目的地 FileWriter fw = new FileWriter("d://2.txt");
// 一次一个字符数组 char[] chs = new char[1024]; int len = 0; while ((len = fr.read(chs)) != -1) { fw.write(chs, 0, len); fw.flush(); }
// 释放资源 fw.close(); fr.close(); } |
字符缓冲流复制文本文件(只能复制文本文件,图片、视频等不可以)
/** * 字符缓冲流复制文本文件(只能复制文本文件,对于图片、视频等不可以) * * @throws Exception */ @Test public void copyFileDemo() throws Exception{ // 封装数据源 //BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("d://1.txt"),"GBK"));//可以通过指定编码来解决复制中可能出现的乱码问题 BufferedReader br = new BufferedReader(new FileReader("d://1.txt")); // 封装目的地 BufferedWriter bw = new BufferedWriter(new FileWriter("d://2.txt"));
// 一次读写一个字符数组 char[] chs = new char[1024]; int len = 0; while ((len = br.read(chs)) != -1) { bw.write(chs, 0, len); bw.flush(); }
// 释放资源 bw.close(); br.close(); } |
法二:
package 字符流复制文本文件;
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter;
public class Test { public static void main(String[] args) throws Exception { //封装数据源 BufferedReader br = new BufferedReader(new FileReader("d://1.txt")); //封装目的源 BufferedWriter bw = new BufferedWriter(new FileWriter("d://2.txt")); String s; while((s = br.readLine())!=null){ bw.write(s); bw.newLine();//换行 bw.flush(); } System.out.println("复制文件成功!"); bw.close(); br.close(); } } |
面试题:close()和flush()的区别?
A:close()关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了。(一般用close(),只有数据量特别大的时候才会用flush())
B:flush()仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。
打印流
1. IO流中的打印流指的是什么?
答:字节流打印流PrintStream和字符打印流PrintWriter
2. 打印流有什么特点?
答:A:只能写数据,不能读数据。
B:可以操作任意类型的数据。
C:如果启动了自动刷新,能够自动刷新。
D:可以直接操作文本文件的。
3. 哪些流对象是可以直接操作文本文件的呢?
答: FileInputStream
FileOutputStream
FileReader
FileWriter
PrintStream
PrintWriter
4. 什么是基本流?什么是高级流?
答:基本流:就是能够直接读写文件的
高级流:在基本流基础上提供了一些其他的功能
5. 简介一下打印流的自动刷新功能
答:一般我们使用流时,最后都要flush()刷新一下,我们通常使用的close()的原理也是先刷新、再关闭的,但是打印流中的字符打印流有自动刷新的功能,就是说用了它的这个功能就不用flush()一下了。但这个功能很鸡肋,而且麻烦,我们不用它。
打印流改进复制文本文件案例
package cn.itcast_03;
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; /* * 需求:DataStreamDemo.java复制到Copy.java中 * 数据源: * DataStreamDemo.java -- 读取数据 -- FileReader -- BufferedReader * 目的地: * Copy.java -- 写出数据 -- FileWriter -- BufferedWriter -- PrintWriter */ public class CopyFileDemo { public static void main(String[] args) throws IOException { // 以前的版本 // 封装数据源 // BufferedReader br = new BufferedReader(new FileReader( // "DataStreamDemo.java")); // // 封装目的地 // BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java")); // // String line = null; // while ((line = br.readLine()) != null) { // bw.write(line); // bw.newLine(); // bw.flush(); // } // // bw.close(); // br.close();
// 打印流的改进版 // 封装数据源 BufferedReader br = new BufferedReader(new FileReader( "DataStreamDemo.java")); // 封装目的地 PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true); String line = null; while((line=br.readLine())!=null){ pw.println(line); } pw.close(); br.close(); } } |
6. 标准输入输出流指得是什么?
答:System类有两个成员变量,in和out,in的类型是InputStream,即标准输入流,out的类型是PrintStream,即标准输出流。
/*
* 标准输入输出流
* System类中的两个成员变量:
*public static final InputStream in “标准”输入流。
* public static final PrintStream out “标准”输出流。
*
* InputStream is = System.in;
* PrintStream ps = System.out;
*/
7. 使用标准输出流向控制台打印信息
/** * 使用标准输出流向控制台打印信息 * * @throws Exception */ @Test public void systemOutDemo() throws Exception{ // 有这里的讲解我们就知道了,这个输出语句其本质是IO流操作,把数据输出到控制台。 System.out.println("helloworld");
// 获取标准输出流对象 PrintStream ps = System.out; ps.println("hello world"); } } |
8. 输出语句用字符缓冲流改进(鸡肋)
/** * 输出语句用字符缓冲流改进 * * @throws Exception */ @Test public void systemOutDemo() throws Exception{ BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write("hello"); bw.newLine(); // bw.flush(); bw.write("world"); bw.newLine(); // bw.flush(); bw.write("java"); bw.newLine(); bw.flush(); bw.close(); } |
9. 使用标准输入流实现键盘录入功能
/** * 使用标准输入流实现键盘录入功能 * * @throws Exception */ @Test public void systemInDemo() throws Exception{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入一个字符串:"); String line = br.readLine(); System.out.println("你输入的字符串是:" + line);
System.out.println("请输入一个整数:"); line = br.readLine(); int i = Integer.parseInt(line); System.out.println("你输入的整数是:" + i); } |
流的序列化
配置文件properties