your programing

스트림에서 바이트 배열 만들기

lovepro 2020. 9. 28. 09:52
반응형

스트림에서 바이트 배열 만들기


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

다음은 .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의 대답은 맞지만 .NET에 이미 존재하는 코드를 다시 작성하고 있습니다 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();
        }
    }
}

add namespace to the config file and use it anywhere you wish


You can even make it fancier with extensions:

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

And then call it as a regular method:

byte[] arr = someStream.ToByteArray()

You can simply use ToArray() method of MemoryStream class, for ex-

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

I get a compile time error with Bob's (i.e. the questioner's) code. Stream.Length is a long whereas BinaryReader.ReadBytes takes an integer parameter. In my case, I do not expect to be dealing with Streams large enough to require long precision, so I use the following:

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

The one above is ok...but you will encounter data corruption when you send stuff over SMTP (if you need to). I've altered to something else that will help to correctly send byte for byte: '

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;
        }'

Create a helper class and reference it anywhere you wish to use it.

public static class StreamHelpers
{
    public static byte[] ReadFully(this Stream input)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            input.CopyTo(ms);
            return ms.ToArray();
        }
    }
}

In case anyone likes it, here is a .NET 4+ only solution formed as an extension method without the needless Dispose call on the MemoryStream. This is a hopelessly trivial optimization, but it is worth noting that failing to Dispose a MemoryStream is not a real failure.

public static class StreamHelpers
{
    public static byte[] ReadFully(this Stream input)
    {
        var ms = new MemoryStream();
        input.CopyTo(ms);
        return ms.ToArray();
    }
}

In namespace RestSharp.Extensions there is method ReadAsBytes. Inside this method is used MemoryStream and there is the same code like in some examples on this page but when you are using RestSharp this is easiest way.

using RestSharp.Extensions;
var byteArray = inputStream.ReadAsBytes();

You can use this extension method.

public static class StreamExtensions
{
    public static byte[] ToByteArray(this Stream stream)
    {
        var bytes = new List<byte>();

        int b;
        while ((b = stream.ReadByte()) != -1)
            bytes.Add((byte)b);

        return bytes.ToArray();
    }
}

This is the function which I am using, tested and worked well. please bear in mind that 'input' should not be null and 'input.position' should reset to '0' before reading otherwise it will break the read loop and nothing will read to convert to array.

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

i was able to make it work on a single line:

byte [] byteArr= ((MemoryStream)localStream).ToArray();

as clarified by johnnyRose, Above code will only work for MemoryStream

참고URL : https://stackoverflow.com/questions/221925/creating-a-byte-array-from-a-stream

반응형