c# - "Where are my bytes?"或文件长度特征调查

标签 c# size byte

这是我关于 downloading files in chunks 问题的延续.解释会很大,所以我会尽量把它分成几个部分。

1)我试图做什么?

我正在为 Window-Phone 应用程序创建一个下载管理器。首先我尝试解决下载的问题
大文件(解释在上一个问题中)。不,我想添加“可恢复下载”功能。

2)我已经做过的事情。

目前我有一个运行良好的下载管理器,它可以超越 Windows Phone 的 RAM 限制。
这个管理器的特点是,它允许使用 HTTP Range header 下载小块文件。

对其工作原理的快速解释:

该文件以恒定大小的块下载。我们称这个大小为“delta”。下载文件块后,
它以追加模式保存到本地存储(硬盘,在 WP 上称为隔离存储)(因此,下载的字节数组是
总是添加到文件的末尾)。下载单个块后的语句

if (mediaFileLength >= delta) // mediaFileLength is a length of downloaded chunk

被检查。如果是真的,那
意味着,还有一些东西可供下载,并且这个方法被递归调用。否则就意味着,这个块
是最后一个,没有什么可以下载了。

3)有什么问题?

直到我在一次性下载时使用了这个逻辑(一次性我的意思是,当您开始下载文件并等待下载完成时)
效果很好。但是,我决定,我需要“恢复下载”功能。 所以,事实:

3.1) 我知道,文件块大小是一个常数。

3.2) 我知道,当文件完全下载与否。 (这是我的应用程序逻辑的间接结果,
不会因解释而使您厌烦,只是假设这是事实)

在这两个陈述的假设下,我可以证明,下载的块数等于
(CurrentFileLength)/delta .其中 CurrentFileLenght 是已下载文件的大小(以字节为单位)。

要继续下载文件,我应该简单地设置所需的标题并调用下载方法。这似乎是逻辑,不是吗?我试图实现它:
    // Check file size
    using (IsolatedStorageFileStream fileStream = isolatedStorageFile.OpenFile("SomewhereInTheIsolatedStorage", FileMode.Open, FileAccess.Read))
    {
      int currentFileSize = Convert.ToInt32(fileStream.Length);
      int currentFileChunkIterator = currentFileSize / delta;
    }

我看到的结果是什么?下载的文件长度等于 2432000 字节( delta 是 304160 ,总文件大小约为 4,5 MB ,我们只下载了其中的一半)。所以结果是
大约 7,995 . (它实际上是 long/int 类型,所以它是 7,而应该是 8!)为什么会发生这种情况?
简单的数学告诉我们,文件长度应该是 2433280 ,所以给定的值非常接近,但不相等。

进一步的调查表明,所有值都来自 fileStream.Length不准确,但都接近。

为什么会这样? 我不知道确切,但也许 .Length 值是从文件元数据中获取的。
也许,这种四舍五入对于这种方法来说是正常的。也许,当下载中断时,文件没有完全保存......(不,那真的很棒,不可能)

所以问题就解决了 - 它是 “如何确定下载的块数” .问题是如何解决。

4)我对解决问题的想法。

我的第一个想法是在这里使用数学。设置一些 epsilon-neiborhood 并在 currentFileChunkIterator = currentFileSize / delta; 中使用它声明。
但这将要求我们记住第一类和第二类错误(或者误报和错过,如果您不喜欢统计术语。)也许,没有什么可以下载的了。
另外,我没有检查,如果提供的值和真​​实值的差异应该永久增长
否则会出现周期性波动。对于小尺寸(大约 4-5 MB),我只看到了增长,但这并不能证明什么。

所以,我在这里寻求帮助,因为我不喜欢我的解决方案。

5) 我想听到的答案是:

是什么导致了实际值(value)和接收值(value)之间的差异?

有没有办法获得真正的值(value)?

如果没有,我的解决方案是否适合这个问题?

还有其他更好的解决方案吗?

附言我不会设置 Windows-Phone 标签,因为我不确定这个问题是否与操作系统有关。我使用了隔离存储工具
检查下载文件的大小,它向我显示与收到的值相同(我很抱歉截图中的俄语):

File size is wrong image

最佳答案

我正在回答您的更新:

到目前为止,这是我的理解:实际写入文件的长度(四舍五入到下一个 1KiB)比您实际写入文件的长度要长。这会导致您对“file.Length == 下载量”的假设是错误的。

一种解决方案是单独跟踪此信息。创建一些元数据结构(可以使用相同的存储机制持久化)以准确跟踪已下载的块以及文件的整个大小:

[DataContract] //< I forgot how serialization on the phone works, please forgive me if the tags differ
struct Metadata
{
     [DataMember]
     public int Length;
     [DataMember]
     public int NumBlocksDownloaded;
}

假设您继续以连续方式下载它们,这足以重建哪些块已被下载,哪些块尚未下载。

编辑

当然,在将数据写入流之前,您必须将代码从简单的追加更改为将流的位置移动到正确的块:
 file.Position = currentBlock * delta;
 file.Write(block, 0, block.Length);

关于c# - "Where are my bytes?"或文件长度特征调查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14848786/

相关文章:

c# - 字符串的实际长度

image - 适用于 iOS 的必应搜索 API

Delphi 开发人员的 C# 标准/风格?

c# - 在 C# 中获取内核时间

c# - 使用 C# WebBrowser 时是否可以检测到调用的任何 javascript 函数

html - 保持子元素的字体大小不受根元素字体大小的影响

用于以字节为单位返回文件大小的 VBA Excel 函数

c# - 什么使 Min(byte,int) 调用不明确?

c++ - 将位数组转换为短

c# - 从 Expression<Func<TModel,TProperty>> 获取字符串形式的属性