The application will transfer multiple files, and it is important to me that they be transferred with names. To do this, you need to send each time a message with the name of the file or is it something else can be done?
2 answers
The first byte send the length of the file name, the next 4 bytes - the length of the file, followed by the bytes of the file name, and then the bytes of the file itself. Or, in order not to bother with converting data, you can expand the fields a bit:
Server.java
package com.example; import java.io.File; import java.io.FileInputStream; import java.io.OutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.net.ServerSocket; import java.net.Socket; public class Server { private static int PORT = 2121; private static String FOLDER = "./files"; public static void main(String[] args) { File sourceDir = new File(FOLDER); try (ServerSocket listener = new ServerSocket(PORT)) { while (true) { try (Socket socket = listener.accept(); OutputStream out = socket.getOutputStream()) { for (String fileName : sourceDir.list()) { // ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²ΡΠ²Π°Π΅ΠΌ ΡΡΡΠΎΠΊΡ, ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡΡ ΠΈΠΌΡ ΡΠ°ΠΉΠ»Π°, // Π² ΠΌΠ°ΡΡΠΈΠ² Π±Π°ΠΉΡ byte[] name = fileName.getBytes("utf-8"); // ΠΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌ Π΄Π»ΠΈΠ½Ρ ΡΡΠΎΠ³ΠΎ ΠΌΠ°ΡΡΠΈΠ²Π° out.write(name.length); // ΠΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌ Π±Π°ΠΉΡΡ ΠΈΠΌΠ΅Π½ΠΈ out.write(name); File file = new File(FOLDER + "/" + fileName); // ΠΠΎΠ»ΡΡΠ°Π΅ΠΌ ΡΠ°Π·ΠΌΠ΅Ρ ΡΠ°ΠΉΠ»Π° long fileSize = file.length(); // ΠΠΎΠ½Π²Π΅ΡΡΠΈΡΡΠ΅ΠΌ Π΅Π³ΠΎ Π² ΠΌΠ°ΡΡΠΈΠ² Π±Π°ΠΉΡ ByteBuffer buf = ByteBuffer.allocate(Long.BYTES); buf.putLong(fileSize); // Π ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌ out.write(buf.array()); try (FileInputStream in = new FileInputStream(file)) { // Π§ΠΈΡΠ°Π΅ΠΌ ΡΠ°ΠΉΠ» Π±Π»ΠΎΠΊΠ°ΠΌΠΈ ΠΏΠΎ ΠΊΠΈΠ»ΠΎΠ±Π°ΠΉΡΡ byte[] data = new byte[1024]; int read; while ((read = in.read(data)) != -1) { // Π ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌ Π² ΡΠΎΠΊΠ΅Ρ out.write(data); } } catch(IOException exc) { exc.printStackTrace(); } } } catch(IOException exc) { exc.printStackTrace(); } } } catch(IOException exc) { exc.printStackTrace(); } } } Client.java
package com.example; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.net.Socket; public class Client { private static int PORT = 2121; private static String HOST = "localhost"; private static String FOLDER = "./files"; public static void main(String[] args) { try (Socket s = new Socket(HOST, PORT); InputStream in = s.getInputStream()) { // Π§ΠΈΡΠ°Π΅ΠΌ ΡΠ°Π·ΠΌΠ΅Ρ ΠΈΠΌΠ΅Π½ΠΈ int nameSize; while((nameSize = in.read()) != -1) { // Π§ΠΈΡΠ°Π΅ΠΌ ΡΠ°ΠΌΠΎ ΠΈΠΌΡ byte[] name = new byte[nameSize + 1]; in.read(name, 0, nameSize); // ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²ΡΠ²Π°Π΅ΠΌ ΠΎΠ±ΡΠ°ΡΠ½ΠΎ Π² ΡΡΡΠΎΠΊΡ String fileName = new String(name, "utf-8").trim(); System.out.println(fileName); File file = new File(FOLDER + "/" + fileName); try (FileOutputStream out = new FileOutputStream(file)) { // Π§ΠΈΡΠ°Π΅ΠΌ ΡΠ°Π·ΠΌΠ΅Ρ ΡΠ°ΠΉΠ» byte[] fileSizeBuf = new byte[8]; in.read(fileSizeBuf, 0, 8); // ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²ΡΠ²Π°Π΅ΠΌ Π² long ByteBuffer buf = ByteBuffer.allocate(Long.BYTES); buf.put(fileSizeBuf); buf.flip(); long fileSize = buf.getLong(); // Π§ΠΈΡΠ°Π΅ΠΌ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅ ΡΠ°ΠΉΠ»Π° Π±Π»ΠΎΠΊΠ°ΠΌΠΈ ΠΏΠΎ ΠΊΠΈΠ»ΠΎΠ±Π°ΠΉΡΡ int read = 0; byte[] data = new byte[1024]; while (read < fileSize) { read += in.read(data); // Π ΠΏΠΈΡΠ΅ΠΌ Π² ΡΠ°ΠΉΠ» out.write(data); } } catch(IOException exc) { exc.printStackTrace(); } } } catch(IOException exc) { exc.printStackTrace(); return; } } } - Good afternoon, tell me what can replace this line.for (String fileName: sourceDir.list ()). When you start the client and server on the server side, Exception in thread "main" java.lang.NullPointerException appears at java.base / java.util.Objects.requireNonNull (Objects.java:221) at Server.main (Server.java:2 the lines are highlighted in yellow, and the idea proposes to replace it with Objects.requireNonNull (sourceDir.list ()) But the result is the same, tell me what can be replaced - Akalit
- It is necessary not to replace, but to figure out what this line does and why it gives an error. - Sergey Gornostaev
- As I understand in this line, we create a forech loop after we create a backup string variable to which the lines from the file arrive, while trying to split the file into an array of strings - Akalit
- An error may occur in this line if there is a problem with the file. Thanks, I will try to search =) - Akalit
There are several approaches to solving your problem:
Serialization. Use the built-in serialization ( Java Serialization API ), or one of the popular libraries . That is, you serialize the object, transfer and deserialize it on the receiving side.
Use your data exchange protocol. For example, after a connection is established, the client sends the file name, receives a confirmation from the server, then sends the contents of the file, and again receives confirmation of the receipt of the file.
Send the file name and its contents in one request, then you need to organize the format of the data transfer, as already described in this response