I am trying to send any file via TCP from my client (on a mobile device) to a console server (on a computer).
Connecting, sending, receiving, in my opinion, is normal, but there is a problem with writing data to a file.
For example, music is recorded into it several times, and only one “line” is recorded for a picture.
I suspect that the problem is somewhere in the cycle, but I can not understand for sure.

Server code in which the bytes are received from the socket and written to the file:

String fileName; int size; try { size = sInput.readInt(); fileName = sInput.readUTF(); try { FileOutputStream fos = new FileOutputStream("C:\\Users\\admin\\Downloads\\FileSenderDownload\\" + fileName); byte[] buffer = new byte[size]; int receivedBytes = 0; while (true) { if (receivedBytes == -1) break; receivedBytes = input.read(buffer); System.out.println(receivedBytes); fos.write(buffer, 0, buffer.length); } System.out.println("Запись"); } catch (IOException ex) { ex.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } 

Client code to send the file:

 try { DataOutputStream out = new DataOutputStream(socket.getOutputStream()); ObjectOutputStream output= new ObjectOutputStream(socket.getOutputStream()); output.writeInt((int)sendingFile.length()); output.flush(); System.out.println("File size" + sendingFile.length()); output.writeUTF(sendingFile.getName()); output.flush(); System.out.println("File name" + sendingFile.getName()); FileInputStream input = new FileInputStream(sendingFile); int size = (int)sendingFile.length(); byte[] buffer = new byte[size]; int receivedBytes; while(true) { receivedBytes = input.read(buffer); if (receivedBytes == -1) { break; } if (receivedBytes > 0) { out.write(buffer, 0, receivedBytes); out.flush(); } } input.close(); out.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } 

How to fix this code?

    1 answer 1

    Problems in the while (true) on the server:

    1. receivedBytes = input.read(buffer); must be before the if (receivedBytes == -1) check.
    2. It is necessary to specify the number of bytes read in fos.write , and not the buffer length: fos.write(buffer, 0, receivedBytes);

    As a result, the cycle looks like this:

     while (true) { receivedBytes = input.read(buffer); if (receivedBytes == -1) break; totalCount += receivedBytes; fos.write(buffer, 0, receivedBytes); } 

    And about the code in general: using try-with-resources and constants helps improve the code:

    Customer:

     public void send(File sendingFile) { try (Socket socket = new Socket(SERVER_ADDRESS, PORT); ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); FileInputStream input = new FileInputStream(sendingFile)) { output.writeInt((int)sendingFile.length()); output.writeUTF(sendingFile.getName()); byte[] buffer = new byte[BUFFER_SIZE]; int readCount; while ((readCount = input.read(buffer)) != -1) { output.write(buffer, 0, readCount); } } catch (IOException e) { e.printStackTrace(); } } 

    Server:

     private void get(Socket socket) { try (ObjectInputStream sInput = new ObjectInputStream(socket.getInputStream())) { int size = sInput.readInt(); String fileName = sInput.readUTF(); try (FileOutputStream fos = new FileOutputStream(FILES_DIRECTORY + fileName)) { byte[] buffer = new byte[BUFFER_SIZE]; int receivedBytes = 0; while (receivedBytes < size) { int readCount = sInput.read(buffer); if (readCount == -1) { break; } receivedBytes += readCount; fos.write(buffer, 0, readCount); } } catch (IOException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } 

    If only one file is always transmitted through one socket connection, then you can not bother with the count of the number of bytes received on the server and do it by analogy with the client:

     try (FileOutputStream fos = new FileOutputStream(FILES_DIRECTORY + fileName)) { byte[] buffer = new byte[BUFFER_SIZE]; int readCount; while ((readCount = sInput.read(buffer)) != -1) { fos.write(buffer, 0, readCount); } } 

    With this assumption, the code can be simplified even more using Files.copy :

    Customer:

     public void send(File sendingFile) { try (Socket socket = new Socket(SERVER_ADDRESS, PORT); ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream())) { output.writeUTF(sendingFile.getName()); Path path = sendingFile.toPath(); Files.copy(path, output); } catch (IOException e) { e.printStackTrace(); } } 

    Server:

     private void get(Socket socket) { try (ObjectInputStream sInput = new ObjectInputStream(socket.getInputStream())) { String fileName = sInput.readUTF(); Path path = Paths.get(FILES_DIRECTORY + fileName); Files.copy(sInput, path, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { e.printStackTrace(); } } 
    • Thank you very much, it really worked. It's a pity I can't raise the rating to the answer, but thanks anyway. - Kostya M
    • @KostyaM to health. The main thing is that the answer was accepted. And you can plus and then (if you achieve the desired reputation and if you have a desire in the future) - Regent