I'm trying to build a simple file transfer program that transfers a file from a server to a client. I gave it a try myself by simply writing the file to an ObjectOutputStream. This didn't work. I did some research and I found a whole swath of solutions that utilize a byte[] in which the contents of the file is written to that array and written to a OutputStream. Unfortunately none of the writers explain the code very well.

I was curious if someone could explain to me why a byte[] is needed to read the file as opposed to my solution or even just reading the contents of the file into a String and sending that. What is it about a file and streams that require a solution like this? Thanks for any help.

  • 1
    wonder what was unclear in this comment in your prior deleted question that explained this, "It's common practice to use a byte array to copy a file..." etc – gnat Jun 14 '17 at 5:59
  • I was hoping that someone could go into a little more detail. Is that too much to ask? – namarino Jun 14 '17 at 6:01
  • You can't write a file to an ObjectOutputStream. Are you trying to write a File to an ObjectOutputStream? Because a File is just a file name, not the actual file itself. – immibis Nov 20 '18 at 4:23

A stream is simply a sequence of objects. If you are attempting to stream a file of unknown type, i.e. you are simply pushing raw data and not interpreting its contents, the usual representation is a byte stream.

In Java, object streams are designed to send Objects. Even if you send a byte array, it will send an array object, not a sequence of bytes. They use serialization to send more complex objects which includes metadata.

It sounds like you simply want the sequence of bytes that constitute the file contents.

There are several ways to make this work, using either old-school sockets and streams or NIO. I suggest starting with the old way so you understand how everything works, then moving on to NIO (which is generally just an abstraction of lower level primitives anyway).

Your server should open a ServerSocket, and the client should connect to the server. On the server you open an output stream from the socket, while the client opens an input stream. Note that the socket interface uses the interfaces, not anything like object streams. If you want different streams, you will need to wrap them.

I suggest wrapping each in a buffered input or output stream, and sending the bytes across using that. The key here is that both ends of the stream need to use the same stream abstraction. If one end uses an object stream and the other does not, it will not work. By requesting streams from the sockets, it will work: they return private implementations that wrap the socket and are compatible.

Once you understand how all the parts fit together, I suggest moving up to NIO which makes this a lot easier, but hides important details that it appears you need to learn about before you can safely abstract them away.

  • Oh ok that makes sense. So if object streams are designed to send objects, then why does it not work when I send a file? Isn't that an object? Why is it that I have to read the file and send it's contents? – namarino Jun 14 '17 at 6:10
  • 1
    @namarino What does a “file” object represent? It represents not the contents of the file, but a location in the file system. This location has no meaning on another machine. – amon Jun 14 '17 at 7:36
  • 1
    @namarino amon is correct: a java.io.File object represents a handle to a file, not the contents itself. If you read the JavaDoc for the class, it even says it is an abstract concept for a file that may or may not exist. Think of it this way: if you want to read a simple text file, you pass the File into a FileReader which actually reads the file. The File object itself does not read the file, it simply acts as a signpost to tell other classes which file you want to manage. – user22815 Jun 14 '17 at 17:12
  • Interesting, I never knew that. So in my solution, you're just sending the path of the file which means absolutely nothing to the other computer. So what's the advantage of using a byte[] versus just a String to store the data? – namarino Jun 14 '17 at 18:00
  • @namarino sending bytes means the raw contents of the file are transferred as-is. If you send a string, that implies that the library code that reads the file is interpreting the contents. For example, the file may have text in UTF-8, but Java strings are UTF-16. Newlines may be in Windows format (\r\n) on disk, but are in Unix format (\n) in memory. The client may not get the exact same version of the file. Embedded EOF characters (\z) might be valid in the file format, but when read as text, may cause the file to be truncated. – user22815 Jun 14 '17 at 18:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.