How to convert an Stream into a byte[] in C#?
有没有一种简单的方法或方法可以将c中的
我知道最短的解决方案:
1 2 3 4 5 | using(var memoryStream = new MemoryStream()) { sourceStream.CopyTo(memoryStream); return memoryStream.ToArray(); } |
号
调用下一个函数
1 | byte[] m_Bytes = StreamHelper.ReadToEnd (mystream); |
功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | public static byte[] ReadToEnd(System.IO.Stream stream) { long originalPosition = 0; if(stream.CanSeek) { originalPosition = stream.Position; stream.Position = 0; } try { byte[] readBuffer = new byte[4096]; int totalBytesRead = 0; int bytesRead; while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0) { totalBytesRead += bytesRead; if (totalBytesRead == readBuffer.Length) { int nextByte = stream.ReadByte(); if (nextByte != -1) { byte[] temp = new byte[readBuffer.Length * 2]; Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length); Buffer.SetByte(temp, totalBytesRead, (byte)nextByte); readBuffer = temp; totalBytesRead++; } } } byte[] buffer = readBuffer; if (readBuffer.Length != totalBytesRead) { buffer = new byte[totalBytesRead]; Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead); } return buffer; } finally { if(stream.CanSeek) { stream.Position = originalPosition; } } } |
号
在.NET Framework 4及更高版本中,
对于早期版本的框架,要具有的方便助手功能是:
1 2 3 4 5 6 7 | public static void CopyStream(Stream input, Stream output) { byte[] b = new byte[32768]; int r; while ((r = input.Read(b, 0, b.Length)) > 0) output.Write(b, 0, r); } |
。
然后使用上述方法之一复制到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | var file = new FileStream("c:\\foo.txt", FileMode.Open); var mem = new MemoryStream(); // If using .NET 4 or later: file.CopyTo(mem); // Otherwise: CopyStream(file, mem); // getting the internal buffer (no additional copying) byte[] buffer = mem.GetBuffer(); long length = mem.Length; // the actual length of the data // (the array may be longer) // if you need the array to be exactly as long as the data byte[] truncated = mem.ToArray(); // makes another copy |
编辑:最初我建议使用Jason对支持
对于大多数情况,使用上述通用解决方案可能更简单,但假设您确实希望直接读取到一个名为
1 2 3 4 | byte[] b = new byte[bigEnough]; int r, offset; while ((r = input.Read(b, offset, b.Length - offset)) > 0) offset += r; |
。
也就是说,反复调用
1 2 3 4 | byte[] buf; // byte array Stream stream=Page.Request.InputStream; //initialise new stream buf = new byte[stream.Length]; //declare arraysize stream.Read(buf, 0, buf.Length); // read from stream to byte array |
。
我使用这个扩展类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
号
只需将类复制到解决方案中,就可以在每个流上使用它:
1 | byte[] bytes = myStream.ReadAllBytes() |
号
对我所有的流都很有用,并且节省了很多代码!当然,如果需要的话,您可以修改这个方法来使用这里的其他一些方法来提高性能,但是我喜欢保持简单。
1 |
号
好吧,也许我错过了一些东西,但我就是这样做的:
1 2 3 4 5 6 | public static Byte[] ToByteArray(this Stream stream) { Int32 length = stream.Length > Int32.MaxValue ? Int32.MaxValue : Convert.ToInt32(stream.Length); Byte[] buffer = new Byte[length]; stream.Read(buffer, 0, length); return buffer; } |
号
如果您从移动设备或其他设备发布文件
1 2 3 4 5 | byte[] fileData = null; using (var binaryReader = new BinaryReader(Request.Files[0].InputStream)) { fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength); } |
号
快速肮脏技术:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | static byte[] StreamToByteArray(Stream inputStream) { if (!inputStream.CanRead) { throw new ArgumentException(); } // This is optional if (inputStream.CanSeek) { inputStream.Seek(0, SeekOrigin.Begin); } byte[] output = new byte[inputStream.Length]; int bytesRead = inputStream.Read(output, 0, output.Length); Debug.Assert(bytesRead == output.Length,"Bytes read from stream matches stream length"); return output; } |
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 | static void Main(string[] args) { byte[] data; string path = @"C:\Windows\System32 otepad.exe"; using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read)) { data = StreamToByteArray(fs); } Debug.Assert(data.Length > 0); Debug.Assert(new FileInfo(path).Length == data.Length); } |
。
我会问,如果您希望复制流的内容,为什么要将流读取到字节[],我建议您使用memory stream并将输入流写入内存流。
您还可以尝试一次只读取部分内容,并扩展返回的字节数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public byte[] StreamToByteArray(string fileName) { byte[] total_stream = new byte[0]; using (Stream input = File.Open(fileName, FileMode.Open, FileAccess.Read)) { byte[] stream_array = new byte[0]; // Setup whatever read size you want (small here for testing) byte[] buffer = new byte[32];// * 1024]; int read = 0; while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { stream_array = new byte[total_stream.Length + read]; total_stream.CopyTo(stream_array, 0); Array.Copy(buffer, 0, stream_array, total_stream.Length, read); total_stream = stream_array; } } return total_stream; } |
1 2 3 4 5 6 7 | Stream s; int len = (int)s.Length; byte[] b = new byte[len]; int pos = 0; while((r = s.Read(b, pos, len - pos)) > 0) { pos += r; } |
一个稍微复杂一点的解决方案是,
编辑:如果流不支持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public static class StreamExtensions { // Credit to Earwicker public static void CopyStream(this Stream input, Stream output) { byte[] b = new byte[32768]; int r; while ((r = input.Read(b, 0, b.Length)) > 0) { output.Write(b, 0, r); } } } [...] Stream s; MemoryStream ms = new MemoryStream(); s.CopyStream(ms); byte[] b = ms.GetBuffer(); |
。
"足够大"数组有点夸张。当然,缓冲区需要是"大电子书",但是应用程序的正确设计应该包括事务和分隔符。在这个配置中,每个事务都有一个预设的长度,因此您的数组将预期一定数量的字节,并将其插入到正确大小的缓冲区中。分隔符将确保事务完整性,并将在每个事务中提供。为了使您的应用程序更好,您可以使用2个通道(2个插座)。一种方法是通信固定长度的控制消息事务,其中包括有关使用数据通道传输的数据事务的大小和序列号的信息。接收器将确认缓冲区的创建,然后才发送数据。如果您对流发送器没有控制权,则需要多维数组作为缓冲区。根据您对预期数据的估计,组件数组将小到可以管理,大到可以实际使用。进程逻辑将在随后的元素数组中查找已知的开始分隔符,然后查找结束分隔符。一旦找到结束分隔符,将创建新的缓冲区来存储分隔符之间的相关数据,并且必须重新构造初始缓冲区以允许数据处理。
至于将流转换为字节数组的代码,请参阅下面的代码。
1 2 3 4 | Stream s = yourStream; int streamEnd = Convert.ToInt32(s.Length); byte[] buffer = new byte[streamEnd]; s.Read(buffer, 0, streamEnd); |
号