Java含不可序列化字段对象转InputStream上传S3及readObject实现
自定义readObject方法实现方案
你当前卡壳的核心原因,是writeObject方法中只写入了每个不可序列化对象的字节内容,没有记录每个字节块的长度边界——ObjectInputStream是无边界的顺序流,没有额外的长度标记的话,根本无法区分连续写入的三个字节数组的分段位置。
调整后的完整实现逻辑
第一步:修正writeObject方法
写每个不可序列化对象的字节内容前,先写入对应字节数组的长度(int类型,固定占4个字节),给后续读取做边界标记:
private void writeObject(final ObjectOutputStream objectOutputStream) throws IOException { // 保持原有逻辑,先写入所有默认可序列化字段 objectOutputStream.defaultWriteObject(); // 序列化第一个不可序列化对象,先存长度再存内容 byte[] obj1Bytes = someMethodToconvertObject1ToByteArray(); objectOutputStream.writeInt(obj1Bytes.length); objectOutputStream.write(obj1Bytes); // 序列化第二个不可序列化对象,流程同上 byte[] obj2Bytes = someMethodToconvertObject2ToByteArray(); objectOutputStream.writeInt(obj2Bytes.length); objectOutputStream.write(obj2Bytes); // 序列化第三个不可序列化对象,流程同上 byte[] obj3Bytes = someMethodToconvertObject3ToByteArray(); objectOutputStream.writeInt(obj3Bytes.length); objectOutputStream.write(obj3Bytes); }
第二步:实现对应的readObject方法
严格按照writeObject的写入顺序读取:先读长度标记,再按长度读满对应字节块,最后用你已有的转换方法把字节数组还原成对象即可:
private void readObject(final ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { // 保持原有逻辑,先读取所有默认可序列化字段 objectInputStream.defaultReadObject(); // 还原第一个不可序列化对象 int obj1Length = objectInputStream.readInt(); byte[] obj1Bytes = new byte[obj1Length]; // 必须用readFully,保证读满对应长度的字节,避免流读取不完整导致错位 objectInputStream.readFully(obj1Bytes); this.object1 = convertByteArrayToNonSerializableObject1(obj1Bytes); // 还原第二个不可序列化对象 int obj2Length = objectInputStream.readInt(); byte[] obj2Bytes = new byte[obj2Length]; objectInputStream.readFully(obj2Bytes); this.object2 = convertByteArrayToNonSerializableObject2List(obj2Bytes); // 还原第三个不可序列化对象 int obj3Length = objectInputStream.readInt(); byte[] obj3Bytes = new byte[obj3Length]; objectInputStream.readFully(obj3Bytes); this.object13 = convertByteArrayToNonSerializableObject3(obj3Bytes); }
配套S3上传实现
完全不需要单独拼接多段InputStream,等对象完成自定义序列化后,把整个序列化结果转成单条InputStream就能直接传给S3的上传接口:
// 先把容器类实例序列化到内存字节数组 ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(); ObjectOutputStream objectOutput = new ObjectOutputStream(byteOutput); objectOutput.writeObject(yourContainerClassInstance); objectOutput.close(); // 直接生成可上传的InputStream InputStream uploadStream = new ByteArrayInputStream(byteOutput.toByteArray()); // 传入S3上传接口即可 s3Client.putObject("你的桶名", "你的对象Key", uploadStream, new ObjectMetadata());
关键注意事项
- 读写顺序必须完全和
writeObject的写入逻辑对应,一旦调换字段的读写顺序,整个流的边界标记就会错位,导致读取失败。 - 读取字节块时必须用
readFully()方法,不要直接用read(byte[]):后者可能因为流的阻塞、数据未就绪,返回的实际读取字节数小于数组长度,造成后续所有内容错位。 - 不需要额外寻找容器类InputStream实现,内存中完成序列化后的单流已经完全满足S3的上传要求,不需要做多流拼接。
内容的提问来源于stack exchange,提问作者confuseddev
相关产品推荐
相关产品推荐

