你的位置:首页 > Java教程

[Java教程]I/O流——字节流


流的概念

流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以使文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。

流的分类

①   流按其流向分为“输入流”和“输出流”。

②   流按数据传输单位分为“字节流”和“字符流”。

a)         “字节流”用来读写8位二进制的字节。

b)         “字符流”用来读写16位二进制字符。

③   流按功能分为“节点流”和“过滤流”。

a)         “节点流”用于直接操作目标设备的流。例如:磁盘或一块内存区域。

b)         “过滤流”是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。

 

字节流

字节流类用于向字节流读取8位二进制的字节。一般地,字节流主要用于读写诸如图像或声音等二进制数据。

字节流类以InputStream和OutputStream为顶层类。它们都是抽象类。

一、InputStream

①     InputStream是定义了字节输入流的抽象类。

②     InputStream中定义的方法

a)         public abstract int read()

b)         public int read(byte[] b)

c)         public int read(byte[] b,int off,int len)

d)         public long skip(long n)

e)         public int available()

f)          public void close()

二、OutputStream

① OutputStream是定义了字节输出流的抽象类。

② 该类所有方法返回void值,在出错情况下抛IOException异常

③ OutputStream中定义的方法

g)         public abstract void write(int b)

h)         public void write(byte[] b)

i)           public void write(byte[] b,int off,int len)

j)           public void flush()

k)         public void close()

 

每个抽象类都有多个具体的子类,这些子类对不同的外设进行处理,例如磁盘文件,网络连接,甚至是内存缓冲区。

三、FileInputStream

① FileInputStream类表示能从文件读取字节的InputStream类

② 构造方法

a)         FileInputStream(String filePath)

b)         FileInputStream(File fileObj)

四、FileOutputStream

① FileOutputStream表示能向文件写入字节的OutputStream类

② 构造方法

a)         FileOutputStream(String filePath)

b)         FileOutputStream(File fileObj)

c)         FileOutputStream(String filePath,boolean append)

示例:拷贝指定文件到指定目录

 1 class FileCopyUtil { 2   public static void copyFile(File src, File dst) throws IOException { 3     FileInputStream fis = new FileInputStream(src); 4     FileOutputStream fos = new FileOutputStream(dst); 5     long time1 = System.currentTimeMillis(); 6     int data = -1; 7     while ((data = fis.read()) != -1) { 8       fos.write(data); 9     }10     fis.close();11     fos.close();12     long time2 = System.currentTimeMillis();13     System.out.println("复制完成,共花费:" + (time2 - time1) + "毫秒");14   }15 }

主方法:

1     try {2       FileCopyUtil.copyFile(new File("d:/zhangsan/tu.png"), new File("e:/fuzhi.png"));3     } catch (IOException e) {4       e.printStackTrace();5     }

输出结果

复制完成,共花费:1545毫秒

单一张71K的图片就花费了1545毫秒,由此可见效率是极低的,因为它是读一个写一个,我们可以换种思路,先全部读到一个缓冲区,再将内容一次性写入。这里就好比喝水时一滴一滴地喝还是接到杯子里再喝。

改造下方法,如下:

 1 class FileCopyUtil { 2   public static void copyFile(File src, File dst) throws IOException { 3     FileInputStream fis = new FileInputStream(src); 4     FileOutputStream fos = new FileOutputStream(dst); 5     byte[] buff = new byte[1024 * 1024];// 创建一个1M大小的缓冲区,用来存放输入流中的字节 6     int len = 0;// 用来保存实际读到的字节数 7     long time1 = System.currentTimeMillis(); 8     while ((len = fis.read(buff)) != -1) { 9       fos.write(buff, 0, len);10     }11     fis.close();12     fos.close();13     long time2 = System.currentTimeMillis();14     System.out.println("复制完成,共花费:" + (time2 - time1) + "毫秒");15   }16 }

同样读取那张图片,输出结果:

复制完成,共花费:3毫秒

再复制一个8M的mp3格式文件,输出结果:

复制完成,共花费:39毫秒

 

五、ByteArrayInputStream

①ByteArrayInputStream是把字节数组当成源的输入流。

②两个构造方法,每个都需要一个字节数组提供数据源:

a)       ByteArrayInputStream(byte array[])

b)       ByteArrayInputStream(byte array[],int start,int numBytes)

1     String str="hello,HangZhou";2     ByteArrayInputStream bis=new ByteArrayInputStream(str.getBytes());3     int data=-1;4     while((data=bis.read())!=-1)5     {6       System.out.println((char)data);7     }

输出结果:

h e l l o , H a n g Z h o u

 

六、ByteArrayOutputStream

①ByteArrayOutputStream是把字节数组当作目标的输出流。

②两个构造方法:

a)       ByteArrayOutputStream()

创建一个新的byte数组输出流

b)       ByteArrayOutputStream(int numBytes)

创建一个新的byte数组输出流,具有指定大小缓冲区(字节为单位)

 1     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 2     bos.write(97); 3     bos.write(65); 4     try { 5       bos.write("hello,word".getBytes()); 6     } catch (IOException e) { 7       e.printStackTrace(); 8     } 9     byte[] buff = bos.toByteArray();10     for (byte b : buff) {11       System.out.print((char)data+" ");12     }13 14     FileOutputStream fos=new FileOutputStream("d://aa.txt", true);15     bos.writeTo(fos);//把ByteArrayOutputStream内部缓冲区的数据写到对应的文件输出流中16     fos.close();

输出结果:

aAhello,word

并会在d盘下创建一个aa.txt文件,里面内容为输出结果的内容,再次执行将追加一次执行结果的内容。

 

过滤流

① 过滤流仅仅是为底层透明地提供扩展功能的输入流(输出流)的包装。这些流一般由普通类的方法(即过滤流的一个父类)访问。

② 过滤字节流FilterInputStream和FilterOutputStream。构造方法:

a)  FilterInputStream(InputStream is)

b)  FilterOutputStream(OutputStream os)

③ 这些类提供的方法和InputStream及OutputStream类的方法相同。

④ 常用的过滤流BufferedInputStream和BufferedOutputStream,DataInputStream和DataOutputStream

 

BufferedInputStream,BufferedOutputStream用法举例

使用过滤流来改写上面的复制方法

 1 class FileUtil { 2   public static void copyFile(File src, File dst) throws IOException { 3     FileInputStream fis = new FileInputStream(src); 4     FileOutputStream fos = new FileOutputStream(dst); 5     BufferedInputStream bis=new BufferedInputStream(fis); 6     BufferedOutputStream bos=new BufferedOutputStream(fos); 7      8     int data = 0;// 用来保存实际读到的字节数 9     long time1 = System.currentTimeMillis();10     while ((data = bis.read()) != -1) {11       bos.write(data);12     }13     bis.close();14     bos.close();15     long time2 = System.currentTimeMillis();16     System.out.println("复制完成,共花费:" + (time2 - time1) + "毫秒");17   }18 }

主方法:

1     try {2       FileUtil.copyFile(new File("d:/zhangsan/Closer To Me.mp3"), new File(3           "e:/fuzhi.mp3"));4     } catch (IOException e) {5       e.printStackTrace();6     }7   }

复制同样的一首歌,输出结果:

复制完成,共花费:905毫秒

时间增加了很多,但也比文件直接读写快了不少。Buffered中自带一个8k左右的缓冲区。

 

DataInputStream和DataOutputStream用法举例:

写入文件:

 1     String name="zhangsan"; 2     int age=10; 3     boolean flag=true; 4     char sex='男'; 5     double money=123.45; 6      7     DataOutputStream dos=new DataOutputStream(new FileOutputStream("d:/b.txt")); 8     dos.writeUTF(name); 9     dos.writeInt(age);10     dos.writeBoolean(flag);11     dos.writeChar(sex);12     dos.writeDouble(money);13     dos.close();

打开b.txt后发现有乱码,那是因为写进去的是二进制

 

读文件:

1     DataInputStream dis=new DataInputStream(new FileInputStream("d:/b.txt"));2     //读的顺序必须与写入的顺序一致3     System.out.println(dis.readUTF());4     System.out.println(dis.readInt());5     System.out.println(dis.readBoolean());6     System.out.println(dis.readChar());7     System.out.println(dis.readDouble());8     dis.close();

输出结果:

zhangsan

10

true

123.45

 

过滤流总结:

BufferedInputStream与BufferedOutputStream

需要使用已经存在的节点流来构造,提供缓冲的读写,提高了读写的效率。

DataInputStream与DataOutputStream

数据输入输出流允许应用程序读写基本Java数据类型。应用程序可以使用数据输出流写入,稍后由数据输入流读取。读写顺序要保持一致。




青海旅游最佳时间青海自驾游最佳路线青海旅游多少钱青海旅游报价价格青海旅游团报价2015元旦广州哪里有活动?广州元旦带孩子家人好玩的地方有哪些? 2015锦绣中华元旦活动?元旦深圳锦绣中华民俗村门票优惠价格? 冰雪撒欢季 你不知道的黑龙江民族美食风向标(组图) 2015顺德长鹿农庄元旦活动?元旦长鹿农庄门票优惠价格? 惠州大亚湾旅游吃在哪里?大亚湾哪里有烧烤? 惠州大亚湾旅游度假去哪玩好?大亚湾有没有漂流水上乐园的地方? 惠州大亚湾旅游景点有哪些?惠州大亚湾海边旅游景点推荐? 让山水为真爱作证 第十一届仙女湖爱情文化旅游节 松涛水库:享有“天湖”盛誉的高山天池 【大理旅游】—大理旅游攻略 北京商场七夕购物打折活动信息汇总 海南八音乐器:险些失传的海南本土八音 《下一站说爱你》的拍摄地在哪里?讲述了什么故事? 香港的治安好吗?遇到危险,要怎样报警? 《初恋这件小事》的拍摄地在哪里?拍摄地附近有什么景点? 在泰国的中国人会看泰国剧吗?泰国人一般喜欢看什么样的电视剧和电影? 552-0203-802F Datasheet 552-0203-802F Datasheet 552-0203F Datasheet 552-0203F Datasheet 552-0210 Datasheet 552-0210 Datasheet 从浙江跟团到香港旅游 从浙江跟团到香港旅游 从浙江跟团到香港旅游 佳木斯跟团香港旅游 佳木斯跟团香港旅游 佳木斯跟团香港旅游 浙江跟团去香港 浙江跟团去香港 浙江跟团去香港