5

I am trying to send a file from one computer to another using Java. I have written the code below, it works fine if both sender and receiver are started in the same computer but if they work on different machines received file size is bigger than the original file and it is corrupted.

Note: I am trying to transfer files which are max 10 MBs.

How can I fix this?

Sender:

ServerSocket server_socket = new ServerSocket(8989);
File myFile = new File(myPath);

Socket socket = server_socket.accept();
int count;
byte[] buffer = new byte[1024];

OutputStream out = socket.getOutputStream();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(myFile));
while ((count = in.read(buffer)) > 0) {
     out.write(buffer, 0, count);
     out.flush();
}
socket.close();

Receiver:

Socket socket = new Socket(address, 8989);
FileOutputStream fos = new FileOutputStream(anotherPath);
BufferedOutputStream out = new BufferedOutputStream(fos);
byte[] buffer = new byte[1024];
int count;
InputStream in = socket.getInputStream();
while((count=in.read(buffer)) >0){
    fos.write(buffer);
}
fos.close();
socket.close();
b4da
  • 3,010
  • 4
  • 27
  • 34
  • i have used this funtion for sending and and recieving file but i dont want to close the socket as i have to perform some other function using the socket but if i dont close the sock file recieving isn't get complete whats the soluion for that – zeeshan nisar May 09 '16 at 11:59

3 Answers3

23

On the client side you write up to count bytes and send them:

while ((count = in.read(buffer)) > 0) {
  out.write(buffer, 0, count);

on the server side you read up to count bytes - but then you write the whole buffer to file!

while((count=in.read(buffer)) > 0){
  fos.write(buffer);

Just change it to:

fos.write(buffer, 0, count);

and you'll be on the safe side. BTW your program has another small bug: read() can return 0 which doesn't mean InputStream ended. Use >= instead:

count = in.read(buffer)) >= 0

Have you considered IOUtils.copy(InputStream, OutputStream) from Apache Commons? It would reduce your whole while loops to:

OutputStream out = socket.getOutputStream();
InputStream in = new FileInputStream(myFile);
IOUtils.copy(in, out);
socket.close();

Less code to write, less code to test. And buffering is done internally.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • @Vamshi. if you are using IOUtils then yes because it implements its own buffering. – Ross Apr 23 '15 at 01:46
3

Remember that in.read(buffer) not necessarily fills up the whole buffer with new data. Therefore you should make sure you don't write the whole buffer. Change

while((count=in.read(buffer)) >0){
    fos.write(buffer);
}

to

while((count=in.read(buffer)) >0){
    fos.write(buffer, 0, count);
}
Aleksander Blomskøld
  • 18,374
  • 9
  • 76
  • 82
1

sender

Socket sock = new Socket("127.0.0.1", 5991);
        System.out.println("Connecting.........");
        File myFile = new File("/root/qrcode/");
        File[] files = myFile.listFiles();
       OutputStream os = sock.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);
                            DataOutputStream dos = new DataOutputStream(bos);

                            dos.writeInt(files.length);
                            long totalBytesRead = 0;
                            int percentCompleted = 0;
                            for(File file : files)
                            {
                                     long length = file.length();
                                     dos.writeLong(length);

                                     String name = file.getName();
                                     dos.writeUTF(name);

                                     FileInputStream fis = new FileInputStream(file);
                                     BufferedInputStream bis = new BufferedInputStream(fis);

                                     int theByte = 0;
                                     while((theByte = bis.read()) != -1)
                                     {
                                        totalBytesRead += theByte;


                                        bos.write(theByte);
                                     }
                                    //  System.out.println("file read");
                                     bis.close();
                                 }

                                dos.close();


        //Closing socket  
        sock.close();

receiver

ServerSocket serverSocket = new ServerSocket(5991);  

    while(true) {  
        Socket clientSocket = null; 
        System.out.println("Starting...");
        clientSocket = serverSocket.accept();  

        InputStream in = clientSocket.getInputStream(); //used

        BufferedInputStream bis = new BufferedInputStream(in);

        String dirPath  ;
        dirPath = "/root/NewFolder";

        try{
            DataInputStream dis = new DataInputStream(bis);

            int filesCount = dis.readInt();
            File[] files = new File[filesCount];
            long f_l = 0;
            int count =0 ;
            long totalBytesRead = 0;
            int percentCompleted = 0;

            for(int i = 0; i < filesCount; i++)
            {
                long fileLength = dis.readLong();
                String fileName = dis.readUTF();

                f_l = f_l +fileLength;
                files[i] = new File(dirPath + "/" + fileName);

                FileOutputStream fos = new FileOutputStream(files[i]);
                BufferedOutputStream bos = new BufferedOutputStream(fos);

                int tot = 0;
                for(int j = 0; j < fileLength; j++) {

                    bos.write(bis.read());
                }

                bos.close();

            }

        }catch(Exception ex)
        {
            System.out.println("error in socket programming ");
        }
    }