`
ouyangfei0426
  • 浏览: 127682 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

慎用InputStream的read()方法

    博客分类:
  • java
阅读更多

 

          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 端:

 

package myspider;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 *
 * @author mark
 */
public class MyServerSocket {

    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(8888);
        System.out.println("runing");
        while (true) {
            byte[] b = new byte[22480];
            int readBytes = 0;
            Socket s = ss.accept();
            InputStream is = s.getInputStream();
            while (readBytes < 22480) {
                int read = is.read(b, readBytes, 22480 - readBytes);
                System.out.println(read);
                if (read == -1) {
                    break;
                }
                readBytes += read;
            }
            File f = new File("F:\\project\\bocln_nacec\\xml\\ey.xml");
            if (!f.exists()) {
                f.createNewFile();
                System.out.println("creat " + f.toString());
            }
            FileOutputStream fos = new FileOutputStream(f);
            fos.write(b, 0, readBytes);
            fos.flush();
            fos.close();
            System.out.println("complete");
            is.close();
            s.close();
        }
    }
}

 

Socket 端:

 

package myspider;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 *
 * @author mark
 */
public class MySocket {

    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket s = new Socket("127.0.0.1", 8888);
        OutputStream os = s.getOutputStream();
        File f = new File("F:\\project\\bocln_nacec\\xml\\ye.xml");
        InputStream is = new FileInputStream(f);
        byte[] b = new byte[22480];
        int i = is.read(b);
        is.close();
        os.write(b, 0, i);
        os.flush();
        os.close();
        s.close();
    }
}

 

 

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

 

runing
20389
-1
creat F:\project\bocln_nacec\xml\ey.xml
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
8760
11629
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
3760
620
16009
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
8760
11629
-1
complete
20389
-1
complete
20389
-1
complete
8760
11629
-1
complete
20389
-1
complete
20389
-1
complete
8760
11629
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete
20389
-1
complete

 

 

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

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

 

int readBytes=0;

Byte[] b=new byte[1024]//1024可改成任何需要的值

int len=b.length;

while (readBytes < len) {

                int read = is.read(b, readBytes, len - readBytes);

               //判断是不是读到了数据流的末尾 ,防止出现死循环。

                if (read == -1) {

                    break;

                }

                readBytes += read;

            }
分享到:

相关推荐

    Socket中InputStream的read方法的阻塞特性

    Socket中的InputStream的`read`方法是Java网络编程中一个核心的概念,它在处理客户端与服务器之间的数据传输时起着至关重要的作用。`read`方法的阻塞特性是其设计的一个重要特点,也是理解多线程和并发编程的关键点...

    将输出流OutputStream转化为输入流InputStream的方法

    接着,我们调用`convertOutputStreamToInputStream`方法,将`out`转换为`InputStream`,并命名为`in`。最后,我们从`in`中读取数据并打印出来,恢复了原始写入的数据。 需要注意的是,这种转换方法仅适用于`...

    springboot 解决InputStream只能读取一次的问题

    我们可以创建一个自定义的`HttpServletRequestWrapper`子类,重写`getInputStream()`方法,使其返回一个可以重复读取的`InputStream`。 以下是一个简单的自定义`HttpServletRequestWrapper`示例: ```java import ...

    java InputStream读取数据问题

    - `read()`方法:返回下一个字节的数据,如果到达流的末尾则返回-1。 - `read(byte[] buffer)`:将数据读入提供的缓冲区,返回实际读取的字节数。 - `skip(long n)`:跳过指定数量的字节,但不读取它们。 2. **...

    Java中InputStream类.pdf

    作为抽象类,`InputStream`定义了一系列基本的方法来读取字节数据,这些方法由其子类进行具体实现。`InputStream`的出现是为了提供一个统一的接口,方便开发者处理各种不同类型的输入数据流。 **1. 抽象类与继承...

    Blob、InputStream、byte 互转

    本文介绍了`Blob`、`InputStream`、`byte[]`之间的相互转换方法,并给出了详细的代码示例。这些转换方法在实际开发中非常实用,特别是在处理数据库中的二进制数据时。通过以上方法,开发者可以灵活地进行不同数据...

    原理讲解-ServletInputStream.readLine(byte[] b, int off, int len) 方法

    `readLine(byte[] b, int off, int len)` 方法是 `ServletInputStream` 提供的一个方法,用于读取输入流中的一行数据。这个方法在处理文本数据时非常有用,因为它可以方便地按行读取数据,而不仅仅是单个字节。 在...

    JAVA语言中read方法分析

    其中,`InputStream`及其子类主要用于输入数据,例如通过键盘输入数据时,`InputStream`类中的`read`方法是最常见的选择。 #### 二、`read`方法详解 `read`方法作为`InputStream`类的核心方法之一,在JAVA中用于从...

    IO流文档InputStream / OutputStream

    InputStream是所有输入流的抽象超类,它提供了基本的读取方法,如read()、read(byte[] b)等。InputStream有多种实现类,如FileInputStream、PipedInputStream、FilterInputStream等,每种实现类都有其特定的读取方式...

    INPUTSTREAM

    在Java I/O系统中,`InputStream` 提供了从各种数据源读取字节数据的基本方法。这篇博客文章可能详细解析了 `InputStream` 类及其在实际开发中的应用。 在Java中,`InputStream` 是一个抽象类,位于 `java.io` 包下...

    关于InputStream和OutputStream详细讲解

    关于InputStream和OutputStream关于InputStream和OutputStream关于InputStream和OutputStream关于InputStream和OutputStream

    InputStream与OutputStream及File间互转

    下面我们将详细探讨`InputStream`、`OutputStream`以及它们与`File`之间的转换方法。 1. `InputStream`与`File`的转换: 当我们需要从文件中读取数据时,可以使用`FileInputStream`类,它是`InputStream`的一个...

    InputStream

    读取网络字节流 php stream 二进制

    SocketInputStream.java

    深入剖析tomcat第三章SocketInputStream源码 * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/StringManager.java,v 1.2 2001/07/22 20:25:14 pier Exp $ * $Revision: 1.2...

    Java实现inputstream流的复制代码实例

    InputStream 的主要方法有: * `read()`:读取一个字节 * `read(byte[] b)`:读取多个字节到字节数组中 * `close()`:关闭输入流 InputStream 的限制 InputStream 对象有一个限制:它只能读取一次。也就是说,...

    inputstream读取数据的问题

    inputstream读取数据的问题,对你的file的帮组是很大的。

    Java SE程序 文件的拷贝InputStream类

    Java SE程序 文件的拷贝InputStream类Java SE程序 文件的拷贝InputStream类Java SE程序 文件的拷贝InputStream类Java SE程序 文件的拷贝InputStream类Java SE程序 文件的拷贝InputStream类Java SE程序 文件的拷贝...

    通过jsoup,输入流InputStream爬取图片PaQuPic.rar,有意者入

    while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } } ``` 6. **处理输入流和输出流**:在处理`InputStream`和`OutputStream`时,确保它们都被正确关闭,避免资源泄漏。这里...

    java 文件存储 Inputstream outputstream reader writer的用法

    例如,我们通常用它来从文件、网络或内存中读取数据。相对应的,`OutputStream`是所有字节输出流的基类,用于向各种目的地写入字节数据。以下是一个简单的文件读写的例子: ```java import java.io.*; public ...

    InputStream的用法2---马克-to-win java视频

    InputStream的用法2 --- 马克-to-win java视频 输入流

Global site tag (gtag.js) - Google Analytics