Вы не можете просто объявить байт в качестве разделителя, если работаете со случайными неструктурированными данными (которые сжатые/зашифрованные данные похожи довольно близко), поскольку разделитель всегда может отображаться как обычный байт данных в таких данных.
Если размер данных уже известен, когда вы начинаете писать, просто напишите сначала размер, а затем данные. При чтении вы тогда знаете, вам нужно сначала прочитать размер (например, 4 байта для int), а затем указать столько байтов, сколько указано.
Это, очевидно, не работает, если вы не можете указать размер при записи. В этом случае вы можете использовать механизм экранирования, например. выберите редко появляющийся байт в качестве символа escapce, избегайте всех событий этого байта в данных и используйте другой байт в качестве индикатора конца.
например.
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);
Теперь при чтении и вы читаете ESCAPE байт, вы читали рять ж следующий байт и проверить EOF. Если его не EOF, это escape-код 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);
}
}
Если байты должны быть записаны отлично распределены случайным образом это увеличит длину потока по 1/256, для областей данных, которые не являются полностью случайными, вы можете выбрать байты, который не менее часто появляющиеся (статическим анализ данных или просто образованное предположение).
Редактирование: вы можете уменьшить накладные расходы, используя более сложную логику, например. пример может создать только ESCAPE + ESCAPE или ESCAPE + EOF.Другие 254 байта никогда не могут следовать за ESCAPE в этом примере, поэтому их можно было бы использовать для хранения легальных комбинаций данных.
Частные ключевые подходы не являются более сильными. Они просто используются для разных приложений, в основном для ключевых соглашений или для транспортировки ключей. Вы должны кодировать длину каждого сообщения в потоке, а не пытаться выбрать разделитель. Это безопаснее и проще. – erickson
@erickson Я думаю, вы пропустили запятую между более сильным и закрытым ключом. Я говорил о стандартных алгоритмах секретного ключа, я бы выбрал один из самых сильных. Кроме того, вы запутываете секретный и открытый ключ. Ключ открытого ключа используется для согласования и для передачи частных (симметричных) ключей. –
Хорошо, хотелось убедиться, что вы не работали под общим заблуждением, что асимметричные алгоритмы более безопасны, чем симметричные алгоритмы. «Симметричный» или «секретный ключ» гораздо менее правдоподобен, чем «закрытый ключ». – erickson