Java语言URL中的图像已损坏



我正试图从URL加载此图像,但收到的图像是这样的。

代码:

@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();
            }
  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字节,则会写入太多

我有一些从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;
    }
}

最新更新