2

I'm trying to write client and server side on java. Server side is ok (checked on several clients).

So, the problem is on client side. I allocate memory for bytearray, read from BufferedInputStream and write to that bytearray. Then writing from bytearray to FileOutputStream. Everything is ok but free space of bytearray is filling by NULLs, so received file is not correct(e.g. images).

I found 2 decision of that problem:

  1. Read to bytearray till the end of file(but I don't know where the end of file)
  2. Read from BufferedInputStream to FileInputStream, but it doesn't work:

I actually need receive header and file. Output header to console and write the file to the disc.

Full Source

public class SClient {
private static int bufferSize = 8192;
/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    System.out.println("Enter the address:");
    BufferedReader bufferRead = new BufferedReader
                (new InputStreamReader(System.in));

    try {
        String address = bufferRead.readLine();
        System.out.println("Enter the extention of receiving file:");
        String fileExt = bufferRead.readLine();
        // TODO code application logic here
        Socket socket = new Socket(address,4040);
        BufferedInputStream bis = new BufferedInputStream
                (socket.getInputStream());

        BufferedOutputStream bout = new BufferedOutputStream
                (socket.getOutputStream());
        System.out.println("Enter the request:");
        String message = bufferRead.readLine();// GET /index.html HTTP/1.0

        System.out.println("Header read");
        if(message!=null){
            bout.write(message.getBytes());
        }
        FileOutputStream fout = new FileOutputStream("out"+fileExt);
        String s1 = "\r\n\r\n";
        bout.write(s1.getBytes());
        bout.flush();
        System.out.println("Header sent");

        byte[] res = new byte[bufferSize];
        int got;
        while((got = bis.read(res))!=-1){
            fout.write(res,0,got);
        }
        fout.close();
        bout.flush();
        socket.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
  }
}

Server side source:

    String endLine = "\r\n";
    File f = new File(fileName);
    FileInputStream fstream;
    fstream = new FileInputStream(f);
    response = "HTTP/1.0 200 OK" + endLine;
    header = "Content-type: "+ contentType + endLine + "Content-length: " + f.length() + endLine + endLine;
    bout.write(response.getBytes());
    bout.write(header.getBytes());
    while(fstream.read(buffer) != -1) {
        bout.write(buffer);
    }
    System.out.println("Message sent");
    bout.flush();
    socket.close();

3 Answers 3

4

You have to remember the amount of bytes you read into your buffer and must only write those bytes back. Like this here:

int got;
while ((got = bis.read(res)) != -1) {

    fout.write(res, 0, got);
}
Sign up to request clarification or add additional context in comments.

19 Comments

Thanks, your code helped me to remove NULLs after Header, but image still doesn't show, because I've nulls at the end of file.
@sanatik Socket streams won't end with -1 because until they are closed, they don't end. Instead they rely on terminator characters (for example) or known byte lengths...
@sanatik I guess you already close the file properly, so you are not seeing a partially flushed file or something like that. I also asume you just want to send a single File through your socket, not anything else. Because the code reads everything from the socket until it closes. Maybe show the code to load / show the image or explain on what you want to do so I can check if anything is wrong with that.
@sanatik If you have nulls at the end of the file you haven't used this code. You need to use it at both ends.
@EJP what means both ends?
|
3

Not the answer, but a suggestion...

This doesn't look right. Basically, you are reading a an array of bytes up to a maximum of bufferSize, but then just writing a single byte to the output stream. You are also risking an index out of bounds error because you are incrementing the i on each loop unbound...

while (bis.read(res) != -1) {
    fout.write(res[i]);
    i++;
}

Instead you should be using something more like...

int bytesRead = -1;
while ((bytesRead = bis.read(res)) != -1) {
    fout.write(res, 0, bytesRead);
}

Which will write a the byte array up to the number of bytes read...

The next problem is, you need some way to know when the you've reached the end of the file.

Now, you can put in some kind of terminator character but that could, potentially, corrupt the output file.

Now, because I'm a UI developer, I like to know how much I'm downloading. So, the first then you could send down the stream is the number of bytes to expect, then you can simply keep a count of the bytes read and stop when you've reached your limit...

This would require a slight change to your server, it would need to be able to send a long value, indicating the size of the image (in bytes) to be read and a \n

BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String header = br.readLine();
long expectedBytes = Long.parseLong(header);

Then you would simply loop until you have the required number of bytes...

int bytesRead = 0;
int totalBytes = 0;
while (totalBytes < expectedBytes) {
    bytesRead = bis.read(res);
    fout.write(res, 0, bytesRead);
    totalBytes += expectedBytes;
}

// Flush and close your steams as required.

I did something simular for a screen sharing question

3 Comments

As I read, reading by bytes is the best way. Using BufferedReader can make some misrepresentations.
@sanatik You might need to expand that a little, I'm not sure I understand what you're trying to say. Yes, reading/writing a byte array is more efficient then simply reading/writing a single byte, if the buffer size works with the underlying network requirements
@sanatik 'Misrepresentations' such as what?
1

Memorize the canonical way to copy streams in Java:

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

Use any buffer size greater than zero, typically 4k or 8k.

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.