将一个流的内容复制到另一个流的最佳方法是什么?有标准的实用方法吗?
当前回答
实际上,有一种更简单的方法来做流复制。但是请注意,这意味着您可以将整个文件存储在内存中。如果您正在处理数百兆字节或更大的文件,请不要轻率地尝试使用此功能。
public static void CopySmallTextStream(Stream input, Stream output)
{
using (StreamReader reader = new StreamReader(input))
using (StreamWriter writer = new StreamWriter(output))
{
writer.Write(reader.ReadToEnd());
}
}
注意:关于二进制数据和字符编码也可能存在一些问题。
其他回答
可能有一种方法可以更有效地做到这一点,这取决于您处理的是哪种流。如果可以将一个或两个流转换为MemoryStream,则可以使用GetBuffer方法直接处理表示数据的字节数组。这让你可以使用像Array这样的方法。CopyTo,它抽象了fryguybob提出的所有问题。你可以相信. net知道复制数据的最佳方式。
从。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异常。
简单安全-从原始来源制作新流:
MemoryStream source = new MemoryStream(byteArray);
MemoryStream copy = new MemoryStream(byteArray);
实际上,有一种更简单的方法来做流复制。但是请注意,这意味着您可以将整个文件存储在内存中。如果您正在处理数百兆字节或更大的文件,请不要轻率地尝试使用此功能。
public static void CopySmallTextStream(Stream input, Stream output)
{
using (StreamReader reader = new StreamReader(input))
using (StreamWriter writer = new StreamWriter(output))
{
writer.Write(reader.ReadToEnd());
}
}
注意:关于二进制数据和字符编码也可能存在一些问题。
不幸的是,没有真正简单的解决办法。你可以尝试这样做:
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();
但问题是,如果没有什么可读取的,Stream类的不同实现可能会有不同的行为。从本地硬盘读取文件的流可能会阻塞,直到读操作从磁盘读取了足够的数据来填充缓冲区,并且只有在到达文件末尾时才返回较少的数据。另一方面,从网络读取的流可能返回更少的数据,即使有更多的数据需要接收。
在使用通用解决方案之前,一定要检查您正在使用的特定流类的文档。
推荐文章
- 防止在ASP中缓存。NET MVC中使用属性的特定操作
- 转换为值类型'Int32'失败,因为物化值为空
- c#中有任何连接字符串解析器吗?
- 在Linq中转换int到字符串到实体的问题
- 是否可以动态编译和执行c#代码片段?
- 创建自定义MSBuild任务时,如何从c#代码获取当前项目目录?
- c#和Java的主要区别是什么?
- 在c#中创建一个特定时区的DateTime
- .NET中的属性是什么?
- csproj文件中的“Service Include”是干什么用的?
- 如何使用try catch进行异常处理是最佳实践
- 替换字符串中第一次出现的模式
- .NET中字节的字面后缀?
- 如何处理AccessViolationException
- c#忽略证书错误?