어떻게의 내용을 복사 중 하나는 스트림을 다른?
문제
는 가장 좋은 방법은 무엇입하의 내용을 복사 중 하나는 스트림을 다른?있는 표준 유틸리티는 방법에 대한 이?
해결책
습니다.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);