Search code examples
javasocketsfile-handling

FileOutputStream not closing properly?


I have a socket program that can share files and class objects. But when I share files, the server socket sends files correctly without any errors. The client-side also gets the target file sent from the server and stored in the local folder correctly (also I can open it). But after receiving a file, the FileOutputStream is not closing. To check that, I put a print command at the end of the process. I'm using Lombok to perform close operations. The file that is written is always lower than 21MB in size and the file type is .pdf(because the server manages it). This is my code block.

Path dir = Paths.get("Temp");
if (Files.notExists(dir)) {
   Files.createDirectory(dir);
}
Path file = Files.createTempFile(dir, null, ".pdf");

InputStream inputStream = socket.getInputStream();

@Cleanup
FileOutputStream fileOutputStream = new FileOutputStream(file.toFile());

byte[] buffer = new byte[1024];
int bytesRead;

while ((bytesRead = inputStream.read(buffer)) > 0) {
   fileOutputStream.write(buffer, 0, bytesRead);
}

System.out.println("ok2");
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
</dependency>

I also tried this with try-with-resources but no good.


Solution

  • The server is never closing the connection. Therefore, the read() call on the inputStream eventually 'blocks' (it just sits there, waiting for more data; data that will presumably never come). You haven't exited the block so the FileOutputStream is never closed. You can check this if you want by adding some sysout statements or using a debugger to doublecheck this is the reason (there are some exceedingly esoteric alternative explanations, you might want to double check this).

    It doesn't matter if you're asking lombok to close that or try-with - neither one would close here, as the code is still in the block.

    The solution is generally one of protocol. You haven't explained what this server is. Many options:

    • As part of the protocol, you know how many bytes there are, and you're supposed to track whether you're done or not. Once you have read as many bytes as will come, don't call read() again as that would block. Your while condition must not go > 0, instead decrement a bytesLeft counter and the while loop should loop until it hits 0.
    • You wrote the server, the protocol states the connection is closed when the file is done, so there's this code you pasted isn't the problem, it's the server code.
    • Same but someone else wrote the server, still, bugs in the server.