This is possible.
You should make it a binary (non-human-readable) file, and use the BinaryWriter
and BinaryReader
classes to read and write the lengths.
You can read a file from it like this:
using (FileStream combinedFile = File.Open(...))
using (var binReader = new BinaryReader(combinedFile)) {
while(!combinedFile.EOF) {
long segmentLength = binReader.ReadInt64();
var bytes = new byte[segmentLength];
long totalRead = 0;
while(bytesRead < segmentLength) {
int read = combinedFile.Read(bytes, totalRead, Math.Min(4096, segmentLength - totalRead));
if (read == 0)
throw new InvalidDataException();
}
yield return new MemoryStream(bytes);
}
}
EDIT To make a human-readable file, write the segment length as a fixed-length string (padded to some reasonable number of digits, such as 16), optionally followed by a newline. The maximum segment size is the length of the string.
You can read a file from it like this:
const int LengthPadding = 16
using (FileStream combinedFile = File.Open(...))
using (var binReader = new BinaryReader(combinedFile)) {
while(!combinedFile.EOF) {
char[] segmentLengthChars = binReader.ReadChars(16);
long segmentLength = long.Parse(new string(segmentLengthChars));
binReader.ReadChars(2); //Skip the newline
var bytes = new byte[segmentLength];
long totalRead = 0;
while(bytesRead < segmentLength) {
int read = combinedFile.Read(bytes, totalRead, Math.Min(4096, segmentLength - totalRead));
if (read == 0)
throw new InvalidDataException();
}
yield return new MemoryStream(bytes);
}
}
To write the segment length, call
binWriter.WriteChars(length.ToString().PadLeft(16, '0').ToCharArray());
binWriter.WriteChars(new char[] { '\r', '\n' });
You should explicitly pass an encoding and CultureInfo.InvariantCulture
where applicable.