我正在开发一个java
应用程序,我在其中加载一些包含图像的长列表(从web下载),因此我添加了一个快速HashMap<String,BufferedImage>
作为缓存,以避免重新加载同一图像多个次。
这样可以正常工作并且应用程序更快,但让这个缓存在各个会话中保持不变会很好,所以我将缓存更改为序列化。
BufferedImage
不是Serializable
,所以我必须编写自定义方法。
我的文件结构应该是这样的:
虽然文件保存似乎很好(至少我没有例外),当我尝试加载URL
它会java.io.OptionalDataException
length = 4
并且我不明白为什么。第一次迭代很顺利,但是一旦我尝试加载第二个URL
,我就会遇到这个异常,所以我怀疑加载第一个图像的方式有问题。
这是完整的代码:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
public class PicturesCache {
private static HashMap<String, BufferedImage> picturesCache;
private static final String cacheDiskLocation = "pictures_cache.map";
private static void writeCache(ObjectOutputStream oos, HashMap<String, BufferedImage> data) throws IOException {
// Number of saved elements
oos.writeInt(data.size());
// Let's write (url, image) for each entry in the cache
for (Entry<String, BufferedImage> entry : data.entrySet()) {
oos.writeObject(new URL(entry.getKey()));
ImageIO.write(entry.getValue(), "png", oos);
}
}
private static HashMap<String, BufferedImage> readCache(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Number of saved elements
int size = ois.readInt();
// Cache
HashMap<String, BufferedImage> result = new HashMap<>(size);
// Let's read (url, image) and add them to cache
for (int i = 0; i < size; i++) {
String url = ((URL) ois.readObject()).toString(); // EXCEPTION HERE
BufferedImage image = ImageIO.read(ois);
result.put(url, image);
}
return result;
}
public static void loadCache() {
picturesCache = new HashMap<>();
File file = new File(cacheDiskLocation);
if (file.isFile()) {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream(file);
ois = new ObjectInputStream(fis);
picturesCache = readCache(ois);
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(PicturesCache.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
ois.close();
fis.close();
} catch (IOException ex) {
Logger.getLogger(PicturesCache.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
System.out.println("Cache loaded with " + picturesCache.size() + " elements");
}
public static void saveCache() {
File file = new File(cacheDiskLocation);
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
if (file.isFile()) {
file.delete();
}
file.createNewFile();
fos = new FileOutputStream(file);
oos = new ObjectOutputStream(fos);
writeCache(oos, picturesCache);
} catch (IOException ex) {
Logger.getLogger(PicturesCache.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
System.out.println("Cache saved with " + picturesCache.size() + " elements");
oos.close();
fos.close();
} catch (IOException ex) {
Logger.getLogger(PicturesCache.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public static boolean contains(String url) {
return picturesCache.containsKey(url);
}
public static BufferedImage get(String url) {
return picturesCache.get(url);
}
public static void put(String url, BufferedImage image) {
picturesCache.put(url, image);
}
}
答案 0 :(得分:1)
发生错误是因为ImageIO.read(...)
未读取使用ImageIO.write(...)
编写的所有数据。您可以将图像作为ObjectOutputStread
写入byte[]
。例如:
private static void writeCache(ObjectOutputStream oos,
HashMap<String, BufferedImage> data) throws IOException {
// Number of saved elements
oos.writeInt(data.size());
// Let's write (url, image) for each entry in the cache
for (Entry<String, BufferedImage> entry : data.entrySet()) {
oos.writeObject(new URL(entry.getKey()));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(entry.getValue(), "jpg", baos);
byte[] bytes = baos.toByteArray();
oos.writeObject(bytes);
}
}
private static HashMap<String, BufferedImage> readCache(
ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Number of saved elements
int size = ois.readInt();
// Cache
HashMap<String, BufferedImage> result = new HashMap<>(size);
// Let's read (url, image) and add them to cache
for (int i = 0; i < size; i++) {
String url = ((URL) ois.readObject()).toString(); // EXCEPTION HERE
ByteArrayInputStream bais = new ByteArrayInputStream(
(byte[]) ois.readObject());
BufferedImage image = ImageIO.read(bais);
result.put(url, image);
}
return result;
}