关闭

慎用InputStream的read()方法

标签: AndroidInputStreamRead
978人阅读 评论(0) 收藏 举报
分类:

     InputStream 此抽象类是表示字节输入流的所有类的超类。

          我们从输入流中读取数据最常用的方法基本上就是如下 3  read() 方法了:

         1  read () 方法,这个方法 从输入流中读取数据的下一个字节。返回 0  255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1 

         2  read (byte[] b,int off,int len) 方法, 将输入流中最多 len 个数据字节读入 byte 数组。尝试读取 len 个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数。

         3  read (byte[] b) 方法, 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数。

         第一个方法典型的确定就是处理效率低,不是某些特殊情况,很少使用它,下面说说第 2 个方法跟第 3 个方法,第 3 个方法的本本质其实就是第 2 个方法的特殊情况, 效果等同于:

          read(b, 0, b.length)

所以这里把他们放着一起讨论。

         从第 2 个方法的 API 文档说明来看:“ 将输入流中最多 len 个数据字节读入 byte 数组。尝试读取 len 个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数。”,最多读取 len 个字节,这究竟是何意?API 文档并没有详细说明。是不是就意味着有可能(注意这里是有可能而不是一定,)读取不到 len 个字节呢?答案是“是的”。虽然造成这种情况的原因是什么个人并不知道,但是我们可以通过例子来发现这种情况,下面是源代码(由于只是简单的示例,所以代码也就随便写了):

 

ServerSocket 端:

 

Java代码  收藏代码
  1. package myspider;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.net.ServerSocket;  
  8. import java.net.Socket;  
  9.   
  10. /** 
  11.  * 
  12.  * @author mark 
  13.  */  
  14. public class MyServerSocket {  
  15.   
  16.     public static void main(String[] args) throws IOException {  
  17.         ServerSocket ss = new ServerSocket(8888);  
  18.         System.out.println("runing");  
  19.         while (true) {  
  20.             byte[] b = new byte[22480];  
  21.             int readBytes = 0;  
  22.             Socket s = ss.accept();  
  23.             InputStream is = s.getInputStream();  
  24.             while (readBytes < 22480) {  
  25.                 int read = is.read(b, readBytes, 22480 - readBytes);  
  26.                 System.out.println(read);  
  27.                 if (read == -1) {  
  28.                     break;  
  29.                 }  
  30.                 readBytes += read;  
  31.             }  
  32.             File f = new File("F:\\project\\bocln_nacec\\xml\\ey.xml");  
  33.             if (!f.exists()) {  
  34.                 f.createNewFile();  
  35.                 System.out.println("creat " + f.toString());  
  36.             }  
  37.             FileOutputStream fos = new FileOutputStream(f);  
  38.             fos.write(b, 0, readBytes);  
  39.             fos.flush();  
  40.             fos.close();  
  41.             System.out.println("complete");  
  42.             is.close();  
  43.             s.close();  
  44.         }  
  45.     }  
  46. }  

 

Socket 端:

 

Java代码  收藏代码
  1. package myspider;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.io.OutputStream;  
  8. import java.net.Socket;  
  9. import java.net.UnknownHostException;  
  10.   
  11. /** 
  12.  * 
  13.  * @author mark 
  14.  */  
  15. public class MySocket {  
  16.   
  17.     public static void main(String[] args) throws UnknownHostException, IOException {  
  18.         Socket s = new Socket("127.0.0.1"8888);  
  19.         OutputStream os = s.getOutputStream();  
  20.         File f = new File("F:\\project\\bocln_nacec\\xml\\ye.xml");  
  21.         InputStream is = new FileInputStream(f);  
  22.         byte[] b = new byte[22480];  
  23.         int i = is.read(b);  
  24.         is.close();  
  25.         os.write(b, 0, i);  
  26.         os.flush();  
  27.         os.close();  
  28.         s.close();  
  29.     }  
  30. }  

 

 

先运行 MyServerSocket ,让后多次运行 MySocket ,这是控制台的输出结果( ye.xml 文件长度为 20389 ):

 

Java代码  收藏代码
  1. runing  
  2. 20389  
  3. -1  
  4. creat F:\project\bocln_nacec\xml\ey.xml  
  5. complete  
  6. 20389  
  7. -1  
  8. complete  
  9. 20389  
  10. -1  
  11. complete  
  12. 20389  
  13. -1  
  14. complete  
  15. 20389  
  16. -1  
  17. complete  
  18. 20389  
  19. -1  
  20. complete  
  21. 20389  
  22. -1  
  23. complete  
  24. 20389  
  25. -1  
  26. complete  
  27. 20389  
  28. -1  
  29. complete  
  30. 20389  
  31. -1  
  32. complete  
  33. 20389  
  34. -1  
  35. complete  
  36. 8760  
  37. 11629  
  38. -1  
  39. complete  
  40. 20389  
  41. -1  
  42. complete  
  43. 20389  
  44. -1  
  45. complete  
  46. 20389  
  47. -1  
  48. complete  
  49. 20389  
  50. -1  
  51. complete  
  52. 20389  
  53. -1  
  54. complete  
  55. 20389  
  56. -1  
  57. complete  
  58. 3760  
  59. 620  
  60. 16009  
  61. -1  
  62. complete  
  63. 20389  
  64. -1  
  65. complete  
  66. 20389  
  67. -1  
  68. complete  
  69. 20389  
  70. -1  
  71. complete  
  72. 20389  
  73. -1  
  74. complete  
  75. 8760  
  76. 11629  
  77. -1  
  78. complete  
  79. 20389  
  80. -1  
  81. complete  
  82. 20389  
  83. -1  
  84. complete  
  85. 8760  
  86. 11629  
  87. -1  
  88. complete  
  89. 20389  
  90. -1  
  91. complete  
  92. 20389  
  93. -1  
  94. complete  
  95. 8760  
  96. 11629  
  97. -1  
  98. complete  
  99. 20389  
  100. -1  
  101. complete  
  102. 20389  
  103. -1  
  104. complete  
  105. 20389  
  106. -1  
  107. complete  
  108. 20389  
  109. -1  
  110. complete  
  111. 20389  
  112. -1  
  113. complete  
  114. 20389  
  115. -1  
  116. complete  
  117. 20389  
  118. -1  
  119. complete  
  120. 20389  
  121. -1  
  122. complete  
  123. 20389  
  124. -1  
  125. complete  
  126. 20389  
  127. -1  
  128. complete  
  129. 20389  
  130. -1  
  131. complete  
  132. 20389  
  133. -1  
  134. complete  
  135. 20389  
  136. -1  
  137. complete  
  138. 20389  
  139. -1  
  140. complete  

 

 

         通过观察发现,在大多数情况下,我们能够用 is.read(b, readBytes, 22480 - readBytes) 一次性就读完整个文件,但是还是有极少数情况,我们需要两次(如36、37两行)甚至两次以上(如58、59、60)调用 is.read(b, readBytes, 22480 - readBytes) 方法才能把整个文件读取完。这里由于文件最长只有 20389 ,所以我们能读到的最大字节数也就是 20389 而不会是 22480 了。

         那么我们怎样写代码才能保证在数据流没有到达末尾的情况下读取到自己想要的长度的字节数据呢?我们可以这样写:   

 

Java代码  收藏代码
  1. int readBytes=0;  
  2.   
  3. Byte[] b=new byte[1024]//1024可改成任何需要的值  
  4.   
  5. int len=b.length;  
  6.   
  7. while (readBytes < len) {  
  8.   
  9.                 int read = is.read(b, readBytes, len - readBytes);  
  10.   
  11.                //判断是不是读到了数据流的末尾 ,防止出现死循环。  
  12.   
  13.                 if (read == -1) {  
  14.   
  15.                     break;  
  16.   
  17.                 }  
  18.   
  19.                 readBytes += read;  
  20.   
  21.             }  
0
0
查看评论

InputStream的多种使用

以前写东西,尤其是网络传输方面总会碰到将某种格式的文本或者图片等转幻成数据流的方式来传输,那时候用的就直接网上找点就粘贴,也没什么搞懂到底是怎么个机理。后来抽点空就死啃了点这方面的文章,稍微懂了点,特意分享一下。      InputStream  ...
  • u010271952
  • u010271952
  • 2016-09-02 09:34
  • 1705

java的InputStream和OutputStream的理解

1、在java中stream代表一种数据流(源),javaio的底层数据元,---(想像成水龙头)2、任何有能力产生数据流(源)的javaio对象就可以看作是一个InputStream对象既然它能产生出数据,我们就可以将数据取出,java对封装的通用方法就read()方法了--(出水龙头)3、任何有...
  • brave1
  • brave1
  • 2005-08-07 17:45
  • 19504

Java IO-InputStream家族 -装饰者模式

在学习java.io.*包的时候,InputStream那一群类很让人反感,子类繁多,使用起来也非常奇怪。我们想以缓存的方式从文件中读取字节流。要先创建一个FileInputStream,然后放入BufferedInputStream构造函数中去创建BufferedInputStream。完成这些工...
  • pomony1
  • pomony1
  • 2017-05-30 11:01
  • 1189

重复读取InputStream的方法

1.为什么InputStream不能重复读取首先,熟悉Java的人可能都知道,Java中的Inputstream是不能重复读取的。 但是有没有想过,InputStream为什么不能重复读呢? 其实要回答“为什么”这个问题很简单,就是人家接口就是这么设计的,不能重复读。 所以今天要讨论的问题更像是...
  • u014656173
  • u014656173
  • 2017-08-16 22:30
  • 540

I/O流之进步认识、InputStream以及FileInputStream

File类: 用于描述一个文件或者文件夹的。 通过File对象,我们可以读取文件或者文件夹的属性数据,如果我们需要读取文件的内容数据,那么我们需要使用IO流技术。IO流(Input Output) IO流解决问题: 解决设备与设备之间的数据传输问题。 内存—>硬盘 硬盘—>内存...
  • qq_34944851
  • qq_34944851
  • 2016-07-29 22:40
  • 4318

InputStream read()方法详解

在Java7中,InputStream被定义为一个抽象类,相应的,该类下的read()方法也是一个抽象方法,这也就意味着必须有一个类继承InputStream并且实现这个read方法。 查阅Java7 API,我们可以看到,在InputStream中定义了三个重载的read()方法: 但是在...
  • u010276761
  • u010276761
  • 2016-09-28 19:03
  • 11090

InputStream方法详解

字节输入流的基础类InputStream和OutputStream有许多相同的地方,也有许多不同点,需注意区分。 概要 与OutputStream相比,这个抽象类定义的方法要多一些。读入数据有些时候的确比较麻烦。读入数据的时候,需要判断数据源是否有数据,是否结束等等一些情况,相对复杂。这个抽象类...
  • bingduanlbd
  • bingduanlbd
  • 2013-01-30 17:25
  • 12885

InputStream读取数据问题

1. 关于InputStream.read()      在从数据流里读取数据时,为图简单,经常用InputStream.read()方法。这个方法是从流里每次只读取读取一个字节,效率会非常低。     更好的方法是用...
  • qq_21033663
  • qq_21033663
  • 2016-05-25 17:27
  • 1495

重复读取InputStream的方法

在上篇博客中我们已经知道了Java的InputStream是不能重复被读取的。  但是在有的场合中,我们需要重复利用InputStream的数据。  比如:  1. 一个office word文件流,我需要首先读取InputStream中的前一些字节来判断word...
  • Java_Mr_Zheng
  • Java_Mr_Zheng
  • 2016-09-07 10:34
  • 3820

java InputStream读取不到数据

java InputStream读取数据问题 博客分类:  JDK javaioInputStreambyteavailable  首先请查看一下JavaAPI,可以看到InputStream读取流有三个方法,分别为read(),read(byte...
  • q4358155
  • q4358155
  • 2017-05-16 19:31
  • 926
    个人资料
    • 访问:222181次
    • 积分:2778
    • 等级:
    • 排名:第15239名
    • 原创:19篇
    • 转载:228篇
    • 译文:0篇
    • 评论:9条
    最新评论