Tôi không nhận được tất cả các câu trả lời bằng cách sử dụng CopyTo
, trong đó có thể các hệ thống sử dụng ứng dụng có thể chưa được nâng cấp lên .NET 4.0+. Tôi biết một số người muốn buộc mọi người nâng cấp, nhưng khả năng tương thích cũng rất tốt.
Một điều nữa, tôi không được sử dụng một luồng để sao chép từ một luồng khác ở nơi đầu tiên. Tại sao không làm:
byte[] bytes = myOtherObject.InputStream.ToArray();
Khi bạn có các byte, bạn có thể dễ dàng ghi chúng vào một tệp:
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();
}
}
Mã này hoạt động như tôi đã kiểm tra nó với một .jpg
tệp, mặc dù tôi thừa nhận tôi chỉ sử dụng nó với các tệp nhỏ (dưới 1 MB). Một luồng, không sao chép giữa các luồng, không cần mã hóa, chỉ cần viết các byte! Không cần quá phức tạp hóa mọi thứ với StreamReader
nếu bạn đã có một luồng bạn có thể chuyển đổi bytes
trực tiếp với .ToArray()
!
Chỉ có nhược điểm tiềm năng mà tôi có thể thấy khi thực hiện theo cách này là nếu bạn có một tệp lớn, có nó dưới dạng luồng và sử dụng .CopyTo()
hoặc tương đương cho phép FileStream
truyền phát thay vì sử dụng một mảng byte và đọc từng byte một. Kết quả có thể chậm hơn theo cách này. Nhưng nó không nên bị nghẹt vì .Write()
phương thức FileStream
xử lý ghi byte và nó chỉ thực hiện một byte mỗi lần, vì vậy nó sẽ không làm tắc bộ nhớ, ngoại trừ việc bạn sẽ phải có đủ bộ nhớ để giữ luồng như một byte[]
đối tượng . Trong tình huống của tôi khi tôi sử dụng nó, nhận được một OracleBlob
, tôi đã phải đi đến mộtbyte[]
, nó đủ nhỏ, và bên cạnh đó, dù sao cũng không có luồng phát nào cho tôi, vì vậy tôi chỉ gửi các byte của mình cho hàm của tôi, ở trên.
Một tùy chọn khác, sử dụng một luồng, sẽ là sử dụng nó với CopyStream
chức năng của Jon Skeet trong một bài đăng khác - điều này chỉ sử dụng FileStream
để lấy luồng đầu vào và tạo tệp trực tiếp từ nó. Nó không sử dụng File.Create
, giống như anh ta đã làm (điều này ban đầu có vẻ là vấn đề đối với tôi, nhưng sau đó thấy nó có khả năng chỉ là một lỗi 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();
}