5

我正在用 Sockets 用 Ja​​va 编写程序。我可以向客户端发送命令,也可以从客户端向服务器发送命令。要阅读命令,我使用BufferedReader. 要编写它们,aPrintWriter但是现在我想通过套接字传输文件(而不是简单地创建第二个连接)
首先,我将文件包含多少字节写入输出流。例如 40000 字节。所以我40000通过套接字写入数字,但连接的另一端读取78.

所以我在想:BufferedReader读取的不仅仅是行(通过调用readLine(),这样我会从文件数据中丢失一些字节。因为它们位于BufferedReader.
所以这个数字78是我要传输的文件的一个字节。

这种思维方式对还是不对。如果是这样,如何解决这个问题。
我希望我已经解释得很好。


这是我的代码,但我的默认语言是荷兰语。所以一些变量名听起来很奇怪。

public void flushStreamToStream(InputStream is, OutputStream os, boolean closeIn, boolean closeOut) throws IOException {
    byte[] buffer = new byte[BUFFERSIZE];
    int bytesRead;
    if ((!closeOut) && closeIn) { // To Socket from File
        action = "Upload";
        os.write(is.available()); // Here I write 400000
        max = is.available();
        System.out.println("Bytes to send: " + max);
        while ((bytesRead = is.read(buffer)) != -1) {
            startTiming(); // Two lines to compute the speed
            os.write(buffer, 0, bytesRead);
            stopTiming(); // Speed compution
            process += bytesRead;
        }
        os.flush();
        is.close();
        return;
    }
    if ((!closeIn) && closeOut) { // To File from Socket
        action = "Download";
        int bytesToRead = -1;
        bytesToRead = is.read(); // Here he reads 78.
        System.out.println("Bytes to read: " + bytesToRead);
        max = bytesToRead;
        int nextBufferSize;
        while ((nextBufferSize = Math.min(BUFFERSIZE, bytesToRead)) > 0) {
            startTiming();
            bytesRead = is.read(buffer, 0, nextBufferSize);
            bytesToRead -= bytesRead;
            process += nextBufferSize;
            os.write(buffer, 0, bytesRead);
            stopTiming();
        }
        os.flush();
        os.close();
        return;
    }
    throw new IllegalArgumentException("The only two boolean combinations are: closeOut == false && closeIn == true AND closeOut == true && closeIn == false");
}

这是解决方案:
感谢詹姆斯的建议
,我认为laginimaineb anwser 是解决方案的一部分。

阅读命令。

DataInputStream in = new DataInputStream(is); // Originally a BufferedReader
// Read the request line
String str;
while ((str = in.readLine()) != null) {
    if (str.trim().equals("")) {
       continue;
    }
    handleSocketInput(str);
}

现在flushStreamToStream:

public void flushStreamToStream(InputStream is, OutputStream os, boolean closeIn, boolean closeOut) throws IOException {
    byte[] buffer = new byte[BUFFERSIZE];
    int bytesRead;
    if ((!closeOut) && closeIn) { // To Socket from File
        action = "Upload";
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeInt(is.available());

        max = is.available();
        System.out.println("Bytes to send: " + max);
        while ((bytesRead = is.read(buffer)) != -1) {
            startTiming();
            dos.write(buffer, 0, bytesRead);
            stopTiming();
            process += bytesRead;
        }
        os.flush();
        is.close();
        return;
    }
    if ((!closeIn) && closeOut) { // To File from Socket
        action = "Download";
        DataInputStream dis = new DataInputStream(is);
        int bytesToRead = dis.readInt();
        System.out.println("Bytes to read: " + bytesToRead);
        max = bytesToRead;
        int nextBufferSize;
        while ((nextBufferSize = Math.min(BUFFERSIZE, bytesToRead)) > 0) {
            startTiming();
            bytesRead = is.read(buffer, 0, nextBufferSize);
            bytesToRead -= bytesRead;
            process += nextBufferSize;
            os.write(buffer, 0, bytesRead);
            stopTiming();
        }
        os.flush();
        os.close();
        return;
    }
    throw new IllegalArgumentException("The only two boolean combinations are: closeOut == false && closeIn == true AND closeOut == true && closeIn == false");
}

马汀。

4

4 回答 4

4

我不确定我是否听从了你的解释。

但是,是的 - 您无法真正控制 BufferedReader 实际读取的内容。这种读取器的要点是它根据需要乐观地读取底层资源的块以补充其缓冲区。所以当你第一次调用时readLine,它会发现它的内部缓冲区没有足够的空间来满足你的请求,并且会离开并从底层源读取它感觉的多少字节到它的缓冲区中,这通常比你刚才问了。填充缓冲区后,它会从缓冲的内容中返回您的行。

因此,一旦将输入流包装在 BufferedReader 中,就应该确保只通过同一个缓冲读取器读取该流。如果你不这样做,你最终会丢失数据(因为一些字节将被消耗并且现在位于 BufferedReader 的缓存中等待服务)。

于 2009-12-02T17:12:30.460 回答
1

DataInputStream 很可能是您想要使用的。另外,不要使用 available() 方法,因为它通常是无用的。

于 2009-12-02T19:29:35.120 回答
0

这里只是一个疯狂的刺 - 40000 是二进制的 1001110001000000 。现在,这里的前七位是 1001110,即 78。意思是,您正在写入 2 个字节的信息,但读取的是 7 位。

于 2009-12-02T17:12:46.030 回答
0

BufferedReader 假定它是从底层输入流中读取的唯一一个。

其目的是最小化来自底层流的读取次数(这很昂贵,因为它们可以非常深入地委托)。为此,它保留了一个缓冲区,它通过在对底层流的一次调用中读取尽可能多的字节来填充该缓冲区。

所以是的,你的诊断是准确的。

于 2009-12-02T17:15:30.483 回答