在 readline() 调用之后,Java 的 BufferedReader 是否在其内部缓冲区中留下字节?
我在我的服务器中遇到了一个问题,在我发送一个包含 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这里的代码中没有
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, callingBufferedReader.readLine()
might very well leave stuff around in its internal buffer. It's buffering the input.If you wrap one of your
InputStream
in aBufferedReader,
you can't really get much sane behavior if you read from theBufferedReader
and then later on read from theInputStream.
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 anInputStream.
是的,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.)在写入要确定已发送的数据后,在 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 callflush()
.我想您必须刷新输出流,以确保任何缓冲的字节都正确发送到流中。关闭流同样会运行该进程。
刷新的 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: