Java。来自 URL 的损坏图片

Java. Broken image from URL

我正在尝试加载这个 image from URL, but receive image like this

代码:

@Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            try {
                URL url = new URL("http://s.developers.org.ua/img/announces/java_1.jpg");
                BufferedInputStream in = new BufferedInputStream(url.openStream());
                byte[] b = new byte[512];
                while (in.read(b)!=-1)
                    out.write(b);
                Image img = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
                g2.drawImage(img, 0, 0, getWidth(), getHeight(), null);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

我有一些代码从 URL 复制文件到本地。到目前为止,结果与实际源代码相同。稍微修改一下或许可以解决。

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import org.apache.commons.io.FilenameUtils;
import javax.imageio.ImageIO;

public class ImagesUrlToImagesLocal {
    public ArrayList<String> getIt(ArrayList<String> urlFile)
    {
        ArrayList<String> strResult = new ArrayList<String>();
        Image imagesUrl = null;
        String baseName = null;
        String extension = null;
        File outputfile = null;
        try {
            for (int i = 0; i < urlFile.size(); i++)
            {
                URL url = new URL(urlFile.get(i));
                baseName = FilenameUtils.getBaseName(urlFile.get(i));
                extension = FilenameUtils.getExtension(urlFile.get(i));
                imagesUrl = ImageIO.read(url);
                BufferedImage image = (BufferedImage) imagesUrl;
                outputfile = new File("temp_images/" + baseName + "." + extension);
                ImageIO.write(image, extension, outputfile);
                strResult.add("temp_images/" + baseName + "." + extension);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return strResult;
    }
}
  1. 不要在 paintComponent 方法中读取图像,这会使您的应用程序显得迟缓,因为该方法是在事件调度程序线程 (EDT) 上执行的。此外,每当您的组件重新绘制时,它都会被重新读取,这意味着您将一遍又一遍地下载图像。相反,预先阅读它,或者在一个单独的线程中(即使用 SwingWorker),并且只从 paintComponent 方法内部调用 g.drawImage(...)

  2. 图像损坏的原因是您的字节复制代码,您没有注意读取了多少字节(只要该值不是-1) ,而是无条件地复制 512 字节。不过,这里你不需要这样做,你可以简单地将流传递给ImageIO.read,像这样,使代码更简单和更易读:

    URL url = new URL("http://s.developers.org.ua/img/announces/java_1.jpg");
    try (BufferedInputStream in = new BufferedInputStream(url.openStream())) {
        BufferedImage img = ImageIO.read(in);
    }
    

    添加额外的 try (try-with-resources) 块确保您的流也正确关闭以避免资源泄漏。

  3. 为了完整性,修复字节复制代码,正确的版本是:

    // ... as above ...
    byte[] b = new byte[512];
    int bytesRead; // Keep track of the number of bytes read into 'b'
    while ((bytesRead = in.read(b)) != -1)
        out.write(b, 0, bytesRead);
    

我不知道这是否是唯一的问题,但您写的可能比得到的多。 我建议您将您的编写代码更改为:

int len;
while ((len=in.read(b))!=-1)
    out.write(b, 0, len);

否则,如果最后一个缓冲区不是恰好 512 字节长,你会写太多