FileStreaming 背后的原理
Principles behind FileStreaming
我最近在做一个涉及很多FileStreaming
的项目,这是我以前没有真正接触过的。
为了尝试更好地了解这些方法的原理,我编写了一些代码(理论上)将文件从一个 dir
下载到另一个,并逐步完成,评论我对什么的理解每一步都实现了,就像这样...
从 DownloadRequest 对象获取文件信息对象
RemoteFileInfo fileInfo = svr.DownloadFile(request);
WCF 服务中的 DownloadFile 方法
public RemoteFileInfo DownloadFile(DownloadRequest request)
{
RemoteFileInfo result = new RemoteFileInfo(); // create empty fileinfo object
try
{
// set filepath
string filePath = System.IO.Path.Combine(request.FilePath , @"\" , request.FileName);
System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath); // get fileinfo from path
// check if exists
if (!fileInfo.Exists)
throw new System.IO.FileNotFoundException("File not found",
request.FileName);
// open stream
System.IO.FileStream stream = new System.IO.FileStream(filePath,
System.IO.FileMode.Open, System.IO.FileAccess.Read);
// return result
result.FileName = request.FileName;
result.Length = fileInfo.Length;
result.FileByteStream = stream;
}
catch (Exception ex)
{
// do something
}
return result;
}
使用从 fileinfo 返回的 FileStream 读入新的写入流
// set new location for downloaded file
string basePath = System.IO.Path.Combine(@"C:\SST Software\DSC\Compilations\" , compName, @"\");
string serverFileName = System.IO.Path.Combine(basePath, file);
double totalBytesRead = 0.0;
if (!Directory.Exists(basePath))
Directory.CreateDirectory(basePath);
int chunkSize = 2048;
byte[] buffer = new byte[chunkSize];
// create new write file stream
using (System.IO.FileStream writeStream = new System.IO.FileStream(serverFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
do
{
// read bytes from fileinfo stream
int bytesRead = fileInfo.FileByteStream.Read(buffer, 0, chunkSize);
totalBytesRead += (double)bytesRead;
if (bytesRead == 0) break;
// write bytes to output stream
writeStream.Write(buffer, 0, bytesRead);
} while (true);
// report end
Console.WriteLine(fileInfo.FileName + " has been written to " + basePath + " - Done!");
writeStream.Close();
}
我所希望的是对使用 FileStream
时到底发生了什么的任何澄清或扩展。
我可以实现下载,现在我知道我需要编写什么代码才能执行这样的下载,但我想知道更多关于 为什么 它有效的信息。我在网上找不到 'beginner-friendly' 或分步说明。
幕后发生了什么?
流只是一种抽象,从根本上说,它就像数据集合中的指针一样工作。
以"Hello World!"的例子字符串为例,它只是字符的集合,本质上就是字节。
作为流,它可以表示为:
- 长度为 12(可能更多,包括终止字符等)
- 流中的位置。
您通过移动位置和请求数据来读取流。
所以阅读上面的文字(在伪代码中)可能是这样的:
do
get next byte
add gotten byte to collection
while not the end of the stream
the entire data is now in the collection
在从文件系统或远程机器等来源访问数据时,流确实有用。
想象一个大小为几千兆字节的文件,如果 OS 在程序想要读取它(比如视频播放器)时将所有文件加载到内存中,就会出现很多问题.
相反,程序请求访问文件,OS returns 一个流;流告诉程序有多少数据,并允许它访问该数据。
根据实现的不同,OS 可能会在程序访问它之前将一定数量的数据加载到内存中,这被称为 缓冲区。
但从根本上说,程序只是请求下一位数据,OS 要么从缓冲区获取数据,要么从源(例如磁盘上的文件)获取数据。
相同的原则适用于不同计算机之间的流,除了请求下一位数据很可能涉及到远程机器请求它。
.NET FileStream
class 和 Stream
基础 class,最终都只是遵从 windows 系统来处理流,它们并没有什么特别之处,只是你可以用抽象来做些什么,使它们如此强大。
写入流是一样的,只是将数据放入缓冲区,以供请求者访问。
无限数据
正如用户指出的,流可用于不确定长度的数据。
所有流操作都需要时间,因此读取流通常是一个阻塞操作,会等待数据可用。
因此您可以在流仍然打开时一直循环,并等待数据进入 - 实际中的一个例子是实时视频广播。
我找到了一本书 - C# 5.0 All-In-One For Dummies - 它解释了所有 Stream
类 的一切,它们是如何工作的,哪一个是最合适的等等。
才读了大概30分钟,就已经有了这样的理解。
优秀的向导!
我最近在做一个涉及很多FileStreaming
的项目,这是我以前没有真正接触过的。
为了尝试更好地了解这些方法的原理,我编写了一些代码(理论上)将文件从一个 dir
下载到另一个,并逐步完成,评论我对什么的理解每一步都实现了,就像这样...
从 DownloadRequest 对象获取文件信息对象
RemoteFileInfo fileInfo = svr.DownloadFile(request);
WCF 服务中的 DownloadFile 方法
public RemoteFileInfo DownloadFile(DownloadRequest request)
{
RemoteFileInfo result = new RemoteFileInfo(); // create empty fileinfo object
try
{
// set filepath
string filePath = System.IO.Path.Combine(request.FilePath , @"\" , request.FileName);
System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath); // get fileinfo from path
// check if exists
if (!fileInfo.Exists)
throw new System.IO.FileNotFoundException("File not found",
request.FileName);
// open stream
System.IO.FileStream stream = new System.IO.FileStream(filePath,
System.IO.FileMode.Open, System.IO.FileAccess.Read);
// return result
result.FileName = request.FileName;
result.Length = fileInfo.Length;
result.FileByteStream = stream;
}
catch (Exception ex)
{
// do something
}
return result;
}
使用从 fileinfo 返回的 FileStream 读入新的写入流
// set new location for downloaded file
string basePath = System.IO.Path.Combine(@"C:\SST Software\DSC\Compilations\" , compName, @"\");
string serverFileName = System.IO.Path.Combine(basePath, file);
double totalBytesRead = 0.0;
if (!Directory.Exists(basePath))
Directory.CreateDirectory(basePath);
int chunkSize = 2048;
byte[] buffer = new byte[chunkSize];
// create new write file stream
using (System.IO.FileStream writeStream = new System.IO.FileStream(serverFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
do
{
// read bytes from fileinfo stream
int bytesRead = fileInfo.FileByteStream.Read(buffer, 0, chunkSize);
totalBytesRead += (double)bytesRead;
if (bytesRead == 0) break;
// write bytes to output stream
writeStream.Write(buffer, 0, bytesRead);
} while (true);
// report end
Console.WriteLine(fileInfo.FileName + " has been written to " + basePath + " - Done!");
writeStream.Close();
}
我所希望的是对使用 FileStream
时到底发生了什么的任何澄清或扩展。
我可以实现下载,现在我知道我需要编写什么代码才能执行这样的下载,但我想知道更多关于 为什么 它有效的信息。我在网上找不到 'beginner-friendly' 或分步说明。
幕后发生了什么?
流只是一种抽象,从根本上说,它就像数据集合中的指针一样工作。
以"Hello World!"的例子字符串为例,它只是字符的集合,本质上就是字节。
作为流,它可以表示为:
- 长度为 12(可能更多,包括终止字符等)
- 流中的位置。
您通过移动位置和请求数据来读取流。
所以阅读上面的文字(在伪代码中)可能是这样的:
do
get next byte
add gotten byte to collection
while not the end of the stream
the entire data is now in the collection
在从文件系统或远程机器等来源访问数据时,流确实有用。
想象一个大小为几千兆字节的文件,如果 OS 在程序想要读取它(比如视频播放器)时将所有文件加载到内存中,就会出现很多问题.
相反,程序请求访问文件,OS returns 一个流;流告诉程序有多少数据,并允许它访问该数据。
根据实现的不同,OS 可能会在程序访问它之前将一定数量的数据加载到内存中,这被称为 缓冲区。
但从根本上说,程序只是请求下一位数据,OS 要么从缓冲区获取数据,要么从源(例如磁盘上的文件)获取数据。
相同的原则适用于不同计算机之间的流,除了请求下一位数据很可能涉及到远程机器请求它。
.NET FileStream
class 和 Stream
基础 class,最终都只是遵从 windows 系统来处理流,它们并没有什么特别之处,只是你可以用抽象来做些什么,使它们如此强大。
写入流是一样的,只是将数据放入缓冲区,以供请求者访问。
无限数据
正如用户指出的,流可用于不确定长度的数据。
所有流操作都需要时间,因此读取流通常是一个阻塞操作,会等待数据可用。
因此您可以在流仍然打开时一直循环,并等待数据进入 - 实际中的一个例子是实时视频广播。
我找到了一本书 - C# 5.0 All-In-One For Dummies - 它解释了所有 Stream
类 的一切,它们是如何工作的,哪一个是最合适的等等。
才读了大概30分钟,就已经有了这样的理解。
优秀的向导!