Java 使用CypherInputStream解密对象时出现EOFEException&;ObjectInputStream来自文件

Java 使用CypherInputStream解密对象时出现EOFEException&;ObjectInputStream来自文件,java,encryption,deserialization,fileinputstream,eofexception,Java,Encryption,Deserialization,Fileinputstream,Eofexception,首先,我使用FileOutputStream,CipherOutputStream&ObjectOutputStream在文件中编写了一个对象。 代码流是这样的Object>ObjectOutputStream>CipherOutputStream>FileOutputStream>File。 现在,当我试图从文件中读取该对象时,抛出了EOFEException。 读取对象的流程类似于objectFile&用于读取对象

首先,我使用
FileOutputStream
CipherOutputStream
&
ObjectOutputStream
在文件中编写了一个对象。 代码流是这样的
Object>ObjectOutputStream>CipherOutputStream>FileOutputStream>File
。 现在,当我试图从文件中读取该对象时,抛出了EOFEException。 读取对象的流程类似于
object

我有一个类IOManager,它有方法
IntIODEtail getIODetail(Path,boolean isComp)
&
boolean writeIntIODetail(IntIODEtail obj,Path dir,boolean comp)
它分别创建
FileInputStream
FileOutputStream
,并调用工厂类ObjectHandler的不同方法&对流中的对象进行加密和写入,或对流中的对象进行读取和解密

IOManager的代码

public static IntIODetail getIODetail(Path filepath,boolean isComp)throws IOException{
      if(!isComp)
           return getIODetail(filepath);
      if(!filepath.isAbsolute())
           return null;
      if((!Files.exists(filepath))||Files.isDirectory(filepath))
           return null;
      try(FileInputStream f=new FileInputStream(filepath.toFile());
                BufferedInputStream bin=new BufferedInputStream(f)){
           IntIODetail obj=ObjectHandler.readCompObj(f);
           if(obj!=null)
                return obj;
           throw new IOException();
      }
 }
public static boolean writeIntIODetail(IntIODetail obj,Path dir,boolean comp){
      if(!comp)
           return writeIntIODetail(obj,dir);
      if(!dir.isAbsolute())
           return false;
      if(!Files.isDirectory(dir))
           return false;
      String name="c";
      {//generate the formated file name. 
           name+="v";
           if(obj instanceof IODetail)
                name+=IODetail.getVersion();
           else
                name+="NA";
           name=name+"p";
           if(obj.programID()>=0)
                name+=obj.programID();
           else
                name+="NA";
           name+="i";
           if(obj.index()>=0)
                name+=obj.index();
           else
                name+="NA";
           name+=".data";
      }
      Path f=dir.resolve(name);
      try(FileOutputStream fout=new FileOutputStream(f.toFile());
                BufferedOutputStream bout =new BufferedOutputStream(fout)){
           return ObjectHandler.writeCompObj(fout, obj);
      } catch(IOException ex) {
           return false;
      }
 }
ObjectHandler的代码

public static boolean writeObj(OutputStream out,IntIODetail o) throws IOException{
      synchronized(out){

           try(ObjectOutputStream objOut=new ObjectOutputStream(out)){
                objOut.writeObject(o);
           }catch(InvalidClassException | NotSerializableException e){
                return false; 
           }
           return true;
      }
 }
public static IntIODetail readObj(InputStream in) throws IOException{
      synchronized(in){

           try(ObjectInputStream objIn=new ObjectInputStream(in)){
                IntIODetail ob=(IntIODetail)objIn.readObject();
                return ob;
           } catch(ClassNotFoundException | InvalidClassException 
                     | StreamCorruptedException | OptionalDataException e) {
                return null;
           }
      }
 }
public static boolean writeCompObj(OutputStream out,IntIODetail o)
           throws IOException{

      try {        
           byte[] keyBytes = "1234123412341234".getBytes();  //example
           final byte[] ivBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 
                0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; //example

           final SecretKey key = new SecretKeySpec(keyBytes, "AES");
           final IvParameterSpec IV = new IvParameterSpec(ivBytes);
           final Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
           cipher.init(Cipher.ENCRYPT_MODE, key, IV);
           try(CipherOutputStream cstream = new CipherOutputStream(out, cipher)){
                return writeObj(cstream,o);
           }
      } catch(Exception ex) {
           return false;
      }
 }
public static IntIODetail readCompObj(InputStream in)
           throws IOException{
      try {
           byte[] keyBytes = "1234123412341234".getBytes();
           final byte[] ivBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
                       0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

           final SecretKey secretkey = new SecretKeySpec(keyBytes, "AES");
           final IvParameterSpec IV = new IvParameterSpec(ivBytes);
           final Cipher decipher = Cipher.getInstance("AES/CBC/NoPadding");
                decipher.init(Cipher.DECRYPT_MODE, secretkey, IV);
           try(CipherInputStream cin=new CipherInputStream(in,decipher)){
                return readObj(cin);
           }
      } catch(InvalidKeyException | InvalidAlgorithmParameterException
                | NoSuchPaddingException |NoSuchAlgorithmException ex) {
           return null;
      }
 }
有关完整代码,请访问

编辑:-根据“EJP”的建议,我添加了堆栈跟踪

Exception in thread "main" java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2353)
at java.io.ObjectInputStream$BlockDataInputStream.readUTFBody(ObjectInputStream.java:3092)
at java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:2892)
at java.io.ObjectInputStream.readString(ObjectInputStream.java:1646)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1344)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
at java.util.ArrayList.readObject(ArrayList.java:791)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1058)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1909)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1808)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2018)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1942)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1808)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
at lib.runDetails.ObjectHandler.readObj(ObjectHandler.java:115)
at lib.runDetails.ObjectHandler.readCompObj(ObjectHandler.java:184)
at lib.runDetails.IOManager.getIODetail(IOManager.java:133)
at testRunDetails.IOManagerTest2.main(IOManagerTest2.java:27)
虽然对象的大小并不重要,但我必须提到,对象有非常重要的数据,比如两个字符串列表,其中包含100000多个元素。 这里我创建了
缓冲流来解决这个问题,但它不起作用。

我已经解决了这个问题。。。 我尝试了不同的加密和解密算法。 我将
AES/CBC/NoPadding
替换为
AES/CBC/PKCS5Padding
&在
FileStreams
CypherStreams
之间使用
BufferedStream

现在,代码流类似于
ObjectOutputStream>CipherOutputStream>BufferedOutputStream>FileOutputStream>File
&用于读取
对象


我仍然不明白实际的问题。虽然问题已经解决,但我有兴趣了解实际问题。

如果某个问题不起作用,您最不希望做的事情就是丢弃异常,这些异常可能会试图告诉您问题所在。此外,如果您进行解密/加密,您是否仍会获得eof?由于使用加密创建文件时很难验证文件的内容,因此我将使用公式中的it来查看您是否仍然像小问题一样获得eofLooks,但BufferedOutputStream是从FileOutputStream创建的,但从未实际使用过,ObjectHandler只提供文件输出。对于流,您还可以使用-wait-it-流密码,如AES-CTR模式。至少密码不会-嗯,不应该-在处理前等待数据块填满。@NeelPetel不会屏蔽、打印、读取并修复它们,因为这样做也可能修复您的问题。