我正在加密数据到流。例如,如果我的数据类型为Int32
,我将使用BitConverter.GetBytes(myInt)
来获取字节,然后将这些字节写入流中。
要读回数据,我读sizeof(Int32)
以确定要读取的字节数,读取这些字节,然后使用BitConverter.ToInt32(byteArray, 0)
将字节转换回Int32
。
那么我怎么用字符串做这个呢?写字符串没问题。但是读取字符串时的技巧是知道在我将其转换回字符串之前要读取多少字节。
我发现了类似的问题,但他们似乎认为字符串占用了整个流,只是读到了流的末尾。但是在这里,我可以在字符串之前和之后有任意数量的其他项目。
请注意,此处StringReader
不是一个选项,因为我想要处理可能比我想要加载到内存中的文件数据更大的选项。
答案 0 :(得分:1)
我们想到的解决方案是提供预定的标记值来表示字符串的结尾(例如,ASM使用0字节),或者在每个字符串之前提供固定长度的元数据块新的数据类型。在那个元数据块中,类型和长度,以及你发现它包含的任何其他信息。
对于紧凑性,我会使用sentinel值,如果它在你的系统中有效。
答案 1 :(得分:1)
您通常会发送内容长度标题,然后读取该信息确定的长度。
以下是一些示例代码:
public async Task ContinouslyReadFromStream(NetworkStream sourceStream, CancellationToken token)
{
while (!ct.IsCancellationRequested && sourceStream.CanRead)
{
while (sourceStream.CanRead && !sourceStream.DataAvailable)
{
// Avoid potential high CPU usage when doing stream.ReadAsync
// while waiting for data
Thread.Sleep(10);
}
var lengthOfMessage = BitConverter.ToInt32(await ReadExactBytesAsync(stream, 4, ct), 0);
var content = await ReadExactBytesAsync(stream, lengthOfMessage, ct);
// Assuming you use UTF8 encoding
var stringContent = Encoding.UTF8.GetString(content);
}
}
protected static async Task<byte[]> ReadExactBytesAsync(Stream stream, int count, CancellationToken ct)
{
var buffer = new byte[count];
var totalBytesRemaining = count;
var totalBytesRead = 0;
while (totalBytesRemaining != 0)
{
var bytesRead = await stream.ReadAsync(buffer, totalBytesRead, totalBytesRemaining, ct);
ct.ThrowIfCancellationRequested();
totalBytesRead += bytesRead;
totalBytesRemaining -= bytesRead;
}
return buffer;
}