【问题标题】:How to send a list of files over a socket in Java [duplicate]如何通过Java中的套接字发送文件列表[重复]
【发布时间】:2012-07-10 08:08:03
【问题描述】:

我已使用代码here 通过套接字发送单个文件。但是,我需要能够通过套接字发送多个文件(基本上是目录中的所有文件)并让客户端识别文件之间的分隔方式。坦率地说,我完全不知道该怎么做。任何提示都会有所帮助。

注意 1: 我需要一种方法来在一个连续的流中发送文件,客户端可以将其分离为单独的文件。它不能依赖于来自客户端的单个请求。

注意 2:要回答一个我很确定我会参加 cmets 的问题,不,这是不是家庭作业。

EDIT 有人建议我可以在文件本身之前发送文件的大小。我该怎么做,因为通过套接字发送文件总是以预定的字节数组或单个字节完成,而不是File.length()返回的long

【问题讨论】:

    标签: java sockets


    【解决方案1】:

    这是一个完整的实现:

    发送方:

    String directory = ...;
    String hostDomain = ...;
    int port = ...;
    
    File[] files = new File(directory).listFiles();
    
    Socket socket = new Socket(InetAddress.getByName(hostDomain), port);
    
    BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
    DataOutputStream dos = new DataOutputStream(bos);
    
    dos.writeInt(files.length);
    
    for(File file : files)
    {
        long length = file.length();
        dos.writeLong(length);
    
        String name = file.getName();
        dos.writeUTF(name);
    
        FileInputStream fis = new FileInputStream(file);
        BufferedInputStream bis = new BufferedInputStream(fis);
    
        int theByte = 0;
        while((theByte = bis.read()) != -1) bos.write(theByte);
    
        bis.close();
    }
    
    dos.close();
    

    接收方:

    String dirPath = ...;
    
    ServerSocket serverSocket = ...;
    Socket socket = serverSocket.accept();
    
    BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
    DataInputStream dis = new DataInputStream(bis);
    
    int filesCount = dis.readInt();
    File[] files = new File[filesCount];
    
    for(int i = 0; i < filesCount; i++)
    {
        long fileLength = dis.readLong();
        String fileName = dis.readUTF();
    
        files[i] = new File(dirPath + "/" + fileName);
    
        FileOutputStream fos = new FileOutputStream(files[i]);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
    
        for(int j = 0; j < fileLength; j++) bos.write(bis.read());
    
        bos.close();
    }
    
    dis.close();
    

    我没有测试它,但我希望它会工作!

    【讨论】:

    • 不确定是我不清楚还是什么,但客户端和服务器似乎与我的意图相反。无论如何,这是一个非常简单的修复。谢谢!
    • @ewok 哎呀,看到标题就写代码了。但是,没有什么大的区别,我很高兴能帮上忙 :)
    • 完美解决方案。非常感谢
    • readUTF() 如何知道文件名何时完成?你能接收到另一种语言的流吗?你需要做什么来识别文件名的结尾和数据的开头?
    【解决方案2】:

    您可以在每个文件之前先发送文件的大小,这样客户端就会知道当前文件何时结束并期待下一个(大小)。这将允许您对所有文件使用一个连续的流。

    【讨论】:

    • 你能给我一个简单的例子吗?我对套接字编程很陌生,我不确定如何发送文件的大小,因为您必须发送预定的字节数组或单个字节,而不是File.length() 将发送的长返回
    • 您可以将File.length() 转换为适当大小的字节数组并使用它(Long.SIZE 告诉您位数,通过一些数学运算您可以得到字节数)- 查看this SO thread 关于如何进行 long->byte 数组转换
    • @Attila 或直接使用 DataInputStreamDataOutputStream :)
    【解决方案3】:

    一个非常简单的方法是在发送每个文件之前发送文件长度,以便您可以确定文件之间的分隔。

    当然,如果接收进程是Java,你可以只发送Objects。

    【讨论】:

      【解决方案4】:

      您可以在客户端压缩文件并将此压缩流发送到服务器。

      例如:http://www.exampledepot.com/egs/java.util.zip/CreateZip.html

      与...

      OutputStream output = connection.getOutputStream();
      ZipOutputStream out = new ZipOutputStream(output);
      

      【讨论】:

      • 谢谢,但压缩并不是特别有用。我需要一个能够在下一个文件仍在流式传输时处理一个文件的流
      【解决方案5】:

      也许最快的方法是自动将目录中的文件压缩和解压缩到一个文件中,请参见 java.util.zip 包

      【讨论】:

        猜你喜欢
        • 2015-10-01
        • 2012-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多