문자열에서 스트림을 어떻게 생성합니까?


답변:


956
public static Stream GenerateStreamFromString(string s)
{
    var stream = new MemoryStream();
    var writer = new StreamWriter(stream);
    writer.Write(s);
    writer.Flush();
    stream.Position = 0;
    return stream;
}

다음을 사용하는 것을 잊지 마십시오.

using (var stream = GenerateStreamFromString("a,b \n c,d"))
{
    // ... Do stuff to stream
}

StreamWriter처분되지 않는 것에 대해 . StreamWriter기본 스트림을 감싸는 래퍼 일 뿐이므로 처리해야 할 리소스를 사용하지 않습니다. 이 Dispose메소드 는 쓰는 기본 Stream을 닫습니다 StreamWriter. 이 경우에 MemoryStream우리 는 돌아 가고자합니다.

.NET 4.5에는 이제 StreamWriter작성자가 폐기 된 후에 기본 스트림을 열어 두는 과부하 가 있지만이 코드는 동일한 기능을 수행하며 다른 버전의 .NET에서도 작동합니다.

BaseStream을 닫지 않고 StreamWriter를 닫을 수있는 방법이 있습니까?를 참조하십시오 .


134
지적해야 할 중요한 개념은 스트림이 바이트로 구성되고 문자열은 문자로 구성된다는 것입니다. 문자를 하나 이상의 바이트 (또는이 경우와 같이 스트림)로 변환 할 때 항상 특정 인코딩을 사용하거나 가정 한다는 것을 이해하는 것이 중요합니다 . 이 답변은 경우에 따라 정확하지만 기본 인코딩을 사용하므로 일반적으로 적합하지 않을 수 있습니다. 명시 적으로 Encoding을 StreamWriter 생성자에 전달하면 작성자가 Encoding의 의미를 고려해야한다는 것이 더 분명해집니다.
drwatsoncode

6
스트림을 사용하기 위해 "사용 중"을 사용하는 것을 잊지 말고 사용 GenerateStreamFromString방법에서는 StreamWriter와 함께 사용하지 않습니다. 이것에 대한 이유가 있습니까?
Ben

12
@ 벤 예. StreamWriter를 폐기하면 기본 스트림도 닫힙니다. 우리는 그것을 원하지 않습니다. Writer가 일회용 인 이유는 스트림을 정리하는 것이므로 무시하는 것이 안전합니다.
Cameron MacFarland

2
또한 전체 문자열이 메모리에 복사되는데, 이는 큰 문자열에 중요 할 수 있습니다. 이제 메모리에 하나의 추가 사본이 있기 때문입니다.
UGEEN

1
@ahong 실제로는 아닙니다. StreamWriter어쨌든 당신이 내부적으로 말한 것을하고있을 것입니다. 장점은 캡슐화와 간단한 코드이지만 인코딩과 같은 것을 추상화하는 비용이 듭니다. 그것은 당신이 달성하려는 것에 달려 있습니다.
Cameron MacFarland 6

724

다른 해결책 :

public static MemoryStream GenerateStreamFromString(string value)
{
    return new MemoryStream(Encoding.UTF8.GetBytes(value ?? ""));
}

31
누군가 XML 문자열 역 직렬화에서 이것을 사용하는 경우 플래그없이 작동하도록 UTF8을 유니 코드로 전환해야했습니다. 좋은 소식 !!!
Gaspa79

2
나는 받아 들인 대답 보다이 것을 좋아합니다 (Rhyous의 비틀기와 확장 방법으로 사용하기위한 사소한 여분의 설탕 포함). 보다 유연하고 적은 LOC와 관련된 객체 수 감소 (StreamWriter가 필요 없음)
KeithS

2
new MemoryStream(Encoding.UTF8.GetBytes("\ufeff" + (value ?? ""))스트림의 시작 부분에 BOM을 포함해야하는 경우
robert4

5
이것은 매우 간결한 구문이지만 byte []가 많이 할당되므로 고성능 코드에주의하십시오.
michael.aird

1
이 솔루션은 여전히 ​​스트림을 읽기 전용으로 만들 기회를 남겼습니다. new MemoryStream( value, false ). 스트림 작성기로 스트림을 작성해야하는 경우 스트림을 읽기 전용으로 만들 수 없습니다.
codekandis

106

이것을 정적 문자열 유틸리티 클래스에 추가하십시오.

public static Stream ToStream(this string str)
{
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(str);
    writer.Flush();
    stream.Position = 0;
    return stream;
}

확장 기능이 추가되어 간단하게 수행 할 수 있습니다.

using (var stringStream = "My string".ToStream())
{
    // use stringStream
}

5
가비지 수집기가를 정리하면 반환 된 스트림이 반 임의의 예외를 일으켜 닫히는 것을 발견했습니다 StreamWriter. 수정은 다른 생성자를 사용하는 것이 었습니다 .
Bevan

45
public Stream GenerateStreamFromString(string s)
{
    return new MemoryStream(Encoding.UTF8.GetBytes(s));
}

24

MemoryStream클래스를 사용 Encoding.GetBytes하여 문자열을 먼저 바이트 배열로 변환하십시오.

나중에 TextReader스트림에 필요 합니까? 그렇다면 StringReader직접 제공 하고 MemoryStreamEncoding단계를 무시할 수 있습니다.


23

나는 다음과 같은 답변을 혼합하여 사용했습니다.

public static Stream ToStream(this string str, Encoding enc = null)
{
    enc = enc ?? Encoding.UTF8;
    return new MemoryStream(enc.GetBytes(str ?? ""));
}

그리고 나는 이것을 다음과 같이 사용합니다 :

String someStr="This is a Test";
Encoding enc = getEncodingFromSomeWhere();
using (Stream stream = someStr.ToStream(enc))
{
    // Do something with the stream....
}

토마스, 왜 투표하지? enc = enc ?? Encoding.UTF8을 사용하면 특정 인코딩 또는 기본값 UTF8을 사용하여 스트림을 구체적으로 요청할 수 있습니다. 서명이 줄이 필요합니다.
Robocide

이것을 별도의 클래스 (일반 정적 클래스가 아닌?)에 넣어야한다는 언급도 도움이되며 다운 투표를 줄입니다.
Ali

13

아래에 나열된 확장 방법을 사용합니다. 개발자가 인코딩에 대한 결정을 내릴 수 있도록해야하므로 마술이 적습니다.

public static class StringExtensions {

    public static Stream ToStream(this string s) {
        return s.ToStream(Encoding.UTF8);
    }

    public static Stream ToStream(this string s, Encoding encoding) {
        return new MemoryStream(encoding.GetBytes(s ?? ""));
    }
}

1
첫 번째 방법을로 구현하는 것을 선호합니다 return ToStream(s, Encoding.UTF8);. 현재 구현에서 ( return s.ToStream(Encoding.UTF8);개발자는 코드를 이해하기가 더 어렵다고 생각하며,이 경우 s == null는 처리되지 않고 발생하는 것으로 보인다 NullReferenceException.
Palec

10

여기 있습니다 :

private Stream GenerateStreamFromString(String p)
{
    Byte[] bytes = UTF8Encoding.GetBytes(p);
    MemoryStream strm = new MemoryStream();
    strm.Write(bytes, 0, bytes.Length);
    return strm;
}

1
쓰기 후 위치를 재설정해야합니다. joelnet의 답변과 같이 생성자를 사용하는 것이 좋습니다.
짐 발터

10

다음에 대한 확장 메소드의 현대화되고 약간 수정 된 버전 ToStream:

public static Stream ToStream(this string value) => ToStream(value, Encoding.UTF8);

public static Stream ToStream(this string value, Encoding encoding) 
                          => new MemoryStream(encoding.GetBytes(value ?? string.Empty));

@Palec의 @Shaun Bowe 답변에 제안 된 수정.



4

인코딩을 변경 해야하는 경우 @ShaunBowe 의 솔루션에 투표하십시오 . 그러나 여기의 모든 대답은 전체 문자열을 메모리에 한 번 이상 복사합니다. ToCharArray+ BlockCopy콤보로 대답은 두 번 수행합니다.

이것이 중요한 경우 Stream원시 UTF-16 문자열 의 간단한 래퍼입니다. StreamReader선택 과 함께 사용하는 경우 Encoding.Unicode:

public class StringStream : Stream
{
    private readonly string str;

    public override bool CanRead => true;
    public override bool CanSeek => true;
    public override bool CanWrite => false;
    public override long Length => str.Length * 2;
    public override long Position { get; set; } // TODO: bounds check

    public StringStream(string s) => str = s ?? throw new ArgumentNullException(nameof(s));

    public override long Seek(long offset, SeekOrigin origin)
    {
        switch (origin)
        {
            case SeekOrigin.Begin:
                Position = offset;
                break;
            case SeekOrigin.Current:
                Position += offset;
                break;
            case SeekOrigin.End:
                Position = Length - offset;
                break;
        }

        return Position;
    }

    private byte this[int i] => (i & 1) == 0 ? (byte)(str[i / 2] & 0xFF) : (byte)(str[i / 2] >> 8);

    public override int Read(byte[] buffer, int offset, int count)
    {
        // TODO: bounds check
        var len = Math.Min(count, Length - Position);
        for (int i = 0; i < len; i++)
            buffer[offset++] = this[(int)(Position++)];
        return (int)len;
    }

    public override int ReadByte() => Position >= Length ? -1 : this[(int)Position++];
    public override void Flush() { }
    public override void SetLength(long value) => throw new NotSupportedException();
    public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
    public override string ToString() => str; // ;)     
}

그리고 여기 에 필요한 바운드 검사 ( MemoryStream따라서 가지고있는 방법 ToArrayWriteTo방법도 있음) 가있는보다 완벽한 솔루션이 있습니다.


-2

문자열 확장의 좋은 조합 :

public static byte[] GetBytes(this string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

public static Stream ToStream(this string str)
{
    Stream StringStream = new MemoryStream();
    StringStream.Read(str.GetBytes(), 0, str.Length);
    return StringStream;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.