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;
}
}
不要在 paintComponent
方法中读取图像,这会使您的应用程序显得迟缓,因为该方法是在事件调度程序线程 (EDT) 上执行的。此外,每当您的组件重新绘制时,它都会被重新读取,这意味着您将一遍又一遍地下载图像。相反,预先阅读它,或者在一个单独的线程中(即使用 SwingWorker
),并且只从 paintComponent
方法内部调用 g.drawImage(...)
。
图像损坏的原因是您的字节复制代码,您没有注意读取了多少字节(只要该值不是-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) 块确保您的流也正确关闭以避免资源泄漏。
为了完整性,修复字节复制代码,正确的版本是:
// ... 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 字节长,你会写太多
我正在尝试加载这个 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;
}
}
不要在
paintComponent
方法中读取图像,这会使您的应用程序显得迟缓,因为该方法是在事件调度程序线程 (EDT) 上执行的。此外,每当您的组件重新绘制时,它都会被重新读取,这意味着您将一遍又一遍地下载图像。相反,预先阅读它,或者在一个单独的线程中(即使用SwingWorker
),并且只从paintComponent
方法内部调用g.drawImage(...)
。图像损坏的原因是您的字节复制代码,您没有注意读取了多少字节(只要该值不是
-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) 块确保您的流也正确关闭以避免资源泄漏。为了完整性,修复字节复制代码,正确的版本是:
// ... 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 字节长,你会写太多