【问题标题】:Trim Padding From ByteArrayOutputStream从 ByteArrayOutputStream 修剪填充
【发布时间】:2013-07-30 19:06:08
【问题描述】:

我正在使用 Amazon S3 并想上传一个 InputStream(这需要计算我发送的字节数)。

public static boolean uploadDataTo(String bucketName, String key, String fileName, InputStream stream) {

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    byte[] buffer = new byte[1];

    try {
        while (stream.read(buffer) != -1) { // copy from stream to buffer
            out.write(buffer); // copy from buffer to byte array
        }
    } catch (Exception e) {
        UtilityFunctionsObject.writeLogException(null, e);
    }

    byte[] result = out.toByteArray(); // we needed all that just for length
    int bytes = result.length;
    IO.close(out);
    InputStream uploadStream = new ByteArrayInputStream(result);

    ....

}

有人告诉我一次复制一个字节效率非常低(对于大文件来说很明显)。我不能做得更多,因为它会为ByteArrayOutputStream 添加填充,我无法删除它。我可以从result 中删除它,但我怎样才能安全地做到这一点?如果我使用 8KB 缓冲区,我可以只去掉最右边的 buffer[i] == 0 吗?还是有更好的方法来做到这一点?谢谢!

在 Windows 7 x64 上使用 Java 7。

【问题讨论】:

  • 没有“填充”。这里的问题是你在 writing 垃圾,在对write() 的调用中不包含“count”参数。
  • @EJP 我现在解决了我的问题,但我不认为我在写无法解释的垃圾。字节缓冲区将填满 InputStream 允许的大小,而数组中的所有其他值都设置为 0(我相信默认 Java 变量值)。因此,我会收到文本,然后是一百万 NUL 或 '\0',这不正确吗?

标签: java amazon-s3 stream bytearray


【解决方案1】:

你可以这样做:

int read = 0;
while ((read = stream.read(buffer)) != -1) {
    out.write(buffer, 0, read);
}

stream.read() 返回已写入buffer 的字节数。您可以将此信息传递给out.write()len 参数。因此,请确保只写入从流中读取的字节。

【讨论】:

    【解决方案2】:

    使用 Jakarta Commons IOUtils 一步即可从输入流复制到字节数组流。它将使用高效的缓冲区,并且不会写入任何多余的字节。

    【讨论】:

      【解决方案3】:

      如果您想提高效率,您可以在阅读文件时对其进行处理。我会将uploadStream 替换为stream 并删除其余代码。

      如果你需要一些缓冲,你可以这样做

       InputStream uploadStream = new BufferedInputStream(stream);
      

      默认缓冲区大小为 8 KB。

      如果你想要长度使用 File.length();

       long length = new File(fileName).length();
      

      【讨论】:

      • 我试过了,AMZ 库用大写字母警告你不应该这样做。所以我正在尝试更安全的方式(另外,这种方式经过AMZ的库优化,显然可以是多线程的)。
      • @jsn 我可以告诉你,首先复制文件要糟糕得多。它速度更慢,代码更多,并且更容易因大文件而中断。
      • 我可能会误解,但我没有将文件复制到 S3。它是来自内存的所有数据(来自 StringBuffer 的 InputStream)。我正在做的是我正在读取整个流以获取字节数,然后重新创建它并将其与字节数一起传递给 S3(为了优化;我可以只传递流,但随后它给出我那个警告)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多