If your in
是一个 BufferedReader 那么你就会遇到缓冲超过需要的常见问题。 BufferedReader 的默认缓冲区大小是 8192 个字符,这大约是您期望的和实际得到的之间的差异。因此,您丢失的数据位于 BufferedReader 的内部缓冲区内,转换为字符(我想知道为什么它没有因某种转换错误而中断)。
The only workaround is to read the first lines byte-by-byte without using any buffered classes readers. Java doesn't provide an unbuffered InputStreamReader with readLine() capability as far as I know (with the exception of the deprecated DataInputStream.readLine(), as indicated in the comments below), so you have to do it yourself. I would do it by reading single bytes, putting them into a ByteArrayOutputStream until I encounter an EOL, then converting the resulting byte array into a String using the String constructor with the appropriate encoding.
请注意,虽然您无法使用 BufferedInputReader,但没有什么可以阻止您从一开始就使用 BufferedInputStream,这将使逐字节读取更加高效。
Update
事实上,我现在正在做类似的事情,只是稍微复杂一点。它是一种应用程序协议,涉及交换一些用 XML 很好地表示的数据结构,但它们有时附加有二进制数据。我们通过在根 XML 中添加两个属性来实现这一点:fragmentLength 和 isLastFragment。第一个指示 XML 部分后面有多少字节的二进制数据,isLastFragment 是一个布尔属性,指示最后一个片段,因此读取方知道不会再有二进制数据。 XML 以 null 结尾,因此我们不必处理 readLine()。读取代码如下所示:
InputStream ins = new BufferedInputStream(socket.getInputStream());
while (!finished) {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int b;
while ((b = ins.read()) > 0) {
buf.write(b);
}
if (b == -1)
throw new EOFException("EOF while reading from socket");
// b == 0
Document xml = readXML(new ByteArrayInputStream(buf.toByteArray()));
processAnswers(xml);
Element root = xml.getDocumentElement();
if (root.hasAttribute("fragmentLength")) {
int length = DatatypeConverter.parseInt(
root.getAttribute("fragmentLength"));
boolean last = DatatypeConverter.parseBoolean(
root.getAttribute("isLastFragment"));
int read = 0;
while (read < length) {
// split incoming fragment into 4Kb blocks so we don't run
// out of memory if the client sent a really large fragment
int l = Math.min(length - read, 4096);
byte[] fragment = new byte[l];
int pos = 0;
while (pos < l) {
int c = ins.read(fragment, pos, l - pos);
if (c == -1)
throw new EOFException(
"Preliminary EOF while reading fragment");
pos += c;
read += c;
}
// process fragment
}
事实证明,使用以 null 结尾的 XML 确实是一件很棒的事情,因为我们可以在不更改传输协议的情况下添加其他属性和元素。在传输级别,我们也不必担心处理 UTF-8,因为 XML 解析器会为我们做这件事。在您的情况下,您可能对这两行感到满意,但如果您稍后需要添加更多元数据,您可能也希望考虑以 null 结尾的 XML。