简体   繁体   中英

How can I read a binary file from a socket input stream which includes textual headers?:

OK, so I have a socket InputStream over which the server is sending a data stream containing a number of lines of header text followed by a binary stream of bytes making up the pdf file it is sending (of a length specified in the header section). The server, which I can't control, does not close the data stream after it sends its data so i must read the exact amount of bytes from the stream and then close it myself from the client end.

So, my question is, how do you or are there any utilities which will allow me to easily read the headers (as text) and then read an exact amount of bytes from the same input sream?

I've tried various Reader classes which work great for the headers, but as I've learned not so great for the binary content of the data ( Reader s work with characters not bytes). Utilities such as apache commons IOUtils don't work for me because the stream remains open/unterminated and attempts at IOUtils.toBytes(inputStream) hang indefinitely.

The solution seems to be to work with Stream classes rather than Reader classes, but it seems so low level that there must be utilities out there to help me with this. Reading the binary data using a DataInputStream seems easy enough, but I'm stumped as to how to read the headers. Any advice?

EDIT: Here is a sample message:

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

<pdf binary data...>

The new line between the headers and binary data determine the end of the headers and the start of the binary data.

You can convert binary bytes to text. I suggest you read all the data as binary and convert the header to text from the binary for the header.

EDIT: here is a sample solution. It assumes that all headers are as you suggested and the files are small enough to fit into memory. You may want to buffer your input stream.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM