怎样实现让接收端通过已知文件长度来接收文件。发送端和接收端具体的实现方法?原来我在文件传输过程中没有涉及文件长度,发送端发送完后,关了输出流,就自动关闭了Socket,无法继续发送其它文件。通过搜索相关问题答案,我考虑通过文件长度来传文件。下面是我的部份代码:
----------------------------------------------------
发送方:
Socket socket_send;//已连接了对方
OutputStream ops = socket.getOutputStream();
DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream("待发送文件")));
DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(ops));
byte[] buf = new byte[1024];
while((dis.read(buf))!=-1)
{
     dos.write(buf,0,buf.length);
}
dos.flush();
dos.close();//如果没有这句,接收方while((dis.read(buf))!=-1)将一直等待,就连文件数据传完了也不会退出while语句.但加了这句,就可以正确地发送该文件了,只不过发完后,socket也断开了,不能再重复发文件了......
---------------------------------------------------
接收方:
Socket socket_accept;//已连接了对方
InputStream ips=socket_accept.getInputStream();
BufferedInputStream br=new BufferedInputStream(ips);
DataInputStream dis= new DataInputStream(br);
DataOutputStream dos= new DataOutputStream(new BufferedOutputStream(new FileOutputStream("保存目录")));
byte[] buf = new byte[1024];
while((dis.read(buf))!=-1)//如果发送方没关闭输出流,则不会退出循环
{
     dos.write(buf,0,buf.length);
}
dos.flush();
dos.close();

解决方案 »

  1.   

    发送方可以在发送之前先发送一个文件长度的消息给接受端,然后再发送文件啊。
    你看http协议下载的时候是先获得要传输文件的长度信息的。
      

  2.   

    如果只是需要发送多个文件,可以在所有文件发送完成后关闭连接即可:----------------------------------------------------
    发送方:
    Socket socket_send;//已连接了对方
    OutputStream ops = socket_send.getOutputStream();
    String[] files = ...;
    for (int i=0; i<files.length; i++)
        sendFile(ops, files[i]);
    ops.close();void sendFile(OutputStream ops, String file) throws IOException {
        DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(ops));
        byte[] buf = new byte[1024];
        while((dis.read(buf))!=-1)
        {
            dos.write(buf,0,buf.length);
        }
        dos.flush();
    }然则你要解决的问题似乎并非只是“发送多个文件”? ...
      

  3.   

    其实我要实现的是双方既能发文件又能收文件。还应该能让接收者选择接收或是不接收,及接收后文件的保存目录。现在我大部份问题已解决,就是如果接收了话,发送端只能关闭输出流,要不然就连一个文件也发送失败。而发送端传完文件后,立即关闭输出流的话,socket也随之断开了。
      

  4.   

    jshi123:
    files.length是批量发送的文件数目吧,不是单个文件的文件长度吧?
      

  5.   

    按你的要求看,最简单的方法是每次发送一个文件,每次发送时重新建立连接-〉传送数据-〉关闭。
    files是String数组,用来存放一组文件名,files.length指文件的数量
      

  6.   

    我现在把我要解决的问题简述一下吧:
    在双方已建立socket连接,并且接收方已经知道要接收多大文件的前提下,怎样具体实现接收端接收文件。
      

  7.   

    先尝试解答你的问题:----------------------------------------------------
    发送方:
    Socket socket_send;//已连接了对方
    OutputStream ops = socket.getOutputStream();
    DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream("待发送文件")));
    DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(ops));
    dos.writeLong(new File("待发送文件").length()); // 先发送文件长度
    byte[] buf = new byte[1024];
    while((dis.read(buf))!=-1)
    {
         dos.write(buf,0,buf.length);
    }
    dos.flush();
    //dos.close(); 你应当是不希望在输出流中写EOF的
    ---------------------------------------------------
    接收方:
    Socket socket_accept;//已连接了对方
    InputStream ips=socket_accept.getInputStream();
    BufferedInputStream br=new BufferedInputStream(ips);
    DataInputStream dis= new DataInputStream(br);
    DataOutputStream dos= new DataOutputStream(new BufferedOutputStream(new FileOutputStream("保存目录")));
    long fileLength = dis.readLong(); // 先读取文件长度
    long totalBytes = 0; // 已读取的字节数
    int bytes; // 每次循环读到的字节数
    byte[] buf = new byte[1024];
    while((bytes = dis.read(buf))!=-1 && totalBytes < fileLength)//如果发送方没关闭输出流,并且未读取足够数据,则不会退出循环
    {
         dos.write(buf,0,buf.length);
     totalBytes += bytes;
    }
    // 即时发送方未关闭输出,只要读取指定的字节数后,便能退出循环
    dos.flush();
    dos.close();上面的方法是通过先发送文件长度,接收方接收到指定的长度数据后,在发送方不关闭连接的情况下,退出循环。
    不知道你所说的“通过已知文件长度来接收文件”是否指的这个。
      

  8.   

    int bytes; // 每次循环读到的字节数
    bytes应该初始化吧。照你的意思,是不是初始化为1024呢?可我将bytes值设为1024,总会出现接收方没有完全接收数据的错误。现在还在测试中,不知是否我的程序错误。
      

  9.   

    不必初始化,因为每次循环都会对其赋值:
    while((bytes = dis.read(buf))!=-1 && totalBytes < fileLength)
    即便有初值,执行到上述这条语句也被重新赋值了,所以接收方不能完全接收数据应该与初值无关。
    接收方退出循环有两个条件:输入流关闭、和接收到足够数据,所以请注意发送方不要过早关闭输出或连接,希望有所帮助。
      

  10.   

    收文件时,还是停在while中。
    为了测试,我加了显示读的字节数
    {
     dos.write(buf,0,buf.length);
     totalBytes += bytes;
     System.out.println(bytes);
    }
    结果是,接收时,程序停在while中了,命令行显示的是一列1024,没有在最后显示小于1024的数。这是什么原因呢?
      

  11.   

    问题已经解决了,我按照你说的方法,并在发送端与接收端之间添加了两对同步标识(传输开始与传输结束)。就解决了这个问题。
      谢谢jshi123了。
      

  12.   

    我提问的目的就是想知道按长度收文件,即jshi123提供的这段代码:
    while((bytes = dis.read(buf))!=-1 && totalBytes < fileLength)
    {
         dos.write(buf,0,buf.length);
         totalBytes += bytes;
    }
    可能是我问题说得不清楚的原因,让你们一时不知道我问什么。我说的这一要求“双方既能发文件又能收文件,还应该能让接收者选择接收或是不接收,选择接收后文件的保存目录”,原来就已经通过自定义传输协议的方式实现了。就是重复发送文件这块困扰了我好几天。今天总算在各位的帮助下解决了,心情放松多了。我做的这个是我现在学士学位毕业设计题目---加密算法与数字签名技术的研究与实现。加密与签名部份实现之后,为了方便传输加密文件及密钥,我加了文件传输与聊天模块。文件传输与聊天放一起,同时用两个端口实现。再次感谢你们的帮忙。特别是jshi123
      

  13.   

    你好,yz790724(想想)。
    我提的问题是:怎样让socket接收端通过已知文件长度来接收文件 
    我解决问题了之后,就急着结帖,结帖时,没见你的发言。虽然没机会给你加点分数,可还是要感谢你顶帖祝贺的。