【问题标题】:InputStream.read() returning -1 after PrintWriterInputStream.read() 在 PrintWriter 之后返回 -1
【发布时间】:2017-06-09 16:31:54
【问题描述】:

下面的服务器和客户端代码尝试通过其名称发送文件:

  • 客户端使用在 println 被调用后刷新的 PrintWriter 发送 文件名。之后,客户端使用 while 循环的通用方法发送文件内容,该循环读取文件直到 InputStream.read 返回 -1。
  • 服务器使用 BufferedReader (readLine) 读取文件名。之后,服务器使用相同的 while 循环读取文件内容。

问题是:当服务器和客户端程序在同一台机器(我的 Windows 笔记本电脑)上本地执行时,一切都会成功执行。 然而,当程序在同一网络的不同机器上执行时,服务器端InputStream.read()返回-1。

我不是在代码中寻找答案。(我已经用 DataInputStream 重写了)我想知道为什么会出现这种情况。

服务器:

try {
        ServerSocket server = new ServerSocket(3000);
        Socket client = server.accept();
        InputStream in = client.getInputStream();
        BufferedReader printIn = new BufferedReader(new InputStreamReader(in));
        String name = printIn.readLine();
        byte[] bytes = new byte[1024*16];
        File file = new File(name);
        FileOutputStream fOut = new FileOutputStream(file);
        int count;
        while ((count = in.read(bytes, 0, bytes.length)) != -1) {
            fOut.write(bytes, 0, count);
        }
        fOut.close();
        server.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

客户:

try {
        Socket client = new Socket("localhost",3000);
        OutputStream out = client.getOutputStream();
        PrintWriter printOut = new PrintWriter(out,true);
        printOut.println("old.jar");
        byte[] bytes = new byte[1024*16];
        File file = new File("old.jar");
        FileInputStream fIn = new FileInputStream(file);
        int count;
        while((count = fIn.read(bytes,0, bytes.length)) != -1) {
            out.write(bytes, 0, count);
        }
        fIn.close();
        client.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

【问题讨论】:

  • 您不能在同一个套接字上混合缓冲流或读取器。 BufferedReader 将提前读取并消耗以下文件数据的一部分。您需要一种不同的方法来发送文件名,该方法使用与您正在读取以下文件数据的相同输入流。 readUTF()/writeUTF() 浮现在脑海中。
  • 谢谢你,@EJP。我不知道用于套接字的底层协议。
  • @EJP 这仍然不能解释为什么文件是在本地连接上发送的。想法?
  • 它与“用于套接字的底层协议”没有任何关系。当其中一个被缓冲时,它与混合不同类型的流有关。就像我说的。因为我说的原因。在本地连接上,您必须获得不同的打包行为,因此文件数据的开头不会与名称一起到达。
  • @EJP 好的,我明白了。为了可以回答这个问题,我将您的 cmets 变成了官方答案并给了您信用。谢谢。

标签: java file sockets printwriter


【解决方案1】:

来自 cmets:“您不能在同一个套接字上混合缓冲流或读取器。BufferedReader 将提前读取并消耗以下文件数据的一部分。”

因此,当 InputStream.read()BufferedReader.readLine() 之后调用时,BufferedReader 会消耗文件数据,因此 InputStream.read( ) 返回 -1。

关于代码在本地连接上成功执行的原因:本地连接的打包行为可能与远程连接不同

(归功于@EJP)

【讨论】:

    猜你喜欢
    • 2015-01-25
    • 1970-01-01
    • 2014-08-07
    • 2016-02-18
    • 2018-08-03
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 2019-03-10
    相关资源
    最近更新 更多