0

How to send a file from server to client?

I have a server and a client which can both send messages to eachother. When I send a request on my client, it sends a message to my server and my server will create a file on it's filesystem and send it to my client line per line.

Client:

socket = new Socket(InetAddress.getByName(address), Integer.parseInt(port));
writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
writer.println("GD"); // GD stands for get data

Server:

ServerSocket serverSocket = new ServerSocket(Integer.parseInt(port), 0, InetAddress.getByName(address));
socket = serverSocket.accept();
OutputStream writer = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

// SNIP - readline happens in a thread etc. Not important

String line = reader.readLine();

if("GD".equals(line)) {
    File dataFile = getDataFile();

    BufferedReader br = new BufferedReader(new FileReader(dataFile));
    String line;

    while(null != (line = br.readLine())) {
        writer.send("FD;" + line);
        // FD stands for file data so my client knows that it's a line from the requested file
    }
}

If my file is rather big (let's say several hundred thousands of lines), it means my server needs to send the data line per line. Not to mention that it has to read through the file and use it's memory to store the strings before sending them. It feels very inefficient.

I was wondering if there is a way to send a file from my server to my client without wasting this many resources. Can anyone help me with this?

So in short: Can I send a file from my server to my client without having to stream through my file and send it line per line.

JREN
  • 3,572
  • 3
  • 27
  • 45
  • 1
    Where is the resource wasted? A file with 5k lines is not unusual. Also your code seems to be just fine. – Uwe Plonus Jun 28 '13 at 12:25
  • Well, let's assume that my file is much bigger then. I don't want to run into any problems if I get an unusual file in the future. – JREN Jun 28 '13 at 12:27
  • I do not see a reason to ping-pong, request-response-message. Is it important to the question? – Val Jun 28 '13 at 12:29
  • @Val no it's not important, it's part of a much bigger application. The only thing that I'm actually asking is if there's a way to send my data from my server to my client without having to stream through my file and send it's contents line by line. – JREN Jun 28 '13 at 12:31
  • So, you basically ask for a function copy(stream1, stream2)? If it exists, I do not think that generic function will "FD" prefix your every line. – Val Jun 28 '13 at 12:35
  • @Val forget the FD prefix, I'll figure something out for that myself – JREN Jun 28 '13 at 12:37

1 Answers1

2

Unless you need to manipulate the lines (you seem to be inserting the characters "FD;"), why don't you copy a buffer of bytes from one stream to another stream ?

Something along the lines of

byte[] buffer = new byte[8*1024]
int len;
while ( (len= in.read(buffer)) > 0 ) out.write(buffer, 0, len);

Adjust the buffer size to your network conditions.

Now, IMHO, don't even waste your time doing all this. Grab the excellent, and optimized, apache commons-io and do IOUtils.copy(in, out)

(edit) by the way, manipulating lines/strings without specifying encoding the way you are doing it is a receipe for errors on non-ascii files.

Bruno Grieder
  • 28,128
  • 8
  • 69
  • 101