下载图片或处理图片时经常导致内存溢出,原因是使用ImageIO.read读取过大的照片是经常会导致内存溢出问题。转换其他解码方式来解决该问题。
InputStream urlFile = Utils.getUrlFile("url");
try {
//BufferedImage read = ImageIO.read(urlFile);
// 将图像文件加读取到内存成为字节数组
byte[] imgBytes = readBytes(urlFile);
BufferedImage read = readMemoryImage(imgBytes);
} catch (IOException e) {
e.printStackTrace();
}
/**
* 获取文件流
* @param path
* @return
*/
public static InputStream getUrlFile(String path){
try {
URL url = new URL(path);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
InputStream inputStream = connection.getInputStream();
return inputStream;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 从{@link InputStream}读取字节数组<br>
* 结束时会关闭{@link InputStream}<br>
* {@code in}为{@code null}时抛出{@link NullPointerException}
*
* @param in
* @return 字节数组
* @throws IOException
*/
public static final byte[] readBytes(InputStream in) throws IOException {
if (null == in)
throw new NullPointerException("the argument 'in' must not be null");
try {
int buffSize = Math.max(in.available(), 1024 * 8);
byte[] temp = new byte[buffSize];
ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);
int size = 0;
while ((size = in.read(temp)) != -1) {
out.write(temp, 0, size);
}
return out.toByteArray();
} finally {
in.close();
}
}
/**
* 从内存字节数组中读取图像
*
* @param imgBytes
* 未解码的图像数据
* @return 返回 {@link BufferedImage}
* @throws IOException
* 当读写错误或不识别的格式时抛出
*/
public static final BufferedImage readMemoryImage(byte[] imgBytes) throws IOException {
if (null == imgBytes || 0 == imgBytes.length)
throw new NullPointerException("the argument 'imgBytes' must not be null or empty");
// 将字节数组转为InputStream,再转为MemoryCacheImageInputStream
ImageInputStream imageInputstream = new MemoryCacheImageInputStream(new ByteArrayInputStream(imgBytes));
// 获取所有能识别数据流格式的ImageReader对象
Iterator<ImageReader> it = ImageIO.getImageReaders(imageInputstream);
// 迭代器遍历尝试用ImageReader对象进行解码
while (it.hasNext()) {
ImageReader imageReader = it.next();
// 设置解码器的输入流
imageReader.setInput(imageInputstream, true, true);
// 图像文件格式后缀
String suffix = imageReader.getFormatName().trim().toLowerCase();
// 图像宽度
int width = imageReader.getWidth(0);
// 图像高度
int height = imageReader.getHeight(0);
System.out.printf("format %s,%dx%d\n", suffix, width, height);
try {
// 解码成功返回BufferedImage对象
// 0即为对第0张图像解码(gif格式会有多张图像),前面获取宽度高度的方法中的参数0也是同样的意思
return imageReader.read(0, imageReader.getDefaultReadParam());
} catch (Exception e) {
imageReader.dispose();
// 如果解码失败尝试用下一个ImageReader解码
}
}
imageInputstream.close();
// 没有能识别此数据的图像ImageReader对象,抛出异常
throw new IOException("unsupported image format");
}
参考以下链接,尝试了其中一种方法,亲测可行。
https://blog.youkuaiyun.com/10km/article/details/52119508