"我的字节在哪里?" 或调查文件长度特征

Olt*_*ter 12 c# size byte

这是我关于以块的形式下载文件的问题的延续.解释会很大,所以我会尝试将它分成几个部分.

1)我试图做什么?

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

2)我已经做了什么.

目前,我有一个运行良好的下载管理器,可以包含Windows Phone RAM限制.这个管理器的情节是,它允许使用HTTP Range标头下载小块文件.

快速解释它的工作原理:

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

if (mediaFileLength >= delta) // mediaFileLength is a length of downloaded chunk
Run Code Online (Sandbox Code Playgroud)

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

3)有什么问题?

直到我在一次性下载时使用这个逻辑(我的意思是,一次性开始下载文件并等到下载完成后),这种方式运行良好.但是,我决定,我需要"简历下载" 功能.所以,事实:

3.1)我知道,文件块大小是一个常量.

3.2)我知道,文件完全下载与否.(这是我的app逻辑的间接结果,不会因为解释而疲惫不堪,只是假设,这是事实)

假设这两个语句我可以证明,下载的块的数量等于 (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;
    }
Run Code Online (Sandbox Code Playgroud)

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

进一步调查显示,所有值fileStream.Length都是不准确的,但都是接近的.

为什么会这样?我不确切地知道,但也许,.Length值取自文件元数据.也许,这种舍入对于这种方法是正常的.也许,当下载被中断时,文件没有被完全保存......(不,这真是太棒了,它不可能)

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

4)我对解决问题的看法.

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

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

5)我想听到的答案是:

是什么导致实际价值和收益价值之间的差异?

有没有办法获得真正的价值?

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

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

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

文件大小是错误的图像

Olt*_*ter 0

您听说过关于一个菜鸟程序员和 10 个大师程序员的轶事吗?大师级程序员试图在他的解决方案中找到一个错误,菜鸟已经发现了它,但没有告诉它,因为这是一件很愚蠢的事情,我们害怕被嘲笑。

为什么我记得这个?因为情况相似。

对我的问题的解释非常繁重,我决定不提及一些我确信可以正常工作的小方面。(而且它们确实工作正常)

其中一个小方面是,下载的文件是通过 AES PKCS7 填充加密的。嗯,解密是正确的,我知道,那我为什么要提它呢?但我没有。

所以,然后我试图找出到底是什么导致了最后一个块的错误。最可信的版本是关于缓冲问题的,我试图找到我在哪里留下了丢失的字节。我一次又一次地测试,但我找不到它们,因为每一块都在保存,没有任何损失。有一天我明白了:

没有勺子

没有错误。

AES PKCS7 有什么意义?嗯,第一个是它使解密的文件更小。不多,只有16字节。而且我的解密方法和下载方法中都考虑到了,所以应该没有问题吧?

但是,当下载过程中断时会发生什么?最后一个块将正确保存,不会出现缓冲或其他错误。然后我们要继续下载。下载的块的数量将等于currentFileChunkIterator = currentFileSize / delta;

在这里我应该问自己:“你为什么要做那么愚蠢的事情?”

“您下载的一个块大小不是 delta。实际上,它小于 delta”。(解密后块会缩小到 16 个字节,还记得吗?)

Delta 本身由 10 个相等的部分组成,正在解密。因此,我们不应除以 delta,而应除以(delta - 16 * 10),即 (304160 - 160) = 304000

我感觉到这里有一只老鼠。让我们尝试找出下载的块的数量:

2432000 / 304000 = 8.等等...哦Shi~


那么,故事就这样结束了。

整个解决方案的逻辑是正确的。

它失败的唯一原因是我的想法,由于某种原因,下载的解密文件大小应该与下载的加密块的总和相同。

当然,由于我没有提到解密(仅在上一个问题中提到过,仅链接),所以你们都无法给我正确的答案。对此我感到非常抱歉。