L. *_*anc 3 java encoding parsing bytearray snappy
我有一个字节流,返回一个字节数组序列,每个字节数组代表一个记录.
我想将流解析为单个byte []的列表.目前,我已经入侵了一个三字节分隔符,以便我可以识别每条记录的结尾,但是有疑虑.
我看到有一个标准的Ascii记录分隔符.
30 036 1E 00011110 RS  Record Separator
Run Code Online (Sandbox Code Playgroud)
如果字节数组(UTF-8编码)已被压缩和/或加密,使用从该字符派生的byte []是否安全?我担心的是加密/压缩输出可能会出于某种其他目的而产生记录分隔符.请注意,单个byte []记录是压缩/加密的,而不是整个流.
我正在使用Java 8并使用Snappy进行压缩.我还没有选择加密库,但它肯定是更强大,标准的私钥方法之一.
如果您正在使用随机非结构化数据(压缩/加密数据非常接近),则不能简单地将字节声明为分隔符,因为分隔符始终在此类数据中显示为常规数据字节.
如果在开始写入时已知数据大小,则通常先写入大小,然后再写入数据.当你回读时,你知道你需要先读取大小(比如int的4个字节),然后是大小指示的字节数.
如果你在写作时无法分辨大小,这显然是行不通的.在这种情况下,您可以使用转义机制,例如选择一个很少出现的字节作为转义字符,转义数据中该字节的所有出现,并使用不同的字节作为结束指示符.
例如
final static byte ESCAPE = (byte) 0xBC;
final static byte EOF = (byte) 0x00;
OutputStream out = ...
for (byte b : source) {
if (b == ESCAPE) {
// escape data bytes that have the value of ESCAPE
out.write(ESCAPE);
out.write(ESCAPE);
} else {
out.write(b);
}
}
// write EOF marker ESCAPE, EOF
out.write(ESCAPE);
out.write(EOF);
Run Code Online (Sandbox Code Playgroud)
现在读取并读取ESCAPE字节时,读取下一个字节的x并检查EOF.如果它不是EOF,它是一个表示数据字节的转义ESCAPE.
InputStream in = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
while ((int b = in.read()) != -1) {
if (b == ESCAPE) {
b = in.read();
if (b == EOF)
break;
buffer.write(b);
} else {
buffer.write(b);
}
}
Run Code Online (Sandbox Code Playgroud)
如果要写入的字节完全随机分布,这将使流长度增加1/256,对于非完全随机的数据域,您可以选择出现频率最低的字节(通过静态数据分析或只是有根据的猜测) .
编辑:您可以通过使用更复杂的逻辑来减少转义开销,例如,示例只能创建ESCAPE + ESCAPE或ESCAPE + EOF.其他254个字节在示例中永远不会跟随ESCAPE,因此可以利用它来存储合法数据组合.
这是完全不安全的,你永远不知道你的数据中会出现什么。也许你应该考虑像protobuf这样的东西,或者像“首先写入记录长度,然后写入记录,然后冲洗,起泡,重复”这样的方案?
如果有长度,则不需要分隔符。您的读取端读取长度,然后知道要读取第一个记录的长度,然后知道读取下一个长度 - 所有这些都假设长度本身是固定长度的。