【问题标题】:Anticipate the file size of on writing memorystream to file预测将内存流写入文件时的文件大小
【发布时间】:2021-11-28 05:39:13
【问题描述】:

我想在将文件写入设备之前预测文件的确切大小,以便在相应驱动器中没有空间的情况下处理错误或防止崩溃。所以我有这个简单的控制台脚本,它生成文件:

using System;
using System.IO;

namespace myNamespace
{
     class Program
    {
        static void Main(string[] args) {
            byte[] myByteArray = new byte[100];
            MemoryStream stream = new MemoryStream();
            string fileName = "E:\\myFile.mine";
            FileStream myFs = new FileStream(fileName, FileMode.CreateNew);
            BinaryWriter toStreamWriter = new BinaryWriter(stream);

            BinaryWriter toFileWriter = new BinaryWriter(myFs, System.Text.Encoding.ASCII);
            myFs.Write(myByteArray, 0, myByteArray.Length);

            for (int i = 0; i < 30000; i++) {
                toStreamWriter.Write(i);
            }

            Console.WriteLine($"allocated memory: {stream.Capacity}" );
            Console.WriteLine($"stream lenght {stream.Length}");
            Console.WriteLine($"file size: {(stream.Length / 4) * 4.096 }");

            toFileWriter.Write(stream.ToArray());

            Console.ReadLine();
        }
    }
}

当我开始预测文件的大小时,我就明白了。 我将是 stream.Length / 4) * 4.096,但只要 stream.Length / 4 的 raminder 为 0。 以流加13589个整数为例

for (int i = 0; i < 13589; i++) {
    toStreamWriter.Write(i);
}

我知道脚本中的文件大小为 55660,544 字节,但在资源管理器中为 57344 字节。

与添加的整数是 14000 而不是 13589 的结果相同。

stream.Length / 4 的余数不为 0 时,我如何预测我创建的文件的确切大小?

编辑:对于运行脚本的潜在助手,您需要在每次运行脚本时删除创建的文件!当然使用您选择的路径和文件名:)

关于stream.Length / 4) * 4.096 的关系,4 表示字节大小,我猜 4.096 来自数组和文件生成,但任何进一步的解释将不胜感激。

Edit2:检查是否记录了待处理的结果:

for (int i = 13589; i <= 14000; i++) {
    Console.WriteLine($"result for {i} : {(i*4 / 4) * 4.096} ");
}

您获得:

....
result for 13991 : 57307,136
result for 13992 : 57311,232
result for 13993 : 57315,328
result for 13994 : 57319,424
result for 13995 : 57323,52
result for 13996 : 57327,616
result for 13997 : 57331,712
result for 13998 : 57335,808
result for 13999 : 57339,904
result for 14000 : 57344

所以我假设文件大小适合下一个集群 + byteStream 大小,没有小数提示。这个文件大小设置逻辑对文件大小的参与是否有意义?如果流也很大?

【问题讨论】:

  • 你的最终目标是不可能的。请记住,文件具有文件大小和磁盘大小。通常是不同的。请记住,您的进程可能不是唯一运行的进程。这意味着其他进程将写入磁盘并更改检查与您实际将文件写入磁盘之间的剩余磁盘空间。处理空间不足,写入函数抛出异常。
  • 旁注:写入 MemoryStream 然后 一个我们通常不希望的文件(并且还施加了人为的大小限制);即使你这样做:不要使用ToArray();有像 TryGetBufferCopyTo 这样的 API 比 ToArray() 更可取
  • @sbecker 感谢您的建议。运行的其他进程将用于空间可用性问题,这不是我要问的。我的最终目标是将问题放在上下文中。另一方面,当stream.Length / 4) raminder 为0 时,可以分别使用stream.Length / 4stream.Length / 4) * 4.096 预测不同的文件大小和磁盘大小,而c# 以某种方式设置它,所以我不认为具有这两种大小并且不同与我所要求的可行性有关,即对创建的文件大小的预期
  • 您是想计算出您的文件将占用多少磁盘集群,还是想计算出文件将占用多少字节?
  • @sbecker 顺便说一句,我打算将您的句柄应用到空间之外,但写入函数提案引发了异常:)

标签: c# memory binary


【解决方案1】:

根据我对 cme​​ts 的了解,问题是关于如何获取文件的实际文件大小。不是磁盘上的文件大小。而且您的代码实际上几乎是正确的。

数学很基础。在您的示例中,您创建了一个文件流并将一个 100 字节长的数组写入文件流。然后创建内存流并将 30000 个整数写入内存流。然后将内存流写入文件流。考虑到这里的每个整数都是 4 字节长,按照 C# 的规定,生成的文件的文件大小为 (30000 * 4) + 100 = 120100 字节。至少对我来说,这正是 Windows 资源管理器中文件属性所说的内容。

您可以使用以下代码更轻松地获得相同的结果:

FileStream myFs = new FileStream("test.file", FileMode.CreateNew);
byte[] myByteArray = new byte[100];
myFs.Write(myByteArray, 0, myByteArray.Length);

BinaryWriter toFileWriter = new BinaryWriter(myFs, System.Text.Encoding.ASCII);
for (int i = 0; i < 30000; i++)
{
    toFileWriter.Write(i);
}

Console.WriteLine($"stream lenght {myFs.Length}");
myFs.Close();

这将返回 120100 字节的流长度。

如果我误解了您的问题和 cmets,而您实际上是在尝试获取磁盘上的文件大小: 不要去那里。由于环境多变,您无法可靠地预测磁盘上的文件大小。比如文件压缩、加密、各种RAID类型、各种文件系统、各种磁盘类型、各种操作系统。

【讨论】:

  • 感谢您的回答。所以猜测我提到的逻辑似乎被应用于获取文件大小(适合下一个集群的文件大小 + 没有小数提醒的 byteStream 大小)没有用....
猜你喜欢
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多