【问题标题】:How to convert loaded bytes into image without ImageIO.read()如何在没有 ImageIO.read() 的情况下将加载的字节转换为图像
【发布时间】:2015-02-05 08:42:47
【问题描述】:

由于我自己的限制,我不能使用 ImageIO.read()。我只能在 GET 请求后加载字节,我需要将此字节保存为图像文件。但在我看来,还加载了一些额外的数据,浏览器通常会过滤(可能是响应头)。所以我得到了我什至无法作为图像打开的原始字节数组。

我应该如何处理这些字节?

例子:

byte[] buf = ContentLoader.loadBytes(new URL("http://images.visitcanberra.com.au/images/canberra_hero_image.jpg"));
try {
            FileOutputStream fileOutputStream = new FileOutputStream(new File("D:\\image.jpg"));
            fileOutputStream.write(buf);
            fileOutputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

loadBytes() 方法:

public static byte[] loadBytes(URL url) {
        ByteArrayOutputStream boutArray = new ByteArrayOutputStream();
        try {
            URLConnection connection = url.openConnection();
            BufferedInputStream bin = new BufferedInputStream(connection.getInputStream());
            byte[] buffer = new byte[1024 * 16];
            while (bin.read(buffer) != -1) {
                boutArray.write(buffer);
                boutArray.flush();
            }
            bin.close();
        } catch (Exception e) {
            return null;
        }
        return boutArray.toByteArray();
    }

【问题讨论】:

  • 为什么不直接将原始字节存储到文件中?
  • 您想编写自己的 JPEG 解码器吗? (我已经完成了,这是一个有趣的练习)如果没有,请使用 ImageIO.load(内置一个)或查找其他人的 JPEG 解码器。
  • 当我将原始字节存储到文件时,我无法打开它。它包含图像字节和一些奇数字节(如果比较浏览器保存和我保存的此图像的大小)
  • 如果你的最后一个read 调用返回一个字节,你仍然在写入 16384 个字节(那个字节,加上数组中的其他 16383 个字节恰好来自最后一个块)。
  • @immibis 和其他任何read() 通话一样。不能保证它们中的任何一个都会填满缓冲区。

标签: java image http byte


【解决方案1】:

常见问题。在 Java 中复制流的标准方法是:

int count;
while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}
out.close();
in.close();

注意,需要将read()返回的结果存入一个变量中;您需要在下一次write() 通话中使用它;你不应该在循环中flush();并且您需要关闭输入和输出流。

你为什么要使用ByteArrayInputStream 是个谜。这只是浪费时间和空间。直接从 URL 输入流中读取,直接写入FileOutputStream。

【讨论】:

  • 我使用 ByteArrayInputStream 是因为最终我需要创建 BufferedImage,它可能将 InputStream 作为参数。而且因为自己的限制,不能直接通过url加载。
  • 你自己的限制比如什么?您对为此目的使用 JRE 中提供的类有异议?
  • 我使用特殊的库来支持 socks4(JRE 因为它正式不支持 socks4 作为过时的协议)。这就是为什么我编写了自己的 ContentLoader 类,它可以使用 socks4 代理加载数据。所以我不能将 ImageIO.read() 与我的代理一起使用。现在我正在测试同一段代码,但没有代理,因为我知道它也适用于 socsk4 代理。也许这种方式看起来有点复杂,但我不知道其他人:)
  • 是什么让您认为 Java 不再支持 SOCKS 4? documentation 则相反。并且在任何情况下,您都不应该使用 SOCKS 代码污染图像加载器,您应该将它们完全分开。
  • 我知道。这就是我想首先将图像加载到 ByteArrayOutputStream 的原因。然后使用 ImageIO.read() 并正常使用它。
【解决方案2】:

以下代码适用于我:-

    URL url = new URL("my url...");
    InputStream is = url.openStream();
    OutputStream os = new FileOutputStream("img.jpg");

    byte[] b = new byte[2048];
    int length;

    while ((length = is.read(b)) != -1) {
        os.write(b, 0, length);
    }

    is.close();
    os.close();

【讨论】:

    猜你喜欢
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 2019-10-18
    相关资源
    最近更新 更多