0

I am writing a file storage and transfer system using Java. Here's the code on the client side to receive a file:

public static void receiveFile(Socket socket) throws IOException{   
    String fileLocation="/home/limafoxtrottango/Downloads/receivedFile";
    int bytesRead=0;
    int current = 0;
    FileOutputStream fileOutputStream = null;
    BufferedOutputStream bufferedOutputStream = null;

    try {
        // receive file
        byte [] byteArray  = new byte [60022386];
        System.out.println("Waiting to receive a file...");
        //reading file from socket
        InputStream inputStream = socket.getInputStream();
        fileOutputStream = new FileOutputStream(fileLocation);
        bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
        bytesRead = inputStream.read(byteArray,0,byteArray.length);                 //copying file from socket to byteArray
        current = bytesRead;
        do {
            bytesRead =inputStream.read(byteArray, current, (byteArray.length-current));
            if(bytesRead >= 0) current += bytesRead;
        } while(bytesRead > -1);
        bufferedOutputStream.write(byteArray, 0 , current);                         //writing byteArray to file
        bufferedOutputStream.flush();                                               //flushing buffers

        System.out.println("File " + fileLocation  + " downloaded ( size: " + current + " bytes read)");
    } catch(SocketException e){
        System.out.println("Some error occured");
    }
    catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    finally {
        if (fileOutputStream != null) fileOutputStream.close();
        if (bufferedOutputStream != null) bufferedOutputStream.close();
        if (socket != null) socket.close();
    }
}

While receiving a file, I get the following error:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
    at java.lang.System.arraycopy(Native Method)
    at java.io.BufferedOutputStream.write(BufferedOutputStream.java:128)
    at Test.receiveFile(Test.java:211)
    at Test.main(Test.java:70)

Note: The error is in the following line of the code:

bufferedOutputStream.write(byteArray, 0 , current);  

After debugging, I found-out that the client does not have any data in it's input stream, and hence, the read() method always returns -1 (eof). But the server is sending the file successfully.

Here is the code for the server:

public static void sendFile(Socket socket, String fileLocation)
{
    FileInputStream fileInputStream = null;
    BufferedInputStream bufferedInputStream = null;
    OutputStream outputStream = null;
    File file = new File (fileLocation);
    byte [] byteArray  = new byte [(int)file.length()];
    try {
        socket=new Socket(socket.getInetAddress(),port_no);
        fileInputStream = new FileInputStream(file);
        bufferedInputStream = new BufferedInputStream(fileInputStream);
        bufferedInputStream.read(byteArray,0,byteArray.length); // copied file into byteArray

        //sending file through socket
        outputStream = socket.getOutputStream();
        System.out.println("Sending " + fileLocation + "( size: " + byteArray.length + " bytes)");
        outputStream.write(byteArray,0,byteArray.length);           //copying byteArray to socket
        outputStream.flush();                                       //flushing socket
        System.out.println("Done sending!");    
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

And here is my call to the above method:

sendFile(clientSocket, "/home/limafoxtrottango/Downloads/serverDownloads/"+sender);

The thing is that the server is successfully writing the byte into the stream, but the client doesn't seem to have any data in it's input stream.

Prashant Pandey
  • 2,892
  • 1
  • 13
  • 29
  • 1
    Possible duplicate of [What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?](http://stackoverflow.com/questions/5554734/what-causes-a-java-lang-arrayindexoutofboundsexception-and-how-do-i-prevent-it) – Pradeep Simha Feb 04 '17 at 18:28
  • 3
    Try stepping through the code in your IDE debugger. You'll learn a lot more that way than if we tell you what's wrong. – Jim Garrison Feb 04 '17 at 18:30
  • Unrelated comment: this is why tabs shouldn't be used. It renders differently in every editor -_- makes life hell for the people who indents code on SO – denvercoder9 Feb 04 '17 at 18:32
  • Debugging now. It is the first time I'll be using this feature of my IDE, so thanks to Jim Garrison. – Prashant Pandey Feb 04 '17 at 18:37
  • @Jim Garrison, I figured-out that there is no data in the input stream, since the number of bytes read is always -1 (which means that it has reached the eof). This might imply that the server is not sending any data. But I sure that it is. Could you help me out? – Prashant Pandey Feb 04 '17 at 19:13

2 Answers2

0

https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#read(byte[],%20int,%20int)

inputStream.read(byteArray,0,byteArray.length); may return -1 in some cases as given in documentation above. Please cater for such situations.

In addition, I would suggest to use solution given here for both client and server: Efficient way to write InputStream to a File in Java (Version 6)

Client code:

final Path destination = Paths.get(fileLocation);
try (
    final InputStream in = socket.getInputStream();
) {
    Files.copy(in, destination);
}

Server code:

try (
    final InputStream in = new FileInputStream(fileLocation);
) {
    Files.copy(in, socket.getOutputStream());
}

Kind regards, Bala

Community
  • 1
  • 1
BhalchandraSW
  • 716
  • 5
  • 13
  • I read the documentation, and it says that the method returns -1 when it has reaches the eof. Since it always returns -1, my guess is it is not receiving any data in the stream. As for the second solution, I shall try it out. – Prashant Pandey Feb 04 '17 at 19:20
  • Also, using the second method, the downloaded file has size=0B. So, I guess there was no data to copy to the file. – Prashant Pandey Feb 04 '17 at 19:24
  • @PrashantPandey If your server keeps giving 0 bytes in socket, then I believe issue lies outside this code. However, it would be good to keep all the checks in this code for such situations. :) – BhalchandraSW Feb 04 '17 at 19:34
  • I have added the code for the server. Could you please have a look? – Prashant Pandey Feb 04 '17 at 19:38
  • I assume your sendFile(Socket, String) method receives Socket object after invoking accept on ServerSocket object. If not try that and let us know. The accept method waits until a client starts up and requests a connection on the host and port of this server. – BhalchandraSW Feb 04 '17 at 20:50
  • You're correct. The accept on the ServerSocket object is indeed invoked first. – Prashant Pandey Feb 04 '17 at 21:04
0

The server isn't sending anything, contrary to your title. It is closing the connection immediately, so bytesRead is initially -1 and never changes, and you aren't defending against that, so you get the ArrayIndexOutOfBoundsException.

However in the code you posted, the server is sending something but never closing the socket, which is another bug you need to fix. It is also ignoring the count returned by FileInputStream.read() and assuming it filled the buffer, which isn't part of the specification.

So either this is not the real server code or you are connecting to something else, or the server got an IOException that you haven't mentioned.

It's curious that you use two different pieces of code for copying. The standard way to copy a stream in Java is this:

char buffer = new char[8192]; // or whatever size you prefer > 0
int count;
while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

Use this at both ends. There is no need for heroically sized buffers, or buffers the size of the file, or assuming that the file size fits into an int.

user207421
  • 289,834
  • 37
  • 266
  • 440