【问题标题】:From FileInputStream to BufferedInputStream conversion从 FileInputStream 到 BufferedInputStream 的转换
【发布时间】:2016-04-02 09:55:12
【问题描述】:

我们在实验室进行了一些练习,其中之一是将文件传输方法从FileInputStream 转换为BufferedInputStream。它是一个客户端向 Web 服务器发送 GET 请求,Web 服务器发送请求的文件。 我想出了一个简单的解决方案,我只是想检查它是否正确。

原码:

try { 
      FileInputStream fis = new FileInputStream(req);
      // req, String containing file name
      byte[] data = new byte [fis.available()]; 
      fis.read(data); 
      out.write(data); // OutputStream out = socket.getOutputStream();
    } catch (FileNotFoundException e){ 
      new PrintStream(out).println("404 Not Found"); 
    }

我的尝试:

try { 
      BufferedInputStream bis = new BufferedInputStream (new FileInputStream(req));
      byte[] data = new byte[4];

      while(bis.read(data) > -1) {
        out.write(data);
        data = new byte[4];
      }
    } catch (FileNotFoundException e){ 
      new PrintStream(out).println("404 Not Found"); 
    }

该文件是一个名为 index.html 的网页,其中包含一个简单的 html 页面。 我每次都必须重新分配数组,因为在最后一次执行 while 循环时,如果文件的大小不是 4 的倍数,则数据数组将包含上一次执行的字符,这些字符会显示在浏览器中。 出于调试目的,我选择了 4 作为数据大小。 输出正确。

这是一个好的解决方案还是我可以做得更好?

【问题讨论】:

    标签: java fileinputstream bufferedinputstream


    【解决方案1】:

    无需每次都重新创建字节数组 - 只需覆盖它即可。更重要的是,您的循环中有一个概念错误。假设它都是有效的,每次迭代只是将数组写入流。如果您检查BufferedInputStream#read 的文档,您会发现它可能没有读取足够的数据来填充整个数组,并且会返回它实际读取的字节数。你应该使用这个数字来限制你正在写入的字节数:

    while((int len = bis.read(data)) > -1) {
        out.write(data, 0, len);
    }
    

    【讨论】:

      【解决方案2】:

      我建议您在完成后关闭文件。默认情况下,BufferedInputStream 使用 8 KB 缓冲区,您将其缩减为更小的缓冲区。一个更简单的解决方案是一次复制 8 KB 并且不使用添加的缓冲区

      try (InputStream in = new FileInputStream(req)) {
        byte[] data = new byte[8 << 10];
        for (int len; (len = bis.read(data)) > -1; ) 
            out.write(data, 0, len);
      } catch (IOException e) { 
        out.write("404 Not Found\n".getBytes()); 
      }
      

      【讨论】:

      • 感谢您的回复。对于存储在 hd 上的文件,FileInputStream 在每次读取操作时都会访问磁盘,而 BufferedInputStream 不会,因此通常来说效率更高。当文件通过网络提供时,这是否相同 - 这是我现在的情况?还是基本没有区别?
      • FileInputStream 会在每次读取时访问操作系统,操作系统可以使用预测性预读,并且只会偶尔访问磁盘。 BufferedInputStream 仅在您读取的数据块小得多时才有帮助,例如
      猜你喜欢
      • 2016-02-07
      • 1970-01-01
      • 2020-11-30
      • 1970-01-01
      • 1970-01-01
      • 2011-08-08
      • 1970-01-01
      • 2019-03-09
      • 1970-01-01
      相关资源
      最近更新 更多