您可以使用自定义 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;
}
除了IOException
您可能期望被抛出的 s 之外,您还会捕获各种未经检查的异常,其中大部分是由错误引起的……您需要了解:
Exception
除非您尝试进行最后的诊断,否则捕捉是不好的做法。
每当您捕获意外异常时,请务必记录它们以便可以记录堆栈跟踪(取决于记录器配置)。或者,如果您的应用程序不使用日志框架,那么让它调用e.printStackTrace()
.
(如果你不想在生产代码中这样做,也不要在 StackOverflow 问题中这样做......'因为一些复制和粘贴编码器可能只是复制它。)