好的,所以我有一个套接字InputStream
,服务器在其上发送一个数据流,其中包含多行标题文本,后跟一个二进制字节流,构成它发送的pdf文件(标题部分中指定的长度)。我无法控制的服务器在发送数据后不会关闭数据流,因此我必须从流中读取确切的字节数,然后自己从客户端关闭它。
所以,我的问题是,你或者是否有任何实用程序可以让我轻松读取标题(作为文本)然后从同一输入sream中读取确切的字节数?
我已经尝试了各种Reader
类,这些类对于标题非常有用,但是我已经学会了对数据的二进制内容不太了解(Reader
使用字符而不是字节) 。诸如apache commons IOUtils
之类的实用程序对我不起作用,因为流保持打开/未终止并且IOUtils.toBytes(inputStream)
尝试无限期挂起。
解决方案似乎是与Stream
类而不是Reader
类一起使用,但它似乎是如此之低,以至于必须有实用程序来帮助我。使用DataInputStream
读取二进制数据似乎很容易,但我对如何读取标题感到难过。有什么建议吗?
编辑:以下是一条示例消息:
http/1.0 200 OK
content-type: application/doc_request
content-length: 18813
session-id: slukdcy71292645678312
remote-addr: slukdcy7
<pdf binary data...>
标题和二进制数据之间的新行确定标题的结尾和二进制数据的开头。
答案 0 :(得分:4)
您可以将二进制字节转换为文本。我建议您将所有数据读取为二进制文件,并将标题转换为标题的二进制文本。
编辑:这是一个示例解决方案。它假定所有标题都符合您的建议,并且文件足够小以适应内存。您可能希望缓冲输入流。
public class HttpFile {
public final String status;
public final Map<String, String> properties;
public final byte[] data;
public HttpFile(String status, Map<String, String> properties, byte[] data) {
this.status = status;
this.properties = properties;
this.data = data;
}
public static HttpFile readFrom(DataInputStream dis, Charset charset) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int ch;
while((ch = dis.read()) != -1) {
baos.write(ch);
if (ch == '\n') {
ch = dis.read();
// the second newline??
if (ch == '\n')
break;
baos.write(ch);
}
}
String header = new String(baos.toByteArray(), charset);
String[] lines = header.split("\\n");
String status = lines[0];
Map<String, String> properties = new LinkedHashMap<String, String>();
for(int i=1;i<lines.length;i++) {
String[] keyValue = lines[i].split(": ",2);
properties.put(keyValue[0], keyValue[1]);
}
byte[] data = null;
String content_length = properties.get("context-length");
if (content_length != null) {
int length = Integer.parseInt(content_length);
dis.readFully(data = new byte[length]);
}
return new HttpFile(status, properties, data);
}
}