[C#] 스트림에서 바이트 배열 만들기

입력 스트림에서 바이트 배열을 만드는 데 선호되는 방법은 무엇입니까?

다음은 .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) 버퍼를 반환 할 수 있습니다. 따라서 위의 코드는 최적화되지 않았지만 적어도 정확합니다. 스트림을 닫을 책임은 없습니다. 호출자가 그렇게해야합니다.

자세한 내용 및 대체 구현에 대해서는 이 기사 를 참조하십시오 .


답변

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();
    }
}


답변

이미 가지고있는 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 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();
        }
    }
}

구성 파일에 네임 스페이스를 추가하고 원하는 곳에서 사용하십시오.


답변

예를 들어 MemoryStream 클래스의 ToArray () 메서드를 사용할 수 있습니다.

MemoryStream ms = (MemoryStream)dataInStream;
byte[] imageBytes = ms.ToArray();


답변

확장 기능으로 더 멋지게 만들 수도 있습니다.

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()