RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 717301
Accepted
Svyatoslav Nenashev
Svyatoslav Nenashev
Asked:2020-09-12 14:49:07 +0000 UTC2020-09-12 14:49:07 +0000 UTC 2020-09-12 14:49:07 +0000 UTC

如何在套接字上发送文件名?

  • 772

该应用程序将传输许多文件,对我来说,使用名称传输它们很重要。为此,您每次都需要使用文件名发送一条消息,或者是否有可能以不同的方式进行?

java
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Sergey Gornostaev
    2020-09-12T15:06:29Z2020-09-12T15:06:29Z

    您发送的第一个字节是文件名的长度,接下来的 4 个字节是文件的长度,然后是文件名的字节,然后是文件本身的字节。或者,为了不打扰数据转换,您可以稍微扩展字段:

    服务器.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();
            }
        }
    }
    

    客户端.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;
            }
        }
    }
    
    • 8
  2. DaysLikeThis
    2020-09-12T16:33:09Z2020-09-12T16:33:09Z

    有几种方法可以解决您的问题:

    1. 序列化。使用内置的序列化(Java Serialization API),或流行的库之一。也就是说,你序列化一个对象,在接收端传递和反序列化它。

    2. 使用您自己的通信协议。例如,在建立连接后,客户端发送一个文件名,接收来自服务器的确认,然后发送文件的内容,并再次收到文件已被接收的确认。

    3. 在一个请求中发送文件名及其内容,然后您需要组织数据传输格式,如本答案中所述

    • 4

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5