java - 如何从包含文本 header 的套接字输入流中读取二进制文件? :

标签 java http-headers inputstream binary-data

好的,所以我有一个套接字InputStream,服务器通过它发送一个数据流,其中包含多行标题文本,后跟二进制字节流,构成它正在发送的 pdf 文件(在标题部分指定的长度)。我无法控制的服务器在发送数据后不会关闭数据流,因此我必须从流中读取确切的字节数,然后自己从客户端关闭它。

所以,我的问题是,您如何或是否有任何实用程序可以让我轻松读取 header (作为文本),然后从同一输入流中读取准确数量的字节?

我尝试了各种 Reader 类,它们对 header 非常有用,但据我所知,对数据的二进制内容(Readers使用字符而不是字节)。 apache commons IOUtils 等实用程序对我不起作用,因为流保持打开/未终止状态并且尝试 IOUtils.toBytes(inputStream) 无限期挂起。

解决方案似乎是使用 Stream 类而不是 Reader 类,但它的级别似乎太低,必须有实用程序来帮助我解决这个问题.使用 DataInputStream 读取二进制数据似乎很容易,但我对如何读取 header 感到困惑。有什么建议吗?

编辑:这是一条示例消息:

http/1.0 200 OK
content-type: application/doc_request
content-length: 18813
session-id: slukdcy71292645678312
remote-addr: slukdcy7

<pdf binary data...>

header 和二进制数据之间的新行确定 header 的结尾和二进制数据的开始。

最佳答案

您可以将二进制字节转换为文本。我建议您以二进制形式读取所有数据,并将 header 从二进制文件转换为文本。

编辑:这是一个示例解决方案。它假定所有 header 都如您所建议的那样,并且文件足够小以适合内存。您可能想要缓冲您的输入流。

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);
    }
}

关于java - 如何从包含文本 header 的套接字输入流中读取二进制文件? :,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4898527/

相关文章:

java - Java 应用程序在 Eclipse 上运行良好,但在部署为可运行的 jar 后无法正常运行

java - BufferedReader 不读取整个文本文件

java test - 打包一个java应用程序以在另一个linux机器上运行

http-headers - HTTP 响应中 header 的顺序重要吗?

php - 如何加载一个 URL 并只取回它的最后 20k

java - 从 OutputStream 创建 InputStream 的最有效方法

java - 如果建议没有方法,Intellij 可以显示警告吗?

java - 在 Spring EL 中使用数组的内容

php - 解析 WWW URL 前缀的不同方法

java - 为什么恢复下载会下载 Java 应用程序中损坏的文件?