黑马程序员---Java IO流(二)

来源:互联网 发布:好用的化妆品 知乎 编辑:程序博客网 时间:2024/05/23 00:07
---------------------- Android开发、java培训、期待与您交流! --------------------------------------------

*—*字节流

         字节流用于操作二进制数据的流,如:图片、MP3文件。

两个抽象基类InputStream和OutputStream有两个子类FileInputStream和FileOutputStream

1、FileInputStream:字节数据读取流。必须处理的异常FileNotFoundException。

构造方法:

        FileInputStream(String filename):通过打开一个到实际文件的连接来创建一个字节读取流,该文件通过文件系统中的路径名name 指定。

普通方法:

        int read() :从此输入流中读取一个数据字节。 

        int read(byte[] b) :从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 

        void close() :关闭此文件输入流并释放与此流有关的所有系统资源。

2、FileOutputStream:字节数据写入流。必须处理的异常FileNotFoundException。

构造方法:

        FileOutputStream(String name): 创建一个向具有指定名称的文件中写入数据的输出文件流。
        FileOutputStream(String name, boolean append): 创建一个向具有指定 name 的文件中写入数据的输出文件流 。指定的append值决定是否从文件末尾开始写入。

普通方法:

        void write(byte[] b):将 b.length 个字节从指定 byte 数组写入此文件输出流中。
        void write(byte[] b, int off, int len): 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
        void write(int b):将指定字节写入此文件输出流。
        void close():关闭此文件输出流并释放与此流有关的所有系统资源。 

练习:

复制一个图片
思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。

import java.io.*;class  CopyPic{public static void main(String[] args) {FileOutputStream fos = null;FileInputStream fis = null;try{fos = new FileOutputStream("c:\\2.bmp");fis = new FileInputStream("c:\\1.bmp")byte[] buf = new byte[1024];int len = 0;while ((len=fis.read(buf)!=-1){fos.write(buf,0,len);}}catch (IOException e){throw new RuntimeException("复制文件失败");}finally{try{if(fis!=null)fis.close();}catch (IOException e){throw new RuntimeException("读取关闭失败");}try{if(fos!=null)fos.close();}catch (IOException e){throw new RuntimeException("写入关闭失败");}}}}
*—*字节流缓冲区:
缓冲区技术的出现对数据读写效率有很大的提高

对应类

BufferedInputStream

BufferedOutputStream

① 缓冲区要结合流才可以使用。

② 在流的基础上对流的功能进行了增强。

练习:

通过缓冲区技术复制MP3文件。

import java.io.*;class  CopyMp3{public static void main(String[] args) throws IOException{long start = System.currentTimeMillis();copy_1();long end = System.currentTimeMillis();System.out.println((end-start)+"毫秒");}//通过字节流的缓冲区完成复制。public static void copy_1()throws IOException{BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3"));BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));int by = 0;while ((by=bufis.read())!=-1){bufos.write(by);}bufos.close();bufis.close();}}<strong><span style="font-size:18px;"></span></strong>

自定义字节输入流缓冲区

首先要理解字节入流缓冲区类中read()方法的工作原理:

       内部实际上是字节流InputStream中的读一个字节存储到一个自定义的字节数组中的read(byte[] ch)方法进行操作,当读到一个字节的数据就会储存到自定义的字节数组中并返回读到数据个数,直到读完会返回-1。需要定义两个int类型的变量分别表示read方法返回的数据的个数和字节数组的索引。当read方法返回的值为0表示还未读到数据,会继续读取。当read方法返回大于0的值时,表示读到了数据就会向自定义的字节数组中存储,相应的字节数组索引值会增加会返回相应的字节数组值。当read方法返回小于0的值,表示字节流以读取到文件末尾,则返回-1,终止自定义read方法

注意:

读取时字节数据有可能数据中就会有终止标记-1,未读完数据就有可能停止读取,为解决这个问题需要将返回返回数据&(与)255(十进制)或者0xff(十六进制)。

read方法它在向上提升,在前面补零,保证不是—1的那种情况的发生,而write()方法它其实在做一个抢转动作,将最低的八位写出去了,剩下的砍掉了,保证了原数据的原样性。

import java.io.*;class  MyBufferedInputStream{private InputStream in;private byte[] buf = new byte[1024];private int pos = 0,count = 0;MyBufferedInputStream(InputStream in){this.in = in;}//一次读一个字节,从缓冲区(字节数组)获取。public int myRead(){//通过in对象读取硬盘上的数据,并存储buf中。if(count==0){count = in.read(buf);if(count<0)return -1;pos = 0;byte b = buf[pos];count--;pos++;return b&255;}else if(count>0){byte b = buf[pos];count--;pos++;return b&0xff;}return -1;}public void myClose()throws IOException{in.close();}}

练习:

写一个键盘录入的实例代码

System.out: 对应的是标准输出设备,控制台。
System.in:对应的标准输入设备:键盘。

需求:
通过键盘录入数据。
当录入一行数据后,就将该行数据的大写进行打印。
如果录入的数据是over,那么停止录入。

import java.io.*;class  ReadIn{public static void main(String[] args) {InputStream in = System.in;StringBuilder sb = new StringBuilder();while (true){int ch = in.read();if(ch=='\r')continue;if(ch=='\n'){String s = sb.toString();if("over".equals(s))break;System.out.println(s.toUpperCase());sb.delete(0,sb.length());}elsesb.append((char)ch);}}}
       通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。
也就是readLine方法。能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?
readLine方法是字符流BufferedReader类中的方法。而键盘录入的read方法是字节流InputStream的方法。那么能不能将字节流转成字符流在使用字符流缓冲区的readLine方法呢?可以,通过转换流InputStreamReader和OutputStreamWriter进行转换,转换流InputStreamReader可以进将字节输入流转换为字符输入流,转换流OutputStreamWriter可以将字节输出流转换为字符输出流。

import java.io.*;class  TransStreamDemo{public static void main(String[] args) {System.setIn(new FileInputStream("PersonDemo.java"));System.setOut(new PrintStream("zzz.txt"));//获取键盘录入对象。//InputStream in = System.in;//将字节流对象转成字符流对象,使用转换流。InputStreamReader//InputStreamReader isr = new InputStreamReader(in);//为了提高效率,将字符流进行缓冲区技术高效操作。使用BufferedReader//BufferedReader bufr = new BufferedReader(isr);                //三句代码可以写成一句BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//OutputStream out = System.out;//OutputStreamWriter osw = new OutputStreamWriter(out);//BufferedWriter bufw = new BufferedWriter(osw);                //三句代码可以写成一句                BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));String line = null;while ((line=bufr.readLine())!=null){if("over".equals(line))break;bufw.write(line.toUpperCase());bufw.newLine();bufw.flush();}bufr.close();}}

【总结】

字节流与字符流不同之处就是读取的数据不同而已,字节流读取的是字节数据也就是二进制数据,如:图片、多媒体数据。字符流读取的数据当然是字符数据,文本数据。字节流和字符流有很多记忆性的规律,字节流有两个抽象的类InputStream和OutputStream,并各有一个子类FileInputstream和FileOutputStream,子类类名都是以父类名为结尾,开头相同都是File。字符流也有两个抽象类Read和Write,并各有一个子类FileReader和FileWriter,子类类名都是以父类类名为结尾,开头相同都是File。它们的缓冲区流只需在它们父类的前面加上Buffered,字节流的缓冲区流为BufferedInputStream和BufferedOutputStream,字符流的缓冲区流为BufferedReader和BufferedWriter。这样记忆是不是很容易记住呢?




Android开发、java培训、期待与您交流! ----------------------详细请查看:www.itheima.com
0 0
原创粉丝点击