입력 스트림에서 바이트 배열을 만드는 데 선호되는 방법은 무엇입니까?
다음은 .NET 3.5의 현재 솔루션입니다.
Stream s;
byte[] b;
using (BinaryReader br = new BinaryReader(s))
{
b = br.ReadBytes((int)s.Length);
}
스트림 덩어리를 읽고 쓰는 것이 여전히 더 좋은 아이디어입니까?
입력 스트림에서 바이트 배열을 만드는 데 선호되는 방법은 무엇입니까?
다음은 .NET 3.5의 현재 솔루션입니다.
Stream s;
byte[] b;
using (BinaryReader br = new BinaryReader(s))
{
b = br.ReadBytes((int)s.Length);
}
스트림 덩어리를 읽고 쓰는 것이 여전히 더 좋은 아이디어입니까?
답변:
그것은 당신이 믿을 수 있는지 아닌지에 달려 있습니다 s.Length. 많은 스트림의 경우 얼마나 많은 데이터가 있는지 알 수 없습니다. 이러한 경우-.NET 4 이전-다음과 같은 코드를 사용합니다.
public static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16*1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
.NET 4 이상으로, 내가 사용하는 거라고 Stream.CopyTo만들기 - 내 코드에서 루프 기본적으로 동등한 인 MemoryStream, 전화를 stream.CopyTo(ms)한 후 반환 ms.ToArray(). 작업이 완료되었습니다.
왜 내 답변이 다른 답변보다 긴지 설명해야합니다. Stream.Read요청한 모든 내용을 읽도록 보장하지는 않습니다. 예를 들어 네트워크 스트림에서 읽는 경우 더 많은 데이터가 있더라도 하나의 패킷 가치를 읽은 다음 반환 될 수 있습니다. BinaryReader.Read스트림이 끝날 때까지 또는 지정된 크기까지 계속 진행되지만 시작하려면 크기를 알아야합니다.
위의 방법은 MemoryStream데이터가 부족해질 때까지 계속 읽고 읽 습니다. 그런 다음 MemoryStream데이터의 복사본을 배열로 반환 하도록 요청합니다 . 크기를 시작으로 알고 있거나 확실하지 않은 경우 크기를 알고 있다고 생각되면를 시작 MemoryStream하기 위해 해당 크기가되도록 구성 할 수 있습니다 . 마찬가지로 끝에 검사를 할 수 있으며 스트림의 길이가 버퍼와 크기가 같으면 (로 반환 MemoryStream.GetBuffer) 버퍼를 반환 할 수 있습니다. 따라서 위의 코드는 최적화되지 않았지만 적어도 정확합니다. 스트림을 닫을 책임은 없습니다. 호출자가 그렇게해야합니다.
자세한 내용 및 대체 구현에 대해서는 이 기사 를 참조하십시오 .
16*1024구체적으로 물어봐도 될까요?
Jon의 답변은 정확하지만 이미 존재하는 코드를 다시 작성하고 있습니다 CopyTo. 따라서 .Net 4의 경우 Sandip 솔루션을 사용하지만 이전 버전의 .Net의 경우 Jon의 답변을 사용하십시오. Sandip의 코드는 CopyTo많은 상황에서 예외가 있을 가능성이 높고 MemoryStream폐기되지 않은 채 "사용"을 사용하여 개선 될 것 입니다.
public static byte[] ReadFully(Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
input이미 MemorySteam단락되어 있는지 확인하는 것이 좋습니다. 나는 발신자가 어리석은 짓을한다는 것을 알고 MemoryStream있지만 ...
MemoryStream다음 최적화가 당신의 맥락에서 의미가 있는지 여부의 하나 복사하는 데 걸리는 시간에 대해 형식 변환의 수백만을 수행하는 데 걸리는 시간을 비교 한 MemoryStream로를 다른 MemoryStream.
이미 가지고있는 MemoryStream이있는 memorystream.ToArray()경우 지적하십시오.
또한 알려지지 않은 또는 다른 하위 유형의 스트림을 처리하고 있고를 수신 MemoryStream할 수있는 경우 해당 경우에 대해 상기 방법을 중계하고 다른 방법에 대해 여전히 허용 된 답변을 사용할 수 있습니다.
public static byte[] StreamToByteArray(Stream stream)
{
if (stream is MemoryStream)
{
return ((MemoryStream)stream).ToArray();
}
else
{
// Jon Skeet's accepted answer
return ReadFully(stream);
}
}
MemoryStream. 물론 예제는 초기화되지 않은 변수를 사용하는 방법에 있어서도 불완전합니다.
stream.Seek(1L, SeekOrigin.Begin)당신은 내의 readFully 호출하기 전에 스트림은 메모리 스트림 인 경우, 당신은 다른 스트림의 경우 1보다 더 많은 바이트를 얻을 것이다. 호출자가 현재 위치가 스트림의 끝까지 인 곳에서 읽을 것으로 예상하는 경우 CopyTo또는 ToArray(); 대부분의 경우 이것은 문제가되지 않지만 호출자가이 기발한 동작에 대해 알지 못하면 혼동 될 것입니다.
MemoryStream ms = new MemoryStream();
file.PostedFile.InputStream.CopyTo(ms);
var byts = ms.ToArray();
ms.Dispose();
내 커플 센트 ... 내가 자주 사용하는 연습은 이와 같은 방법을 사용자 정의 도우미로 구성하는 것입니다.
public static class StreamHelpers
{
public static byte[] ReadFully(this Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
}
구성 파일에 네임 스페이스를 추가하고 원하는 곳에서 사용하십시오.
CopyTo사용할 수 없었으므로 .NET 3.5 이하에서는 작동 하지 않습니다 Stream.
확장 기능으로 더 멋지게 만들 수도 있습니다.
namespace Foo
{
public static class Extensions
{
public static byte[] ToByteArray(this Stream stream)
{
using (stream)
{
using (MemoryStream memStream = new MemoryStream())
{
stream.CopyTo(memStream);
return memStream.ToArray();
}
}
}
}
}
그런 다음 일반 메소드로 호출하십시오.
byte[] arr = someStream.ToByteArray()
Bob 's (즉, 질문자) 코드에서 컴파일 시간 오류가 발생합니다. Stream.Length는 길지만 BinaryReader.ReadBytes는 정수 매개 변수를 사용합니다. 필자의 경우 긴 정밀도를 요구할만큼 충분히 큰 스트림을 처리 할 것으로 예상하지 않으므로 다음을 사용합니다.
Stream s;
byte[] b;
if (s.Length > int.MaxValue) {
throw new Exception("This stream is larger than the conversion algorithm can currently handle.");
}
using (var br = new BinaryReader(s)) {
b = br.ReadBytes((int)s.Length);
}
누구나 좋아하는 경우 MemoryStream에서 불필요한 Dispose 호출없이 확장 방법으로 형성된 .NET 4+ 전용 솔루션이 있습니다. 이것은 절망적으로 사소한 최적화이지만 MemoryStream을 처리하지 못하는 것이 실제로 실패하지는 않습니다.
public static class StreamHelpers
{
public static byte[] ReadFully(this Stream input)
{
var ms = new MemoryStream();
input.CopyTo(ms);
return ms.ToArray();
}
}
위의 내용은 괜찮습니다 ...하지만 SMTP를 통해 물건을 보내면 데이터가 손상됩니다 (필요한 경우). 바이트 바이트를 올바르게 보내는 데 도움이되는 다른 것으로 변경했습니다. '
using System;
using System.IO;
private static byte[] ReadFully(string input)
{
FileStream sourceFile = new FileStream(input, FileMode.Open); //Open streamer
BinaryReader binReader = new BinaryReader(sourceFile);
byte[] output = new byte[sourceFile.Length]; //create byte array of size file
for (long i = 0; i < sourceFile.Length; i++)
output[i] = binReader.ReadByte(); //read until done
sourceFile.Close(); //dispose streamer
binReader.Close(); //dispose reader
return output;
}'
네임 스페이스 RestSharp.Extensions에는 ReadAsBytes 메소드가 있습니다. 이 메서드 안에는 MemoryStream이 사용되고이 페이지의 일부 예제와 같은 코드가 있지만 RestSharp를 사용하는 경우 가장 쉬운 방법입니다.
using RestSharp.Extensions;
var byteArray = inputStream.ReadAsBytes();
이것은 내가 사용하고 테스트하고 잘 작동 한 기능입니다. 'input'은 null이 아니어야하며 'input.position'은 읽기 전에 '0'으로 재설정되어야합니다. 그렇지 않으면 읽기 루프가 중단되고 배열로 변환하기 위해 아무것도 읽지 않습니다.
public static byte[] StreamToByteArray(Stream input)
{
if (input == null)
return null;
byte[] buffer = new byte[16 * 1024];
input.Position = 0;
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
byte[] temp = ms.ToArray();
return temp;
}
}
public static byte[] ToByteArray(Stream stream)
{
if (stream is MemoryStream)
{
return ((MemoryStream)stream).ToArray();
}
else
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
}
한 줄로 작동시킬 수있었습니다.
byte [] byteArr= ((MemoryStream)localStream).ToArray();
johnnyRose 에 의해 명확하게 , 위의 코드는 MemoryStream에서만 작동합니다
localStream않으면 MemoryStream어떻게됩니까? 이 코드는 실패합니다.
localStreamA와 MemoryStream있지만 localStream입니다 하지MemoryStream , 그것은 것입니다 실패합니다. 이 코드는 잘 컴파일되지만 실제 유형에 따라 런타임에 실패 할 수 localStream있습니다. 항상 기본 유형을 하위 유형으로 캐스트 할 수는 없습니다. 자세한 내용은 여기를 참조하십시오 . 이것은 왜 항상 이것을 할 수 없는지 를 설명하는 또 다른 좋은 예 입니다 .