0

So I have this thing that I'm making and the problem is that I think that some bytes are lost while the file is compressed and send to server as well as saved locally. I was able to send data while not using ByteArrayOutputStream but I have to use it and can't just use socket's OutputStream directly as I need each sent file to have somwhat unique ID. Also sizes of out.zip and out2.zip are different by around 10kB (out2.zip is smaller) here is Log dump: https://pastebin.com/UyTqnRYc

Function that sends data in chunks

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ZipOutputStream zos = new ZipOutputStream(baos);
        ZipParameters zipParameters = buildZipParameters(compressionMethod);
        ObjectOutputStream objOS = new ObjectOutputStream(outputStream);
        File f = new File("out2.zip");
        FileOutputStream fos = new FileOutputStream(f);
        for (File directory:pathsToDirectories) {
            String relativeRootDirectory = directory.getName();
            List<File> filesAndDirectories = Arrays.stream(Objects.requireNonNull(directory.listFiles())).toList();
            for (File somefile:filesAndDirectories) {

                if(somefile.isDirectory()){
                    addDirectoryToZip(zos,somefile,zipParameters,relativeRootDirectory,rootDirectoryName);
                }
                else
                {
                    if (zipParameters.getCompressionMethod() == CompressionMethod.STORE) {
                        zipParameters.setEntrySize(somefile.length());
                    }
                    byte[] buff = new byte[4096];
                    zipParameters.setFileNameInZip(rootDirectoryName+ "/"+somefile.getName()); //YIKES
                    zos.putNextEntry(zipParameters);
                    try(InputStream inputStream = new FileInputStream(somefile)) {
                        int readLen;
                        while (((readLen = inputStream.read(buff)) != -1)) {
                            zos.write(buff);
                            byte[] b = baos.toByteArray();
                            System.out.println("written :"+baos.toByteArray().length);
                            objOS.writeObject(new TransportDataModel((byte) 1,baos.toByteArray()));
                            fos.write(baos.toByteArray());
                            baos.reset();
                            baos.flush();
                        }
                    }
                    zos.closeEntry();
                }

            }
        }
        objOS.writeObject(new TransportDataModel((byte) 1,baos.toByteArray()));
        zos.flush();


        System.out.println("REST OF IT :"+ Arrays.toString(baos.toByteArray()));
        System.out.println(baos.toByteArray().length);
        objOS.writeObject(new TransportDataModel((byte) 1,baos.toByteArray()));

        fos.write(baos.toByteArray());
        baos.reset();
        System.out.println("REST OF IT :"+ Arrays.toString(baos.toByteArray()));
        fos.flush();
        fos.close();
        objOS.writeObject(new TransportDataModel((byte) -1,new byte[0]));

        zos.close();

    }

Record used as a packet


import java.io.Serializable;

public record TransportDataModel(byte id, byte[] data) implements Serializable {
}

Server code:

public Server(int port)
    {
        // starts server and waits for a connection
        try
        {
            server = new ServerSocket(port);
            System.out.println("Server started");

            System.out.println("Waiting for a client ...");

            socket = server.accept();
            System.out.println("Client accepted");

            
            in = new ObjectInputStream(socket.getInputStream());
            File f = new File("out.zip");
            FileOutputStream outputStream = new FileOutputStream(f);
            

            TransportDataModel transportDataModel;
            while (true) {
                transportDataModel= (TransportDataModel) in.readObject();
                    if (transportDataModel.id() == -1) {
                        break;
                    }
                    if(transportDataModel.data().length != 0)
                    {
                        //System.out.println(transportDataModel.id());
                        outputStream.write(transportDataModel.data());
                    }


            }
            outputStream.flush();
            outputStream.close();
            System.out.println("Closing connection");

            // close connection
            socket.close();
            in.close();
            ZipFile zipFile = new ZipFile("out.zip");
            zipFile.extractAll("/home/xenu/IdeaProjects/BBT-BasicBackupTool");
        }
        catch(IOException i)
        {
            i.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
Xenu
  • 11
  • 1
  • I would make use of [`ZipOutputStream#write(byte[], int, int)`](https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/zip/ZipOutputStream.html#write(byte%5B%5D,int,int)) instead of `write(byte[])`. `write(byte[])` is going to write ALL the bytes in the array, but the array may not be full (hence the use of `readLen`) – MadProgrammer Jan 26 '22 at 22:14
  • I'd also be making a lot more use of [The try-with-resources Statement](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) – MadProgrammer Jan 26 '22 at 22:15
  • You might consider having a look at [How to zip the content of a directory in Java](https://stackoverflow.com/questions/51833423/how-to-zip-the-content-of-a-directory-in-java/51833575#51833575) - forget about the socket for now, get the zip workflow to work – MadProgrammer Jan 26 '22 at 22:20
  • @MadProgrammer so I should use java standard zip library instead of external and then try to do something with sockets – Xenu Jan 27 '22 at 13:25
  • You ca use zip4j, but you need to be sure you're managing the buffer correctly – MadProgrammer Jan 27 '22 at 20:36
  • Hymmm, for some reason it works with standard java zipping library so I think I'll just stick with it as it actually has all the stuff that I need thanks to @MadProgrammer for giving me some directions on how to tackle the problem :) – Xenu Feb 01 '22 at 21:14

0 Answers0