0

Ok.... Trying to learn java on my own, been having trouble with this for awhile. I'm trying to transfer a large file over the network using sockets and buffered input and output streams. Doesn't matter what size file I try to transfer. Hopefully I posted my code correctly, I know theres probably many problems with this code, although it compiles and runs ok, I get an IndexOutOfBoundsException the second the client and server go into the while loops, the server gets it during the first bis.read(buf,0,len) and the client gets it during the while(off = fis.read(buf,0,len)..... Any help would be greatly appreciated

//Server Receive code receive method and main for testing
    public File receive(Socket socket) throws IOException{

        //temporarily hard coded filename
        File file = new File("C:\\users\\tom5\\desktop\\sales\\input.dat");
        DataInputStream dis = new DataInputStream(socket.getInputStream());
        FileOutputStream fos = new FileOutputStream(file);
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        //reads file length from datainputstream
        int len = dis.readInt();
        dis.close();
        int bytesRead=0;
        //create buffer
        byte[]buf = new byte[4092];
        int off = 0;

        //read from BufferedInputStream and write to FileOutputStream?
        while(bytesRead < len) {
            bis.read(buf,0,len);
            fos.write(buf,0,len);
            bytesRead++;
        }
        fos.close();
        bis.close();
        return file;
    }
    public static void main(String[]args) throws IOException{
        Server server = new Server();
        Socket socket =server.accept();
        File file = server.receive(socket);
    }
}

//Client sending code

    public void send(Socket socket,File file) throws IOException{
        FileInputStream fis = new FileInputStream(file);
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        int len = (int)file.length();
        dos.writeInt(len);
        dos.flush();
        dos.close();
        System.out.println(file.length());

        byte[]buf = new byte[4092];
        int off= 0;
        while((off = fis.read(buf,0,len)) != -1  ){
            bos.write(buf,0,len);       
        }
    }

    public static void main(String[]args) throws UnknownHostException, IOException{
        Client client = new Client();
        Socket socket =client.connect("localhost",1055);
        File file = new File("C:\\users\\tom5\\desktop\\movie.avi");
    }
}
3
  • Oen thing I noticed right off the bat is that you have two main methods. Commented Apr 19, 2012 at 0:32
  • 1
    I believe those are the code for the server and for the client, not running simultaneously. Commented Apr 19, 2012 at 0:36
  • Change fis.read(buf,0,len) to fis.read(buf,0,4092) and bos.write(buf,0,len) to bos.write(buf,0,off) for starters. Similar problem in server part i see. Commented Apr 19, 2012 at 0:43

3 Answers 3

3
while(bytesRead < len) {
    bis.read(buf,0,len);
    fos.write(buf,0,len);
    bytesRead++;
}

You're trying to read len bytes into buf, which is larger than its length, and you're incrementing bytes by 1 each time even though read can read multiple bytes. It should be more like:

while(bytesRead < len) {
    int n = bis.read(buf);
    fos.write(buf, 0, n);
    bytesRead += n;
}

or if there's the possibility of extra bytes after the file you don't want to read:

while(bytesRead < len) {
    int n = bis.read(buf, 0, Math.min(buf.length, len - bytesRead));
    fos.write(buf, 0, n);
    bytesRead += n;
}

There is a similar problem in the write method. You're storing the return value in off but you never use it.

Sign up to request clarification or add additional context in comments.

Comments

0

You are wrapping the stream twice, once as dis and once as bis. This means that dis is not buffered but when you close it, you close the underlying stream.

I suggest you wrap use ONLY

DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

If you want an efficient buffer size, I suggest you a power of 2, i.e 4096 rather than 4092.

A @fgb notes: You correct use the length read() on the sending size but ignore it on the receiving size (The irony being that you usually get the size you ask for when reading a file, but not so much when reading a socket)

Consider using one common InputStream to OutputStream copier method which works in both situations e.g. like IOUtils.copy().

1 Comment

makes sense, didn't realize I could wrap a DataInputStream in a BufferedInputStream, before I was only using the DIS stream to read Ints and UTF.
0

You are using fixed buffer size. Try this:

byte[] mybytearray = new byte[(int) myFile.length()];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.