将一个流的内容复制到另一个流的最佳方法是什么?有标准的实用方法吗?
当前回答
MemoryStream有.WriteTo(outstream);
. net 4.0在普通流对象上有. copyto。
net 4.0:
instream.CopyTo(outstream);
其他回答
. net Framework 4引入了新的系统流类的CopyTo方法。IO命名空间。使用此方法,我们可以将一个流复制到不同流类的另一个流。
这里有一个例子。
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/>");
我使用以下扩展方法。当一个流是MemoryStream时,他们优化了重载。
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);
}
如果你想要一个过程复制一个流到其他的一个,尼克张贴是好的,但它是丢失的位置重置,它应该是
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
从。net 4.5开始,就有了流。CopyToAsync方法
input.CopyToAsync(output);
这将返回一个Task,完成后可以继续执行,如下所示:
await input.CopyToAsync(output)
// Code from here on will be run in a continuation.
注意,根据对CopyToAsync调用的位置,后面的代码可能继续也可能不继续在调用它的同一个线程上。
调用await时捕获的SynchronizationContext将决定在哪个线程上执行延续。
此外,这个调用(这是一个可能会改变的实现细节)仍然对读写进行排序(它只是没有在I/O完成时浪费线程阻塞)。
从。net 4.0开始,就有了流。CopyTo方法
input.CopyTo(output);
适用于。net 3.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?因为这个长度可能是不可用的!从文档中可以看出:
如果从Stream派生的类不支持查找,则调用Length、SetLength、Position和Seek会抛出NotSupportedException异常。
实际上,有一种更简单的方法来做流复制。但是请注意,这意味着您可以将整个文件存储在内存中。如果您正在处理数百兆字节或更大的文件,请不要轻率地尝试使用此功能。
public static void CopySmallTextStream(Stream input, Stream output)
{
using (StreamReader reader = new StreamReader(input))
using (StreamWriter writer = new StreamWriter(output))
{
writer.Write(reader.ReadToEnd());
}
}
注意:关于二进制数据和字符编码也可能存在一些问题。
推荐文章
- 如何分裂()一个分隔字符串到一个列表<字符串>
- 如何转换列表<字符串>列表<int>?
- c#对象列表,我如何得到一个属性的和
- 我如何使用IValidatableObject?
- 如何指定最小值,但没有使用范围数据注释属性的最大小数?
- c# vs Java Enum(适合c#新手)
- c#消毒文件名
- 在EF中更新父实体时如何添加/更新子实体
- ASP。NET身份的默认密码散列器-它是如何工作的,它是安全的?
- 如何写一个JSON文件在c# ?
- 静态隐式运算符
- 不区分大小写列表搜索
- 'throw'和'throw new Exception()'的区别
- 不能在lambda表达式中使用ref或out参数
- c# int到字节[]