-2

i have a server which sending thousands of tiny files like below:

static File file = null;

static File temp = null;
private static ServerSocket serverSocket;
private static Socket socket;


public static void main(String[] args) throws FileNotFoundException, IOException 
{

    serverSocket = new ServerSocket(3000);
    socket = serverSocket.accept();
    System.out.println("Connected");



    File folder = new File("C:...\\Desktop\\thousands_of_tiny_files");
    File[] listOfFiles = folder.listFiles();
    File result[]=new File[listOfFiles.length];


    byte [] bytearray  = null;
    FileInputStream fin =null;
    BufferedInputStream bin = null; 



    for(int j=0;j<listOfFiles.length;j++){

        String path= listOfFiles[j].getPath();

        result=sendFile(path);
        for(int i=0;i<result.length;i++)   
        {
            fin = new FileInputStream(result[i]);
            bin = new BufferedInputStream(fin); 
            bytearray  = new byte [(int)result.length];
            bin.read(bytearray,0,bytearray.length);
            OutputStream os = socket.getOutputStream();
            System.out.println("Sending Files "+ result[i]);

            os.write(bytearray,0,bytearray.length);
            os.flush();

            System.out.println("File transfer completed");        

        }
    }
 fin.close();
 bin.close();
 socket.close();
}

public static File[] sendFile(String path)
{
    File folder = new File(path);
    File[] listOfFiles = folder.listFiles();

    File[] resultt = new File[listOfFiles.length];
    for(int i=0;i<listOfFiles.length;i++)
    {
        temp=listOfFiles[i];
        if(temp.isFile() && temp!=null)
            resultt[i]=temp;

    }
    return resultt;
}

it is successfull but my problem is in client side. i dont know how to distinguish between the files and write them seperately into the client.

EDIT2: I changed the server side code like following using ZipOutputStream but still dont know how to unzip and write it in the client (mostly, dont know how to define the FileOutputStream in client:

    for(int i=0;i<result.length;i++)   
        {
            fin = new FileInputStream(result[i]);

            bytearray  = new byte [(int)result.length];

            ZipOutputStream zipOpStream = new ZipOutputStream(socket.getOutputStream());
            zipOpStream.putNextEntry(new ZipEntry(result[i].getName()));


            System.out.println("Sending Files "+ result[i]);

            zipOpStream.write(bytearray,0,bytearray.length);
            zipOpStream.flush();

            System.out.println("File transfer completed");        

        }
    }

 socket.close();
} 

and the reciever code:

          socket = new Socket("127.0.0.1",3000);

         String outDir = "C:...\\Desktop\\here";



         BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());            


          ZipInputStream zips = new ZipInputStream(bis);
          ZipEntry zipEntry = null;

          while(null != (zipEntry = zips.getNextEntry())){
          String fileName = zipEntry.getName();
          File outFile = new File(outDir + "/" + fileName);
          System.out.println("----["+outFile.getName()+"], filesize["+zipEntry.getCompressedSize()+"]");

    if(zipEntry.isDirectory()){
    File zipEntryFolder = new File(zipEntry.getName());
    if(zipEntryFolder.exists() == false){
     outFile.mkdirs();
    }

        continue;
    }else{
    File parentFolder = outFile.getParentFile();
    if(parentFolder.exists() == false){
     parentFolder.mkdirs();
    }
   }

   System.out.println("ZipEntry::"+zipEntry.getCompressedSize());



   FileOutputStream fos = new FileOutputStream(outFile);
   int fileLength = (int)zipEntry.getSize();

   byte[] fileByte = new byte[fileLength];
   zips.read(fileByte);
   fos.write(fileByte);
   fos.close();


        socket.close();

     }

now i get an exceptiom"negative NegativeArraySizeException"

Exception in thread "main" java.lang.NegativeArraySizeException
    at recieve.Reciever.<init>(Reciever.java:71)
    at recieve.Recieve$1.<init>(Recieve.java:28)
    at recieve.Recieve.main(Recieve.java:28)
ZipEntry::-1

which probably is because of

   int fileLength = (int)zipEntry.getSize();

but how can I solve this? i need the siz of next entry of zip folder for writing into the file. but the size is in Long not int

lonesome
  • 2,503
  • 6
  • 35
  • 61
  • 3
    Well you've just got a stream of data, with no indication of the length of each file. Consider using a length prefix before each file. (You should also use the value returned by InputStream.read - don't assume you will read the whole file in a single read call.) – Jon Skeet May 30 '14 at 10:34
  • @JonSkeet in fact it does perfectly. there are 2 files in each folder., everuy time i check if i meet a file or folder, then in the **send file()** will send it and then will read second folder until the end. but i wonder how the other side knows each file – lonesome May 30 '14 at 10:43
  • Well that's what he said. It can't. You have to separate them. – user207421 May 30 '14 at 11:16
  • I would concur with Jon on this. You can either initiate new connection for each file, which is more expensive or send the length of the file along with the rest of the data. – ganaraj May 30 '14 at 11:54
  • @EJP well done to state the obvious! how to seperate them? – lonesome May 30 '14 at 12:21
  • Well done to *miss* the obvious, that @JonSkeet has already stated, again. "Consider using a length word prefix." – user207421 May 31 '14 at 18:04
  • @EJP what if you look at the new issue? – lonesome Jun 03 '14 at 03:02

1 Answers1

1

How about writing it into a ZipOutputStream where you can receive the file on the other side as a single stream. Once you have the entire output, you can write the reverse code to deflate the zip file and get all the files. Providing a sample code for writing the Zip into your socket stream, you can build your code over this.

Refer this length for a sample Server and Client implementation sending the file using a ZipOutputStream Stick2Code

ganaraj
  • 420
  • 3
  • 13
  • ok, but how to unzip it in the client side? just replace the zipoutputstream with zipinputstream? – lonesome May 30 '14 at 12:24
  • and last line of ur answer not correct, there is no method called **copy** – lonesome May 30 '14 at 12:32
  • The IOUtils.copy was for illustruation, you are free to write your own code that will copy the bytes from the InputStream to the Zip output stream. – ganaraj May 30 '14 at 13:04
  • Import the IOutils belonging to the following package "org.apache.commons.io.IOUtils". This is available with the apache commons-io project version 1.3.2. Maven dependency org.apache.commons commons-io 1.3.2 – ganaraj May 30 '14 at 13:05
  • AS for inflating the file back you could use the java.util.zip.Inflater. You can refer some of the documentation in following links. [oracle documentation](http://docs.oracle.com/javase/7/docs/api/java/util/zip/Inflater.html), or the following [link](http://stackoverflow.com/questions/6173920/zlib-compression-using-deflate-and-inflate-classes-in-java) – ganaraj May 30 '14 at 13:16
  • my problem is" where should i save these files"? i mean, how to define **FileOutputStream** in client? – lonesome May 31 '14 at 09:58
  • @user1064929: Updated a code to send and read a zip stream. Hope this helps. – ganaraj May 31 '14 at 14:36
  • @user1064929 : Have updated a blog with a working sample code for acheiving a transfer of file over tcp/ip, with parallel transfer to speed up the process. [Send Multiple Files over a single Socket Connnection](http://stick2code.blogspot.in/2014/05/send-multiple-files-over-single-socket.html) and [Transfer Files Between two Systems Over User Defined Ports](http://stick2code.blogspot.in/2014/06/transfer-files-between-two-systems-over.html) – ganaraj Jun 06 '14 at 05:31