我没有使用CopyTo 获得所有答案,可能使用该应用程序的系统可能尚未升级到 .NET 4.0+。我知道有些人想强迫人们升级,但兼容性也很好。
另一件事,我一开始就不会使用流从另一个流中复制。为什么不这样做:
byte[] bytes = myOtherObject.InputStream.ToArray();
一旦有了字节,就可以轻松地将它们写入文件:
public static void WriteFile(string fileName, byte[] bytes)
{
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (!path.EndsWith(@"\")) path += @"\";
if (File.Exists(Path.Combine(path, fileName)))
File.Delete(Path.Combine(path, fileName));
using (FileStream fs = new FileStream(Path.Combine(path, fileName), FileMode.CreateNew, FileAccess.Write))
{
fs.Write(bytes, 0, (int)bytes.Length);
//fs.Close();
}
}
此代码在我使用.jpg 文件进行测试时有效,但我承认我只将它用于小文件(小于 1 MB)。一个流,流之间无需复制,无需编码,只需写入字节!无需使用StreamReader 使事情过于复杂,如果您已经有一个流,您可以直接使用.ToArray() 转换为bytes!
我可以看到这样做的唯一潜在缺点是,如果您有一个大文件,将其作为流并使用.CopyTo() 或等效项允许FileStream 流式传输它而不是使用字节数组并读取字节一个接一个。因此,这样做可能会更慢。但它不应该窒息,因为 FileStream 的 .Write() 方法处理写入字节,并且一次只执行一个字节,所以它不会阻塞内存,除了 你将不得不有足够的内存将流保存为byte[] 对象。在我使用它的情况下,得到一个OracleBlob,我必须去一个byte[],它足够小,而且,无论如何,我没有可用的流媒体,所以我只是将我的字节发送到我的函数,上面。
使用流的另一种选择是将它与 Jon Skeet 在另一篇文章中的 CopyStream 函数一起使用 - 这只是使用 FileStream 获取输入流并直接从中创建文件。它不像他那样使用File.Create(最初对我来说似乎是个问题,但后来发现它可能只是一个VS错误......)。
/// <summary>
/// Copies the contents of input to output. Doesn't close either stream.
/// </summary>
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8 * 1024];
int len;
while ( (len = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, len);
}
}
public static void WriteFile(string fileName, Stream inputStream)
{
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (!path.EndsWith(@"\")) path += @"\";
if (File.Exists(Path.Combine(path, fileName)))
File.Delete(Path.Combine(path, fileName));
using (FileStream fs = new FileStream(Path.Combine(path, fileName), FileMode.CreateNew, FileAccess.Write)
{
CopyStream(inputStream, fs);
}
inputStream.Close();
inputStream.Flush();
}