黑马程序员_IO流_3

来源:互联网 发布:极简装修 知乎 编辑:程序博客网 时间:2024/04/30 10:51

   ----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

1、字节流是由字节组成的,字节流是由字符组成的

2、输入流就是能连续从其中读取数据的对象,输出流刚刚相反,就是能连续写入数据到其中的对象。

由上面2点可以知道JAVA的IO流中有4大基类,分别为InputStream,OutputStream,Reader,Writer。他们都是抽象类。由这4个类派生出来的子类名称都是以父类名作为类名的后缀,以类的功能来作为类的前缀。

 

Writer子类必须实现的方法有 write(char[], int, int)、flush() 和 close()这3个方法也是最常用的方法。write()方法是将char[]数组中从第二个参数一直写到第三个参数。因为写入的参数会保存在流中,所以要调用flush()方法讲数据刷新到目的中。(一个字节构成不了要的数据)。因为Writer类要调用系统资源,所以要调用close()方法来关闭资源。FileWriter是个操作文件的Writer类。可以用来演示.

public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("FileWriterDemo.txt");fw.write("lailongwei");fw.flush();fw.close();Runtime.getRuntime().exec("notepad.exe FileWriterDemo.txt");}

FileWriter的构造函数中可以传入是否续写的参数。True表示续写。

 

Reader子类必须实现的方法只有 read(char[], int, int) 和 close()。read()方法读取一个字符。返回int类型,读到末尾返回-1。read(char[]),字符数组,用于存储读到的字符。返回读到的字符个数。FileReader是个操作文件的Reader类,和FileWriter对应。可以用来演示.

public static void main(String[] args) throws IOException {FileReader fr = new FileReader("FileWriterDemo.txt");char[] temp = new char[16];int len;while ((len = fr.read(temp)) > 0) {System.out.print(new String(temp, 0, len));}fr.close();}

 

因为write()方法和read()方法每个细小的操作都要去调用系统底层的方法所以效率低。这个时候就出现了缓存区。缓存区的出现是为了提高数据的读写效率,分别为BufferReaderBufferWriter。他们是修饰类。修饰类要被修饰对象作为构造函数的参数。BufferReader中有readLine()特有方法。BufferWriternewLine()这个特有方法。分别修改上面的两端代码如下:

public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("FileWriterDemo.txt");//fw.write("lailongwei");BufferedWriter bw = new BufferedWriter(fw);bw.write("lailongwei");bw.newLine();bw.flush();fw.close();bw.close();Runtime.getRuntime().exec("notepad.exe FileWriterDemo.txt");} public static void main(String[] args) throws IOException {FileReader fr = new FileReader("FileWriterDemo.txt");BufferedReader br = new BufferedReader(fr);//char[] temp = new char[16];String line;while ((line = br.readLine()) != null) {System.out.print(line);}fr.close();br.close();}

 

缓存类的close()就会调用被修饰对象的close()方法。newLine()方法的好处是,不同系统换行的表示方式可能不同。readLine()方法原理:无论是读一行还是读多个字符,其实最终都是在硬盘上一个一个的读取,所以最终都是使用的还是read()方法一次一个的读取。

 

上面的演示都没有对异常进行处理。IO流中的IO异常处理方式:在try外部建立应用,然后在try中赋值,finally里面进行close()。close要用try语句块,因为也会跑出异常。在关闭之前要判断流是否为空,为空就不必关闭,不然会抛出异常。示例如下:

public static void main(String[] args) {BufferedReader br = null;try {br = new BufferedReader(new FileReader("FileWriterDemo.txt"));String line;while ((line = br.readLine()) != null) {System.out.print(line);}} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}//char[] temp = new char[16];catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{try {br.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}} }

 

 

InputStream字节输入流,需要定义 InputStream 子类的应用程序必须总是提供返回下一个输入字节的方法read()这个方法返回一个int类型。低八位表示读取到的byte类型,返回-1表示已经读到了末尾)。InputStream的available()方法返回可以读取的字节数。FileInputStream是它的操作文件的子类。

OutputStream字节输出流,需要定义 OutputStream 子类的应用程序必须始终提供至少一种可写入一个输出字节的方法write()方法,就是read()方法的反操作FileOutputStream是它的操作文件的子类。OutputStream的flush并不会进行任何操作。因为他就是写入字节。

因为FileInputStream和FileOutputStream的效率都不高,所以要提高效率,BufferFileInputStream和BufferOutputStream来修饰,提高效率。下面通过键盘录入来演示

import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class BufferInDemo {public static void main(String[] args) {BufferedInputStream bis = null;BufferedOutputStream bos = null;try {bis = new BufferedInputStream(new FileInputStream("QQ.jpg"));bos = new BufferedOutputStream(new FileOutputStream("Q_Q.jpg"));byte[] bytes = new byte[1024];int len;while ((len = bis.read(bytes)) != -1){bos.write(bytes, 0, len);}} catch (FileNotFoundException e1) {// TODO Auto-generated catch blocke1.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{try {bis.close();bos.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println("复制成功");}}

 

InputStreamReader是字节流通向字符流的桥梁。而OutputStreamWriter是字符流通向字节流的桥梁。这两个桥梁的构造函数中可以选择需要解码或者编码的编码表。在存储时,如果需要加入指定的编码表。而指定的编码表只有转换流可以指定。所以要在转换流中填入指定的编码。下面通过键盘录入来演示:

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;public class InputStreamReaderDemo {public static void main(String[] args) {BufferedReader br = null;BufferedWriter bw = null;try {br = new BufferedReader(new InputStreamReader(System.in));bw = new BufferedWriter(new OutputStreamWriter(System.out));String line;while (true) {line = br.readLine();if (line.equals("over")) {break;}else {bw.write(line.toUpperCase());bw.flush();}}} catch (Exception e) {// TODO: handle exception}finally{try {br.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {bw.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}


RandomAccessFile这个类的实例支持对随机访问文件的读取和写入。它不是IO体系中的之类,不过在IO包中。内部封装了一个数组,而且通过指针对数组元素进行操作。可以通过getFilePointer获取指针位置。同时可以通过seek方法来改变指针的位置,其实,完成读写的原理就是内封装了字节输入流和输出流,通过构造函数可以看出该类是否能进行写入(如果模式为只读r,就不会创建文件,如果为rw就会在需要的时候创建)。seek()调整指针的位置。skipBytes()是跳过多少个字节,不能往回跳。通过文件切割来演示:
 

import java.io.File;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandomAccessFile;public class SplitFiltDemo {public static void main(String[] args) {File file = new File("D:\\网络图片\\mypicture.jpg");for (int i = 0; i < 4; i++) {new Thread(new Split(file, i)).start();}System.out.println("没问题");}}class Split implements Runnable{private File file;private int num;public Split(File file,int num){this.file = file;this.num = num;}@Overridepublic void run() {RandomAccessFile raf = null;RandomAccessFile raFile = null;try {raf = new RandomAccessFile("切个" + num + ".split", "rw");raFile = new RandomAccessFile(file, "r");byte[] temp = new byte[1024];int len = 0;raFile.seek(file.length() / 4 * num);while ((len = raFile.read(temp)) != -1 && raFile.getFilePointer() <= (file.length() / 4 * (num + 1))) {raf.write(temp, 0, len);}} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{try {raf.close();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}try {raFile.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}


              ObjectOutputStream是讲对象输出,不过这个对象必须要实现Serializable接口,这个借口中并没有具体的方法,是个标记接口.接口中有个序列号.对象的系列话指的是将堆内存中的对象保存在可以持续保存的地方。可以通过ObjectInputStream方法来重构对象。注意,静态成员不会被系列化,如果想让非静态成员也不参与系列化,这个成员就要用transient来修饰。




     ----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------

详情请查看:http://edu.csdn.net/heima

 

                                   


原创粉丝点击