문제

는 가장 좋은 방법은 무엇입하의 내용을 복사 중 하나는 스트림을 다른?있는 표준 유틸리티는 방법에 대한 이?

도움이 되었습니까?

해결책

습니다.NET4.5 에,거기에 Stream.CopyToAsync 방법

input.CopyToAsync(output);

이 반환됩 Task 할 수 있는 계속에서 완료되면 다음과 같이:

await input.CopyToAsync(output)

// Code from here on will be run in a continuation.

참고는 위치에 따라 전화 CopyToAsync 는 코드는 다음과 같이지 않을 수도 있습을 계속 동일한 스레드에서 호출한다.

SynchronizationContext 캡처를 호출할 때 await 을 결정할 것이 무엇인 스레드가 계속 실행됩니다.

또한,이화(이 구현한 세부사항 변경 가능)아직도 순서를 읽고 씁니다(이것은 그냥을 낭비하지 않는 스레드에 차단 I/O completion).

습니다.NET4.0 에 있는 Stream.CopyTo 방법

input.CopyTo(output);

습니다.NET3.5 기

거기에 아무것도 하지 않으로 구운 프레임워크를 돕기 위해 이;당신은 콘텐츠를 복사할 수동으로 아래와 같이:

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[32768];
    int read;
    while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write (buffer, 0, read);
    }
}

참고 1:이 방법을 할 수 있도록 보고에서 진행(x 읽은 바이 지금까지...)
참고 2:을 사용해야 하는 이유는 무엇입니까 고정된 버퍼 크기지 input.Length?기 때문에 그 길이를 사용하지 못할 수 있습!서 문서:

는 경우에서 파생된 클래스 스트림을 지원하지 않을 찾를 호출하려면 길이,SetLength,위치 추구를 던져 코드 액세스 보안을 통해 보호.

다른 팁

MemoryStream은 .writeto (아웃스트림)를 가지고 있습니다.

.NET 4.0에는 정상 스트림 객체에 .copyto가 있습니다.

.NET 4.0 :

instream.CopyTo(outstream);

다음 확장 방법을 사용합니다. 그들은 한 스트림이 메모리 스트림 일 때 과부하를 최적화했습니다.

    public static void CopyTo(this Stream src, Stream dest)
    {
        int size = (src.CanSeek) ? Math.Min((int)(src.Length - src.Position), 0x2000) : 0x2000;
        byte[] buffer = new byte[size];
        int n;
        do
        {
            n = src.Read(buffer, 0, buffer.Length);
            dest.Write(buffer, 0, n);
        } while (n != 0);           
    }

    public static void CopyTo(this MemoryStream src, Stream dest)
    {
        dest.Write(src.GetBuffer(), (int)src.Position, (int)(src.Length - src.Position));
    }

    public static void CopyTo(this Stream src, MemoryStream dest)
    {
        if (src.CanSeek)
        {
            int pos = (int)dest.Position;
            int length = (int)(src.Length - src.Position) + pos;
            dest.SetLength(length); 

            while(pos < length)                
                pos += src.Read(dest.GetBuffer(), pos, length - pos);
        }
        else
            src.CopyTo((Stream)dest);
    }

"Copystream"의 구현을 구별하는 기본 질문은 다음과 같습니다.

  • 읽기 버퍼의 크기
  • 글의 크기
  • 둘 이상의 스레드를 사용할 수 있습니까 (읽는 동안 쓰기).

이러한 질문에 대한 답변은 사본의 구현을 크게 구현하고 어떤 종류의 스트림과 최적화하려는 것에 의존합니다. "최고의"구현은 스트림이 읽고 쓰고있는 특정 하드웨어를 알아야합니다.

실제로 스트림 사본을 수행하는 덜 무거운 방법이 있습니다. 그러나 전체 파일을 메모리에 저장할 수 있음을 의미합니다. 수백 메가 바이트 이상으로 들어가는 파일을 사용하여주의를 기울이지 않는 경우 이것을 사용하지 마십시오.

public static void CopyStream(Stream input, Stream output)
{
  using (StreamReader reader = new StreamReader(input))
  using (StreamWriter writer = new StreamWriter(output))
  {
    writer.Write(reader.ReadToEnd());
  }
}

참고 : 이진 데이터 및 문자 인코딩에 관한 몇 가지 문제가있을 수 있습니다.

.NET Framework 4 system.io 네임 스페이스의 스트림 클래스의 새로운 "Copyto"메소드를 소개합니다. 이 방법을 사용하여 한 스트림을 다른 스트림 클래스의 다른 스트림에 복사 할 수 있습니다.

여기에 대한 예가 있습니다.

    FileStream objFileStream = File.Open(Server.MapPath("TextFile.txt"), FileMode.Open);
    Response.Write(string.Format("FileStream Content length: {0}", objFileStream.Length.ToString()));

    MemoryStream objMemoryStream = new MemoryStream();

    // Copy File Stream to Memory Stream using CopyTo method
    objFileStream.CopyTo(objMemoryStream);
    Response.Write("<br/><br/>");
    Response.Write(string.Format("MemoryStream Content length: {0}", objMemoryStream.Length.ToString()));
    Response.Write("<br/><br/>");

불행히도, 간단한 솔루션은 없습니다. 당신은 그런 것을 시도 할 수 있습니다 :

Stream s1, s2;
byte[] buffer = new byte[4096];
int bytesRead = 0;
while (bytesRead = s1.Read(buffer, 0, buffer.Length) > 0) s2.Write(buffer, 0, bytesRead);
s1.Close(); s2.Close();

그러나 읽을 것이 없다면 스트림 클래스의 다른 구현이 다르게 행동 할 수 있습니다. 로컬 하드 드라이브에서 파일을 읽는 스트림은 읽기 오퍼레이션이 버퍼를 채우기 위해 디스크에서 충분한 데이터를 읽고 파일 끝에 도달하면 더 적은 데이터를 반환 할 때까지 차단 될 것입니다. 반면에, 네트워크의 스트림 판독 값은 더 많은 데이터가 남아 있더라도 더 적은 데이터를 반환 할 수 있습니다.

일반 솔루션을 사용하기 전에 사용중인 특정 스트림 클래스의 문서를 항상 확인하십시오.

어떤 종류의 스트림을 사용하고 있는지에 따라 더 효율적으로 수행 할 수있는 방법이있을 수 있습니다. 스트림 중 하나 또는 둘 다를 MemoryStream으로 변환 할 수있는 경우 GetBuffer 메소드를 사용하여 데이터를 나타내는 바이트 배열로 직접 작동 할 수 있습니다. 이를 통해 Fryguybob이 제기 한 모든 문제를 추상화하는 Array.copyto와 같은 방법을 사용할 수 있습니다. 데이터를 복사하는 최적의 방법을 알기 위해 .NET을 신뢰할 수 있습니다.

Procdure가 다른 스트림을 다른 스트림에 복사하기 위해 Nick이 게시 한 것도 괜찮지 만 위치 재설정이 누락 된 경우

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[32768];
    long TempPos = input.Position;
    while (true)    
    {
        int read = input.Read (buffer, 0, buffer.Length);
        if (read <= 0)
            return;
        output.Write (buffer, 0, read);
    }
    input.Position = TempPos;// or you make Position = 0 to set it at the start
}

그러나 런타임에있는 경우 프로 시저를 사용하지 않으면 메모리 스트림을 사용합니다.

Stream output = new MemoryStream();
byte[] buffer = new byte[32768]; // or you specify the size you want of your buffer
long TempPos = input.Position;
while (true)    
{
    int read = input.Read (buffer, 0, buffer.Length);
    if (read <= 0)
        return;
    output.Write (buffer, 0, read);
 }
    input.Position = TempPos;// or you make Position = 0 to set it at the start

답은 한 스트림에서 다른 스트림으로의 비동기 복사 방법을 다루지 않았으므로 여기에 한 네트워크 스트림에서 다른 네트워크로 데이터를 복사하기 위해 포트 전달 애플리케이션에서 성공적으로 사용한 패턴이 있습니다. 패턴을 강조하기위한 예외 처리가 부족합니다.

const int BUFFER_SIZE = 4096;

static byte[] bufferForRead = new byte[BUFFER_SIZE];
static byte[] bufferForWrite = new byte[BUFFER_SIZE];

static Stream sourceStream = new MemoryStream();
static Stream destinationStream = new MemoryStream();

static void Main(string[] args)
{
    // Initial read from source stream
    sourceStream.BeginRead(bufferForRead, 0, BUFFER_SIZE, BeginReadCallback, null);
}

private static void BeginReadCallback(IAsyncResult asyncRes)
{
    // Finish reading from source stream
    int bytesRead = sourceStream.EndRead(asyncRes);
    // Make a copy of the buffer as we'll start another read immediately
    Array.Copy(bufferForRead, 0, bufferForWrite, 0, bytesRead);
    // Write copied buffer to destination stream
    destinationStream.BeginWrite(bufferForWrite, 0, bytesRead, BeginWriteCallback, null);
    // Start the next read (looks like async recursion I guess)
    sourceStream.BeginRead(bufferForRead, 0, BUFFER_SIZE, BeginReadCallback, null);
}

private static void BeginWriteCallback(IAsyncResult asyncRes)
{
    // Finish writing to destination stream
    destinationStream.EndWrite(asyncRes);
}

.NET 3.5의 경우 및 시도하기 전에 :

MemoryStream1.WriteTo(MemoryStream2);

쉽고 안전 - 원본 출처에서 새로운 스트림 만들기 :

    MemoryStream source = new MemoryStream(byteArray);
    MemoryStream copy = new MemoryStream(byteArray);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top