【问题标题】:Reading a binary input stream into a single byte array in Java将二进制输入流读入Java中的单字节数组
【发布时间】:2011-11-07 04:36:16
【问题描述】:

The documentation 表示不应使用available() 方法来确定InputStream 的大小。如何将InputStream 的全部内容读入字节数组?

InputStream in; //assuming already present
byte[] data = new byte[in.available()];
in.read(data);//now data is filled with the whole content of the InputStream

我可以多次读取到一个固定大小的缓冲区,但是,我必须将读取的数据合并到一个单字节数组中,这对我来说是个问题。

【问题讨论】:

    标签: java inputstream


    【解决方案1】:

    我认为需要指定缓冲区长度,因为内存是有限的,您可能会用完它

    例子:

    InputStream in = new FileInputStream(strFileName);
        long length = fileFileName.length();
    
        if (length > Integer.MAX_VALUE) {
            throw new IOException("File is too large!");
        }
    
        byte[] bytes = new byte[(int) length];
    
        int offset = 0;
        int numRead = 0;
    
        while (offset < bytes.length && (numRead = in.read(bytes, offset, bytes.length - offset)) >= 0) {
            offset += numRead;
        }
    
        if (offset < bytes.length) {
            throw new IOException("Could not completely read file " + fileFileName.getName());
        }
    
        in.close();
    

    【讨论】:

      【解决方案2】:

      IMO 最简单的方法是使用Guava 及其ByteStreams 类:

      byte[] bytes = ByteStreams.toByteArray(in);
      

      或者对于一个文件:

      byte[] bytes = Files.toByteArray(file);
      

      或者(如果您不想使用 Guava),您可以创建一个 ByteArrayOutputStream,并反复读入一个字节数组并写入 ByteArrayOutputStream(让它处理调整大小),然后调用 ByteArrayOutputStream.toByteArray() .

      请注意,无论您是否知道输入的长度,这种方法都有效 - 当然,前提是您有足够的内存。

      【讨论】:

      • 谢谢。现在让它工作。我想我将不得不分块读取,然后将生成的字节数组合并为一个。
      • @Qiang:这基本上就是我提出的所有解决方案的作用——你不需要为此做很多工作。
      【解决方案3】:

      请记住,这里的答案假定文件的长度小于或等于Integer.MAX_VALUE(2147483647)。

      如果你从一个文件中读入,你可以这样做:

          File file = new File("myFile");
          byte[] fileData = new byte[(int) file.length()];
          DataInputStream dis = new DataInputStream(new FileInputStream(file));
          dis.readFully(fileData);
          dis.close();
      

      更新(2014 年 5 月 31 日):

      Java 7 在 java.nio.file 包中添加了一些新功能,可用于使该示例缩短几行。请参阅 java.nio.file.Files 类中的 readAllBytes() 方法。这是一个简短的例子:

      import java.nio.file.FileSystems;
      import java.nio.file.Files;
      import java.nio.file.Path;
      
      // ...
              Path p = FileSystems.getDefault().getPath("", "myFile");
              byte [] fileData = Files.readAllBytes(p);
      

      Android 从Api level 26(8.0.0,Oreo)开始支持此功能。

      【讨论】:

      • 不幸的是,我没有从文件中读取。我正在阅读 ZipEntry。有没有办法得到类似于这里的文件长度?
      【解决方案4】:

      您可以使用 Apache commons-io 来完成此任务:

      参考this method:

      public static byte[] readFileToByteArray(File file) throws IOException
      

      更新:

      Java 7方式:

      byte[] bytes = Files.readAllBytes(Paths.get(filename));
      

      如果它是一个文本文件并且您想将其转换为字符串(根据需要更改编码):

      StandardCharsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString()
      

      【讨论】:

        【解决方案5】:

        您可以按块 (byte buffer[] = new byte[2048]) 读取它并将这些块写入 ByteArrayOutputStream。从 ByteArrayOutputStream 中,您可以将内容作为 byte[] 检索,而无需事先确定其大小。

        【讨论】:

          【解决方案6】:

          数组索引的最大值是 Integer.MAX_INT - 大约是 2Gb (2^31 / 2 147 483 647)。 您的输入流可能大于 2Gb,因此您必须分块处理数据,抱歉。

                  InputStream is;
                  final byte[] buffer = new byte[512 * 1024 * 1024]; // 512Mb
                  while(true) {
                      final int read = is.read(buffer);
                      if ( read < 0 ) {
                          break;
                      }
                      // do processing 
                  }
          

          【讨论】:

          • 我会 -1 不是关于 max int 的信息 - 你不应该编写不必要的复杂代码 - while(true) 天哪 - 请编辑:int read; while(read = is.read(buffer) &gt; 0 )
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-07
          • 1970-01-01
          • 2011-05-15
          • 1970-01-01
          • 2019-10-29
          • 1970-01-01
          相关资源
          最近更新 更多