【问题标题】:about closing BufferedOutputStream关于关闭 BufferedOutputStream
【发布时间】:2015-06-20 07:00:04
【问题描述】:

我正在尝试使用 TCP 开发一个简单的 Java 文件传输应用程序。 我目前的服务器代码如下:

package tcp.ftp;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class FTPServer {

    public static void main(String[] args) {
        new FTPServer().go();
    }

    void go() {
        try {
            ServerSocket server = new ServerSocket(2015);
            System.out.println("server is running ....!");
            while (true) {
                Socket socket = server.accept();
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String file = reader.readLine();
                System.out.println("file to be downloaded is : " + file);
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
                while (true) {
                    int octet = bis.read();
                    if (octet == -1) {
                        break;
                    }
                    bos.write(octet);
                }
                 bos.flush();
                //bos.close();

            }
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }

}

使用上面我当前的服务器代码,下载无法按预期工作。上面的代码将文件的一部分发送到客户端,而不是整个文件。请注意,我使用了 flush 方法来刷新缓冲区。但是当我用 close() 方法替换 flush() 方法时,文件完全发送到客户端而没有任何丢失。谁能解释一下这种行为!

更新:这是我客户的代码:

package tcp.ftp;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 *
 * @author aaa
 */
public class FTPClient {

    public static void main(String[] args) {
        String file = "JasperReports-Ultimate-Guide-3.pdf";
        try {
            InetAddress address = InetAddress.getLocalHost();
            Socket socket = new Socket(address, 2015);
            System.out.println("connection successfully established ....!");
            PrintWriter pw = new PrintWriter(socket.getOutputStream());
            pw.println(file);
            pw.flush();
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy" + file));
            while (true) {
                int octet = bis.read();
                if (octet == -1) {
                    break;
                }
                bos.write(octet);
            }
            bos.flush();
            System.out.println("file download is complete ...!");

        } catch (UnknownHostException ex) {
            System.out.println(ex.getMessage());
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }
}

不使用 Socket 的另一种行为。使用以下代码将文件从源复制到目标:

    public class CopieFile {
     static void fastCopy(String source, String destination) {

    try {
        FileInputStream fis = new FileInputStream(source);
        BufferedInputStream bis = new BufferedInputStream(fis);
        FileOutputStream fos = new FileOutputStream(destination);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        while (true) {
            int octet = bis.read();
            if (octet == -1) {
                break;
            }
            bos.write(octet);
        }
        bos.flush();
    } catch (FileNotFoundException ex) {
        System.out.println(ex.getMessage());
    } catch (IOException ex) {
        System.out.println(ex.getMessage());
    }
}
public static void main(String[] args) throws IOException {
        String source = "...";
        String destination = "...";
        fastCopy(source, destination);
}// end main
}// end class

上面的代码将文件从一个位置复制到另一个位置而不会造成任何损失。请注意,我没有关闭流。

【问题讨论】:

  • 必须有未发送的字节并关闭全部发送(在缓冲区中)。尝试将flush放在write之后,这样每次写操作后都会flush。
  • 为什么有两个 while (true) 循环?
  • 你是如何阅读客户端上的内容的?只是一个猜测,但可能是所有数据都以任何一种方式发送,但是通过不关闭服务器上的流,客户端上的循环不会正常退出,导致它看起来好像没有收到所有数据。

标签: java sockets socket.io serversocket


【解决方案1】:

如果您从不关闭流,客户端将永远不会结束流,因此它永远不会退出读取循环。

在任何情况下,流和套接字都将超出范围,所以如果你不关闭它们,就会发生资源泄漏。

【讨论】:

  • Object.finalize 应该可以防止资源泄漏......但当然最好关闭流。
  • @Siguza 没有“应该”。它只会在运行时防止泄漏,这是不能保证的。不能依赖它。
  • @EJP 关闭流将关闭套接字,因此,关闭套接字是不必要的。是真的吗?
  • @EJP:您说:“如果您从不关闭流,客户端将永远不会结束流,因此它永远不会退出读取循环”。但为什么 ? flush() 怎么样。
  • @Kachna 1. 您的客户端在流结束时退出读取循环。流结束仅在对等方关闭连接时发生在套接字上。 2. 关闭流关闭套接字当然关闭套接字是多余的。我不知道你为什么要问。
猜你喜欢
  • 2010-11-28
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 2011-10-04
  • 2021-04-20
  • 2013-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多