An octet means a byte, which means that you first have to convert the header text to bytes in UTF-8 encoding, and count the bytes.
You can do that by calling getBytes(Charset charset)
, specifying the UTF_8
charset.
Of course, the problem is that the length of the entire header depends on the number of digits needed to specify the length. The following code will assume that the header length will be a 2-digit number, and retry if that is not the case.
It means that if keyword and value is test
and X
, the result will be 10 test=X\n
, even though 9 test=X\n
would seem more appropriate.
If keyword and value is A
and B
, the result will be 6 A=B\n
, as it should be, and the length will grow to 3, 4, 5, ... digits as needed.
private static byte[] buildExtendedHeader(String keyword, String value) {
byte[] bytes = (' ' + keyword + '=' + value + '\n').getBytes(StandardCharsets.UTF_8);
int len = bytes.length + 2; // let's assume 2-digit length
for (;;) {
byte[] lenBytes = Integer.toString(len).getBytes(StandardCharsets.US_ASCII);
int realLen = lenBytes.length + bytes.length;
if (len == realLen) {
byte[] header = new byte[len];
System.arraycopy(lenBytes, 0, header, 0, lenBytes.length);
System.arraycopy(bytes, 0, header, lenBytes.length, bytes.length);
return header;
}
len = realLen;
}
}
TEST
byte[] header = buildExtendedHeader("LIKE A STAMPEDE", "À LA DÉBANDADE");
System.out.printf("%s%n%d octets:", new String(header, StandardCharsets.UTF_8).replace("\n", "\\n"), header.length);
for (byte b : header)
System.out.printf(" %02x", b);
OUTPUT
36 LIKE A STAMPEDE=À LA DÉBANDADE\n
36 octets: 33 36 20 4c 49 4b 45 20 41 20 53 54 41 4d 50 45 44 45 3d c3 80 20 4c 41 20 44 c3 89 42 41 4e 44 41 44 45 0a