Java复习,Java知识点以及Java面试题(七)
IO流
用来处理设备之间的数据传输
IO流的分类:按流向:输入流(读取数据);输出流(写出数据)
按数据类型:字节流:
字节输入流 读取数据 InputStream
字节输出流 写出数据 OutputStream
字符流:为了方便操作文本数据
字符输入流 读取数据 Reader
字符输出流 写出数据 Writer
InputStream,OutputStream,Reader,Writer都是抽象类,不能实例化,所以我们要使用具体的子类。每种基类的子类都是以父类名作为后缀名:
XxxOutputStream,XxxInputStream,XxxReader,XxxWriter
FileOutputStream:
构造方法:FileOutputStream(File file)
FileOutputStream(String name)
FileOutputStream(String name;Boolean ture)
成员方法:public void wirte(int b):
public void wirte(byte[] b):
public void wirte(byte[] b, int off, int len)
字节输出流操作步骤:创建字节输出流-->写数据-->释放资源,关闭此文件输出流并释放与此流有关的所有系统资源(.close() )
创建字节输出流对象做了几件事情:
A. 调用系统功能去创建文件
B. 创建FileOutputStream对象
C. 把对象指向这个文件
为什么一定要close()呢?
A. 让流对象变成垃圾,这样就可以被垃圾回收器回收了
B. 通知系统去释放跟该文件相关的资源
实现数据换行
加换行符号:
Windos:\r\n; linux:\n; Mac: \r;
如何实现追加写入数据:
使用构造方法:FileOutputStream(String name;Boolean ture)
写入数据时的异常处理:
1 // 为了在finally里面能够看到该对象就必须定义到外面,为了访问不出问题,还必须给初始化值 2 FileOutputStream fos = null; 3 try { 4 // fos = new FileOutputStream("z:\\fos4.txt"); 5 fos = new FileOutputStream("fos4.txt"); 6 fos.write("java".getBytes()); 7 } catch (FileNotFoundException e) { 8 e.printStackTrace(); 9 } catch (IOException e) { 10 e.printStackTrace(); 11 } finally { 12 // 如果fos不是null,才需要close() 13 if (fos != null) { 14 // 为了保证close()一定会执行,就放到这里了 15 try { 16 fos.close(); 17 } catch (IOException e) { 18 e.printStackTrace(); 19 } 20 } 21 }
FileInputStream
字节输入流操作步骤:创建字节输入流对象-->调用read()方法读取数据,并把数据显示在控制台-->释放资源
构造方法同FileOutputStream
成员方法:public int read(): 一次读取一个字节
public int read(byte[] b): 一次读取一个字节数组 返回值是实际读取的字节个数。如果到末尾就返回-1
计算机时如何识别什么时候该把两个字节转换为一个中文呢?
在计算机中中文的存储分两个字节:第一个字节肯定是负数,第二个字节常见是负数,可能是正数。但是没有影响。
通过定义数组的方式确实比以前一次读取一个字节的方式快很多,所以,缓冲区非常有用,java就在开始设计的时候,提供了带缓冲区的字节类。这种类被称为:缓冲区类(高效类)。写数据:BufferedOutputStream;读数据:BufferedInputStream
构造方法可以指定缓冲区的大小,但是我们一般用不上,因为默认缓冲区大小足够了。
为什么不传递一个具体的文件或者文件路径,而是传递一个OutputStream对象呢?因为字节缓冲区流仅仅提供缓冲区,为高效而设计的,但是真正的读写操作还得靠基本的流对象实现.
字符流 = 字节流 + 编码表(由现实世界的字符和对应的数值组成的一张表)
String类中的编码和解码问题:
String(byte[] bytes, String charsetName): 通过指定的字符集解码字节数组
byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组
OutputStreamWrite
OutputStreamWriter(OutputStream out): 根据默认编码把字节流的数据转换为字符流
OutputStreamWriter(OutputStream out, String charsetName):根据指定编码把字节流数据转换为字符流
字符流的五种写数据的方法:
public void write(int c):写一个字符
public void write(char[] cbuf):写一个字符数组
public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
public void write(String str):写一个字符串
public void write(String str,int off,int len):写一个字符串的一部分
close()和flush()的区别?
A:close()关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了(即不能书写和读取数据,否则报错)。
B: 仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。
InputStreamReader
InputStreamReader(InputStream is): 用默认的编码读取数据
InputStreamReader(InputStream is, String charsetName): 根据指定的编码读取数据
字符流读数据的两种方法:
public int read():一次读取一个字符
public int read(char[] chs):一次读取一个字符数组
由于我们常见的操作都是使用本地默认编码,所以,不用指定编码。
而转换流的名称有点长,所以,Java就提供了其子类供我们使用FileWriter,FileReader
字符缓冲流
字符流为了高效读写,也提供了对应的字符缓冲流
BufferedWriter:字符缓冲输出流:将文本写入字符输出流,缓冲各个字符,从而提供的单个字符,数组和字符串的高效写入。可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了
BufferedReader:字符缓冲输入流:从字符输入流中读取文本,缓冲各个字符,从而提供的单个字符,数组和字符串的高效写入。可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了
特殊方法:
BufferedWriter: public void newLine(): 根据系统来决定换行符
BufferdReader:public String readLine(): 一次读取一个一行数据
1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.FileReader; 4 import java.io.FileWriter; 5 import java.io.IOException; 6 7 /* 8 * 复制文本文件 9 * 10 * 分析: 11 * 复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。 12 * 通过该原理,我们知道我们应该采用字符流更方便一些。 13 * 而字符流有5种方式,所以做这个题目我们有5种方式。推荐掌握第5种。 14 * 数据源: 15 * c:\\a.txt -- FileReader -- BufferdReader 16 * 目的地: 17 * d:\\b.txt -- FileWriter -- BufferedWriter 18 */ 19 public class CopyFileDemo { 20 public static void main(String[] args) throws IOException { 21 String srcString = "c:\\a.txt"; 22 String destString = "d:\\b.txt"; 23 // method1(srcString, destString); 24 // method2(srcString, destString); 25 // method3(srcString, destString); 26 // method4(srcString, destString); 27 method5(srcString, destString); 28 } 29 30 // 字符缓冲流一次读写一个字符串 31 private static void method5(String srcString, String destString) 32 throws IOException { 33 BufferedReader br = new BufferedReader(new FileReader(srcString)); 34 BufferedWriter bw = new BufferedWriter(new FileWriter(destString)); 35 36 String line = null; 37 while ((line = br.readLine()) != null) { 38 bw.write(line); 39 bw.newLine(); 40 bw.flush(); 41 } 42 43 bw.close(); 44 br.close(); 45 } 46 47 // 字符缓冲流一次读写一个字符数组 48 private static void method4(String srcString, String destString) 49 throws IOException { 50 BufferedReader br = new BufferedReader(new FileReader(srcString)); 51 BufferedWriter bw = new BufferedWriter(new FileWriter(destString)); 52 53 char[] chs = new char[1024]; 54 int len = 0; 55 while ((len = br.read(chs)) != -1) { 56 bw.write(chs, 0, len); 57 } 58 59 bw.close(); 60 br.close(); 61 } 62 63 // 字符缓冲流一次读写一个字符 64 private static void method3(String srcString, String destString) 65 throws IOException { 66 BufferedReader br = new BufferedReader(new FileReader(srcString)); 67 BufferedWriter bw = new BufferedWriter(new FileWriter(destString)); 68 69 int ch = 0; 70 while ((ch = br.read()) != -1) { 71 bw.write(ch); 72 } 73 74 bw.close(); 75 br.close(); 76 } 77 78 // 基本字符流一次读写一个字符数组 79 private static void method2(String srcString, String destString) 80 throws IOException { 81 FileReader fr = new FileReader(srcString); 82 FileWriter fw = new FileWriter(destString); 83 84 char[] chs = new char[1024]; 85 int len = 0; 86 while ((len = fr.read(chs)) != -1) { 87 fw.write(chs, 0, len); 88 } 89 90 fw.close(); 91 fr.close(); 92 } 93 94 // 基本字符流一次读写一个字符 95 private static void method1(String srcString, String destString) 96 throws IOException { 97 FileReader fr = new FileReader(srcString); 98 FileWriter fw = new FileWriter(destString); 99 100 int ch = 0; 101 while ((ch = fr.read()) != -1) { 102 fw.write(ch); 103 } 104 105 fw.close(); 106 fr.close(); 107 } 108 }
1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 8 /* 9 * 复制图片 10 * 11 * 分析: 12 * 复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。 13 * 通过该原理,我们知道我们应该采用字节流。 14 * 而字节流有4种方式,所以做这个题目我们有4种方式。推荐掌握第4种。 15 * 16 * 数据源: 17 * c:\\a.jpg -- FileInputStream -- BufferedInputStream 18 * 目的地: 19 * d:\\b.jpg -- FileOutputStream -- BufferedOutputStream 20 */ 21 public class CopyImageDemo { 22 public static void main(String[] args) throws IOException { 23 // 使用字符串作为路径 24 // String srcString = "c:\\a.jpg"; 25 // String destString = "d:\\b.jpg"; 26 // 使用File对象做为参数 27 File srcFile = new File("c:\\a.jpg"); 28 File destFile = new File("d:\\b.jpg"); 29 30 // method1(srcFile, destFile); 31 // method2(srcFile, destFile); 32 // method3(srcFile, destFile); 33 method4(srcFile, destFile); 34 } 35 36 // 字节缓冲流一次读写一个字节数组 37 private static void method4(File srcFile, File destFile) throws IOException { 38 BufferedInputStream bis = new BufferedInputStream(new FileInputStream( 39 srcFile)); 40 BufferedOutputStream bos = new BufferedOutputStream( 41 new FileOutputStream(destFile)); 42 43 byte[] bys = new byte[1024]; 44 int len = 0; 45 while ((len = bis.read(bys)) != -1) { 46 bos.write(bys, 0, len); 47 } 48 49 bos.close(); 50 bis.close(); 51 } 52 53 // 字节缓冲流一次读写一个字节 54 private static void method3(File srcFile, File destFile) throws IOException { 55 BufferedInputStream bis = new BufferedInputStream(new FileInputStream( 56 srcFile)); 57 BufferedOutputStream bos = new BufferedOutputStream( 58 new FileOutputStream(destFile)); 59 60 int by = 0; 61 while ((by = bis.read()) != -1) { 62 bos.write(by); 63 } 64 65 bos.close(); 66 bis.close(); 67 } 68 69 // 基本字节流一次读写一个字节数组 70 private static void method2(File srcFile, File destFile) throws IOException { 71 FileInputStream fis = new FileInputStream(srcFile); 72 FileOutputStream fos = new FileOutputStream(destFile); 73 74 byte[] bys = new byte[1024]; 75 int len = 0; 76 while ((len = fis.read(bys)) != -1) { 77 fos.write(bys, 0, len); 78 } 79 80 fos.close(); 81 fis.close(); 82 } 83 84 // 基本字节流一次读写一个字节 85 private static void method1(File srcFile, File destFile) throws IOException { 86 FileInputStream fis = new FileInputStream(srcFile); 87 FileOutputStream fos = new FileOutputStream(destFile); 88 89 int by = 0; 90 while ((by = fis.read()) != -1) { 91 fos.write(by); 92 } 93 94 fos.close(); 95 fis.close(); 96 } 97 }
操作基本数据类型的流
可以读写基本类型的数据
数据输入流:DataInputStream
DataInputStream(InputStream in)
数据输出流: DataOutputStream
DataOutputStream(OutputStream out)
内存操作流: 用于处理临时存储信息的,程序结束,数据就从内存中消失
操作字节数组
ByteArrayInputStream
ByteArrayOutputStream
操作字符数组
CharArrayReader
CharArrayWriter
操作字符串
StringReader
StringWriter
打印流
字节打印流 PrintStream
字符打印流 PrintWriter
只有写数据的,没有读数据的,只能操作目的地,不能操作数据源
可以操作任意类型的数据
print() println()
如果启动了自动刷新,能够自动刷新
PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"),ture);
还是应该调用println()的方法才可以
这个时候不仅仅自动刷新了,还实现了数据的换行
该流是可以直接操作文本文件的
哪些流对象是可以直接操作文本文件的呢?
FileInputStream FileOutputStream
FileReader FileWriter
PrintStream PrintWriter
看API,查流对象的构造方法,如果同时有File类型和String类型的参数,一般来说就是可以直接操作文件的
基本流:能够直接读写文件的
高级流:在基本流的基础上提供了一些其他的功能
标准输入输出流
System类中的两个成员变量:
public static final InputStream in “标准”输入流。
public static final PrintStream out “标准”输出流。
InputStream is = System.in;
PrintStream ps = System.out;
随机访问流
不属于流,是Object类的子类,但它融合了InputStream和OutputStream的功能,支持对文件的随机访问读取和写入。
public RandomAccessFile(String name, String mode): 第一个参数是文件路径,第二个参数是操作文件的模式。模式一般常用‘rw’,既可以写数据也可以读数据