1

I'm trying to write a mini FTP application that reads binary data from a file and sends it to a client. My program usually does not behave as desired and usually ends up sending the file, but not doing it completely (i.e. send text file and the content is blank). I think it may be because I use the filereader to read the line, although I do not quite understand why this would be a problem. Here is the relevant code:

File file = new File(rootDirectory, name);
int filenum = (int)file.length();
long filelen = file.length();
System.out.println("File is: " + filenum + " bytes long");
socketOut.writeLong(filelen);
fileIn = new BufferedReader(new FileReader(file));
System.out.println("Sending: " + name);

while((line = fileIn.readLine()) != null){
       socketOut.writeBytes(line);
       socketOut.flush();
}
6
  • Please post your error with stack trace. Commented May 7, 2014 at 23:24
  • Why are you reading and writing the same file? I think you mean DataOutputStream bos = new DataOutputStream(socketOut);? Your code is a bit confusing... Commented May 7, 2014 at 23:25
  • im sorrry, I had that for testing, I didnt use that outputstream Commented May 7, 2014 at 23:26
  • sorry for not being clear:there is no error, when i send a text file for example, its blank Commented May 7, 2014 at 23:27
  • 1
    two problems, readers read characters not bytes, so you cannot sent number of bytes and then the characters. The other problem is that readline can convert and cut off line endings. Just uns the FileInputStream and read byte[] or use one of the IOUtils to pump data. Commented May 8, 2014 at 0:21

3 Answers 3

2

The problem is that Readers/writers read text (as opposed to Input~/OutputStreams). FileReader internally uses the default operating system encoding. That conversion will never do for binary files. Also note, that readLine discards the line ending (\r\n, \n or \u0085). As of Java 7 you can do

Files.copy(file.toPath(), socketOut);

instead of the wile loop.

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

2 Comments

I had a feeling the bufferreader was a part of it, thank you for clearing that up. Although if I am reading the file into the string variable line, then writing it as bytes, would that not work the same?
@James No. String is not a container for binary data.
1

Joop's solution is perfect for Java7 (or later). If you are stuck on an older version (or want to extend your tool arsenal anyway), have a look at the following free libraries:

  • Apache Commons IO (actually all Apache Commons are interesting to look at). There you can do IOUtils.copy(...)
  • Google Guava There it is a little more complicated but flexible. Use ByteSource.copyTo(ByteSink)

I like the caching in the Google libraries, pretty neat

Comments

1

If you don't have Java 7 and don't want to add external libraries, the canonical copy loop in Java for streams is as follows:

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

where count is an int, and buffer is a byte[] of any non-zero size. It doesn't have to be anywhere near the size of the file. I usually use 8192.

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.