您可以使用自定义 FilterOutputStream 解决限制序列化对象大小的问题:
- 计算
write 方法调用写入的字节数,并
- 当计数超过您的限制时,引发自定义
IOException 子类。
然后将此过滤器放在ByteArrayOutputStream 和ObjectOutputStream 之间。
这就是代码的样子(未经测试!):
public LimitExceededException extends IOException { ... }
public class LimitingOutputStream extends FilterOutputStream {
private int limit;
private int count;
public LimitingOutputStream(OutputStream out, int limit) {
super(out);
this.limit = limit;
}
@Override
public void write(byte b) throws IOException {
if (count++ > limit) {
throw LimitExceededException(...);
}
super.write(b);
}
@Override
// (This override is not strictly necessary, but it makes it faster)
public void write(byte[] bytes, int from, int size) throws IOException {
if (count += size > limit) {
throw LimitExceededException(...);
}
super.write(bytes, from, size);
}
}
/**
* Return the serialization of `o` in a byte array, provided that it is
* less than `limit` bytes. If it is too big, return `null`.
*/
public byte[] serializeWithLimit(Object o, int limit) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
LimitingOutputStream los = new LimitingOutputStream(bos, limit);
ObjectOutputStream oos = new ObjectOutputStream(los);
oos.writeObject(o);
oos.close();
return bos.toByteArray();
} catch (LimitExceededException e) {
return null;
}
}
是的,当超出限制时,它使用异常来“退出”,但这是 IMO 对异常的良好使用。我挑战任何不同意这一点的人提出更好的解决方案。把它放在另一个答案中。
顺便说一句,这是非常糟糕的代码:
} catch (Exception e) {
return Long.MAX_VALUE;
}
除了您可能期望被抛出的IOExceptions 之外,您还捕获了各种未经检查的异常,其中大部分是由错误引起的……您需要了解:
捕捉Exception 是不好的做法,除非您尝试进行最后的诊断。
每当您捕获到意外异常时,请务必记录它们以便可以记录堆栈跟踪(取决于记录器配置)。或者,如果您的应用程序不使用日志框架,则让它调用 e.printStackTrace()。
(如果你不想在生产代码中这样做,也不要在 StackOverflow 问题中这样做......'因为一些复制粘贴编码器可能只是复制它。)