-1

fist of all I have written one object in file using FileOutputStream,CipherOutputStream & ObjectOutputStream. the flow of code is something like this Object > ObjectOutputStream > CipherOutputStream > FileOutputStream > File. now when I tried to read that object from file, the EOFException is being thrown. the flow of reading object is like Object < ObjectInputStream < CipherInputStream < FileInputStream < File.

I have one class IOManager which have methods IntIODEtail getIODetail(Path,boolean isComp)& boolean writeIntIODetail(IntIODetail obj,Path dir,boolean comp) which creates FileInputStreamor FileOutputStream respectively & call Different & methods of factory class ObjectHandler to encrypt & write object to the stream or read & decrypt Object to the stream.

code for 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;
      }
 }

code for 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;
      }
 }

for complete code please visit https://github.com/computer-developers/Program-Tester/tree/master/src/lib/runDetails.

Edit:- as 'EJP' suggested i have added stack trace.

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)

although size of the object does't matters but I have to mention that the object have remarkable data like two Lists of Strings having more than 100000 elements. here I have created Buffered Streams to resolve the problem, but it's not working.

Neel Patel
  • 358
  • 2
  • 13
  • 1
    If something is not working, the last thing you want to be doing is discarding Exceptions which might be trying to tell you what the problem is. – Peter Lawrey Feb 07 '17 at 14:06
  • Also if you take out decryption/encryption, do you still get an eof? Since it is hard to verify the contents of the file when created with encryption I would take the it of the equation to see if you still get the eof – bichito Feb 07 '17 at 14:09
  • Looks like a minor issue, but BufferedOutputStream is created from FileOutputStream but is never actually used, ObjectHandler is supplied with just FileOutput. – M. Prokhorov Feb 07 '17 at 14:13
  • 1
    For a stream you may as well use a - wait for it - stream cipher such as AES-CTR mode. At least the cipher won't - ahem, shouldn't - be waiting for a block to fill up before it can be processed. – Maarten Bodewes Feb 07 '17 at 14:30
  • Stack trace please. Is there an actual problem? Or have you just overrun the end of the file? NB You should use the same object streams for the life of the underlying streams, not use new ones for every object. Ditto the cipher streams. – user207421 Feb 07 '17 at 16:35
  • @PeterLawrey , I got what you trying to say. but I can't figure out where to catch the `EOFException` because there are three Streams 'nested' so please explain how & where I should mask the `EOFException` as you suggested. – Neel Patel Feb 08 '17 at 04:46
  • @efekctive , as I mentioned in updated description, I have tried by taking out decryption/encryption & it works perfectly without any exception. so the problem might be in encryption or decryption. – Neel Patel Feb 08 '17 at 04:52
  • @M.Prokhorov , as I have mentioned in updated comment, i have use `BufferedStreams` to solve the problem but it's not working. – Neel Patel Feb 08 '17 at 04:56
  • @MaartenBodewes , sir I don't get what you say. please explain in detail what you want to say. – Neel Patel Feb 08 '17 at 04:58
  • @EJP , I have added stack trace in updated comment. & about using single Objectstream for multiple objects, I think this does't fit in his case as I'm interested in writing a single object in separate file. so I need new FileStreams as well as new ObjectStreams to mask those. – Neel Patel Feb 08 '17 at 05:03
  • There's no cipher stream in exception stack, and it looks like you reach the end of file before you reach the end of some array list. – M. Prokhorov Feb 08 '17 at 05:34
  • @M.Prokhorov , that may be one possibility & I have noticed that. Even I wondered how this is going. but I try to read object which is written using proper strategy as described above. So there may be some different issue because it works fine when `CypherStreams` are not present in sequence. – Neel Patel Feb 08 '17 at 09:00
  • Have you tried a different OS? even a different machine? I recently helped a person that was experiencing zip file corruption inside tomcat and it just happened in one particular machine/HD.It wouldn't hurt to discard this scenario – bichito Feb 08 '17 at 10:16
  • @efekctive I have tried it on windows platform in multiple computers. – Neel Patel Feb 08 '17 at 10:28
  • 1
    @NeelPatel Not mask them, print them, read them and fix them, because doing that is also likely to fix your problem. – Peter Lawrey Feb 08 '17 at 13:14
  • @NeelPatel Yes. If you didn't fix your exceptions this is a wild goose chase – bichito Feb 08 '17 at 13:31
  • I see no stack trace. You should create both the object stream and the cipher stream at the same time as you create the file stream. Buffered streams are a good idea but there is no reaon why they should solve this problem. – user207421 Feb 08 '17 at 20:57
  • @EJP, I am also interested in writing the object without encryption you may see the `boolean` parameters in methods `getIODetail` & `writeIntIODetail` if those are false then the objects written or read without encryption, creating `ObjectStreams` & `CipherStreams` will leads to repeation of code, that's why I have separated the creation of `ObjectStreams` & `CipherStreams`. If you know better way to implement this then please explain me I'm really interested to know different implementation patterns. – Neel Patel Feb 09 '17 at 01:44

1 Answers1

0

I have solve this... I have tried different algorithm for encryption & decryption. I replace AES/CBC/NoPadding with AES/CBC/PKCS5Padding & use BufferedStream in between FileStreams & CypherStreams.

now the flow of code is like Object > ObjectOutputStream > CipherOutputStream > BufferedOutputStream > FileOutputStream > File. & for read Object < ObjectInputStream < CipherInputStream < BufferedInputStream < FileInputStream < File.

still I don't understand the actual problem. although the problem is solved but I'm interested to know actual problem.

Neel Patel
  • 358
  • 2
  • 13