在 readline() 调用之后,Java 的 BufferedReader 是否在其内部缓冲区中留下字节?

发布于 2024-11-12 02:03:22 字数 1869 浏览 0 评论 0原文

我在我的服务器中遇到了一个问题,在我发送一个包含 X 字节的文件后,我发送一个字符串,表示该文件已结束,另一个文件即将到来,就像

FILE: a SIZE: Y\r\n
send Y bytes
FILE a FINISHED\r\n
FILE b SIZE: Z\r\n
send Z byes
FILE b FINISHED\r\n
FILES FINISHED\r\n

在我的客户端中它无法正确接收一样。 从套接字读取 Y 或 Z 字节后,我使用 readline() 获取命令行。 对于一个文件,它工作得很好,对于多个文件,它很少工作(是的,我不知道它是如何工作一次或两次)

以下是我用来传输二进制文件的一些代码

public static void readInputStreamToFile(InputStream is, FileOutputStream fout,
        long size, int bufferSize) throws Exception
{
    byte[] buffer = new byte[bufferSize];
    long curRead = 0;
    long totalRead = 0;
    long sizeToRead = size;
    while(totalRead < sizeToRead)
    {
        if(totalRead + buffer.length <= sizeToRead)
        {
            curRead = is.read(buffer);
        }
        else
        {
            curRead = is.read(buffer, 0, (int)(sizeToRead - totalRead));
        }
        totalRead = totalRead + curRead;
        fout.write(buffer, 0, (int) curRead);
    }
}





public static void writeFileInputStreamToOutputStream(FileInputStream in, OutputStream out, int bufferSize) throws Exception
{
    byte[] buffer = new byte[bufferSize];
    int count = 0;
    while((count = in.read(buffer)) != -1)
    {
        out.write(buffer, 0, count);
    }
}

,只是为了说明我可以解决将 readline 替换为此代码的问题:

    ByteArrayOutputStream ba = new ByteArrayOutputStream();
    int ch;
    while(true)
    {
        ch = is.read();
        if(ch == -1)
            throw new IOException("Conecção finalizada");
        if(ch == 13)
        {
            ch = is.read();
            if(ch == 10)
                return new String(ba.toByteArray(), "ISO-8859-1");
            else
                ba.write(13);
        }
        ba.write(ch);
    }

PS:“ is" 是我来自套接字的输入流:socket.getInputStream();

我仍然不知道这是否是最好的实现,我正在尝试弄清楚

I´m having a problem, in my server, after I send a file with X bytes, I send a string saying this file is over and another file is coming, like

FILE: a SIZE: Y\r\n
send Y bytes
FILE a FINISHED\r\n
FILE b SIZE: Z\r\n
send Z byes
FILE b FINISHED\r\n
FILES FINISHED\r\n

In my client it does not recive properly.
I use readline() to get the command lines after reading Y or Z bytes from the socket.
With one file it works fine, with multiple files it rarely works (yeah, I dont know how it worked once or twice)

Here are some code I use to transfer binary

public static void readInputStreamToFile(InputStream is, FileOutputStream fout,
        long size, int bufferSize) throws Exception
{
    byte[] buffer = new byte[bufferSize];
    long curRead = 0;
    long totalRead = 0;
    long sizeToRead = size;
    while(totalRead < sizeToRead)
    {
        if(totalRead + buffer.length <= sizeToRead)
        {
            curRead = is.read(buffer);
        }
        else
        {
            curRead = is.read(buffer, 0, (int)(sizeToRead - totalRead));
        }
        totalRead = totalRead + curRead;
        fout.write(buffer, 0, (int) curRead);
    }
}





public static void writeFileInputStreamToOutputStream(FileInputStream in, OutputStream out, int bufferSize) throws Exception
{
    byte[] buffer = new byte[bufferSize];
    int count = 0;
    while((count = in.read(buffer)) != -1)
    {
        out.write(buffer, 0, count);
    }
}

just for note I could solve replacing readline to this code:

    ByteArrayOutputStream ba = new ByteArrayOutputStream();
    int ch;
    while(true)
    {
        ch = is.read();
        if(ch == -1)
            throw new IOException("Conecção finalizada");
        if(ch == 13)
        {
            ch = is.read();
            if(ch == 10)
                return new String(ba.toByteArray(), "ISO-8859-1");
            else
                ba.write(13);
        }
        ba.write(ch);
    }

PS: "is" is my input stream from socket: socket.getInputStream();

still I dont know if its the best implementation to do, im tryinf to figure out

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

感悟人生的甜 2024-11-19 02:03:22

这里的代码中没有 readLine() 调用,而是回答您的问题;是的,调用 BufferedReader.readLine() 很可能会在其内部缓冲区中留下一些东西。它正在缓冲输入。

如果您将其中一个 InputStream 包装在 BufferedReader 中,那么如果您先从 BufferedReader 读取数据,然后再读取数据,则无法真正获得理智的行为从 InputStream 读取。

您可以从 InputStream 读取字节,并通过查找一对 \r\n字节。当您看到一行显示 "FILE: a SIZE: Y\r\n" 时,您将像往常一样继续,只是用于解析行的缓冲区可能包含文件的前几个字节,因此首先将这些字节写出。

或者,您使用 FTP 的思想,使用一个 TCP 流用于命令,使用一个 TCP 流用于实际传输,使用 BufferedReader.readLine() 从命令流中读取数据,并像之前一样读取数据使用InputStream。

There's no readLine() calls in the code here, but to answer your question; Yes, calling BufferedReader.readLine() might very well leave stuff around in its internal buffer. It's buffering the input.

If you wrap one of your InputStream in a BufferedReader, you can't really get much sane behavior if you read from the BufferedReader and then later on read from the InputStream.

You could read bytes from your InputStream and parse out a text line from that by looking for a pair of \r\n bytes. When you got a line saying "FILE: a SIZE: Y\r\n" , you go on as usual, except the buffer you used to parse lines might contain the first few bytes of your file, so write those bytes out first.

Or you use the idea of FTP and use one TCP stream for commands and one TCP stream for the actual transfer, reading from the command stream with a BufferedReader.readLine(), and reading the data as you already do with an InputStream.

稳稳的幸福 2024-11-19 02:03:22

是的,BufferedReader 的主要目的是缓冲数据。它以更大的块从其底层 Reader 读取输入,以避免多次小读取。

它有一个 readLine() 方法,这只是一个很好的好处,通过缓冲可以轻松实现。

如果您确实必须通过同一连接混合文本和二进制数据,您可能需要使用 DataInputStream(位于 BufferedInputStream 之上)及其 readLine() 方法 - 从同一 DataInputStream 读取数据。 (但要注意这里的编码。)

Yes, the main point of a BufferedReader is to buffer the data. It is reading input from its underlying Reader in bigger chunks to avoid having multiple small reads.

That it has a readLine() method is just a nice bonus which is made easily possible by the buffering.

You may want to use a DataInputStream (on top of a BufferedInputStream) and it's readLine() method, if you really have to mix text and binary data over the same connection - read the data from the same DataInputStream. (But take care about the encoding here.)

一江春梦 2024-11-19 02:03:22

在写入要确定已发送的数据后,在 OutputStream 上调用 flush()。所以本质上是在每个文件的末尾调用flush()

Call flush() on the OutputStream after you've written data that you want to be certain has been sent. So essentially at the end of each file call flush().

一个人的夜不怕黑 2024-11-19 02:03:22

我想您必须刷新输出流,以确保任何缓冲的字节都正确发送到流中。关闭流同样会运行该进程。

刷新的 Javadocs 说:

刷新此输出流并强制
任何缓冲的输出字节
写出来了。总承包合同
冲洗是调用它是一个
表明,如果有任何字节
之前写入的内容已被缓冲
通过执行输出
流,这样的字节应该立即
写成他们想要的
目的地。

I guess you must flush your output stream in order to make sure any buffered bytes are properly sent down the stream. Closing the stream will equally have this process run.

The Javadocs for flush say:

Flushes this output stream and forces
any buffered output bytes to be
written out. The general contract of
flush is that calling it is an
indication that, if any bytes
previously written have been buffered
by the implementation of the output
stream, such bytes should immediately
be written to their intended
destination.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文