流-内容长度

时间:2018-09-24 18:51:27

标签: c#

是否无法获取流当前保存的内容的长度?

我以为Length可以给我我想要的东西,但是在我的测试中却没有。

public class Solution {

    public static void Main(string[] args)
    {
        var raw = new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5 };
        using (var stream = new MemoryStream(3)) {
            long size = stream.Length;              // Actual 0, expected 0
            long capacity = stream.Capacity;        // Actual 3, expected 3
            long position = stream.Position;        // Actual 0, expected 0

            stream.Write(raw, 0, raw.Length);
            size = stream.Length;                   // Actual 6, expected 6
            capacity = stream.Capacity;             // Actual 256, expected big enough to hold content
            position = stream.Position;             // Actual 6, expected 6

            var buffer = new byte[1];
            stream.Read(buffer, 0, 1);
            size = stream.Length;                   // Actual 6, expected 5
            capacity = stream.Capacity;             // Actual 256, expected same as before
            position = stream.Position;             // Actual 6, expected 5

            stream.Write(raw, 0, raw.Length);
            size = stream.Length;                   // Actual 12, expected 11
            capacity = stream.Capacity;             // Actual 256, expected same as before
            position = stream.Position;             // Actual 12, expected 11

            stream.Seek(0, 0);
            size = stream.Length;                   // Actual 12, expected 11
            position = stream.Position;             // Actual 0, expected 0
        }
    }
}

我希望读取结果将大小减小1。显然不会。这就提出了一个问题,如果字节保留在内存中并且报告的长度包括读取的字节,那么何时将其从内存中删除? (我们不能永远积累!)如何获取当前内容的长度? (写入的总字节数-读取的总字节数)?

编辑: 我已经知道,如果您不向后搜索,该位置将在第一次写入时保留在流的末尾。共享位置以进行读写。但是,其他问题仍然存在。

2 个答案:

答案 0 :(得分:0)

在c#中,

  

Stream是所有流的抽象基类。流是字节序列的抽象,例如文件,输入/输出设备,进程间通信管道或TCP / IP套接字。 Stream类及其派生类提供了这些不同类型的输入和输出的通用视图,并将程序员与操作系统和基础设备的特定细节区分开来。 read MS source

您应该注意,它不是StackQueue的抽象。这很可能是在实施过程中实际使用的概念,但这没有意义。但是重要的是

  

流涉及三个基本操作:

     
      
  • 您可以从流中读取。读取是将数据从流传输到数据结构(例如字节数组)中。

  •   
  • 您可以写入流。写入是将数据从数据结构传输到流中。

  •   
  • 流可以支持搜索。搜寻是指查询和修改流中的当前位置。搜寻能力取决于流具有的后备存储类型。例如,网络流没有当前位置的统一概念,因此通常不支持搜索。

  •   

从流中读取时您实际上在做什么

  

将流中.Position中指定数量的项目写入缓冲区中,从缓冲区中的给定位置开始

这意味着Stream的内容在被读取后仍保留在Stream中。只是对Flush的调用才能清除Stream see MS docs

中的缓冲数据

获取Position给出了流中如果调用stream.Write( … )stream.Read( … )将从下一个读/写操作开始的位置。设置Position可以设置流中从下一个调用开始的位置。

     const int numberOfBytesToRead = 2;
     const int streamStart = 0;
     using (var stream = new MemoryStream(3))
     {
        Debug.Assert(stream.Length == 0);
        Debug.Assert(stream.Capacity == 3);
        Debug.Assert(stream.Position == 0);
        stream.Write(raw, 0, raw.Length);

        Debug.Assert(stream.Length == raw.Length);
        Debug.Assert(stream.Position == 6);

        stream.Position = streamStart;
        Debug.Assert(stream.Position == 0);
        var buffer = new byte[numberOfBytesToRead];
        var bytesRead = stream.Read(buffer, 0, buffer.Length);

        Debug.Assert(bytesRead == numberOfBytesToRead);
        Debug.Assert(stream.Length == raw.Length);
        Debug.Assert(stream.Position == numberOfBytesToRead);

        stream.Write(raw, 0, raw.Length);
        Debug.Assert(stream.Length == raw.Length+numberOfBytesToRead);
        Debug.Assert(stream.Position == raw.Length + numberOfBytesToRead);
        stream.Position = raw.Length;

        buffer = new byte[numberOfBytesToRead];
        stream.Read(buffer, 0, buffer.Length);

        var builder = new StringBuilder("|");
        foreach (var item in buffer)
           builder.Append($"{item}|");

        Debug.Assert(builder.ToString().Equals("|5|6|"));

        builder = new StringBuilder("|");
        buffer = new byte[numberOfBytesToRead+raw.Length];
        stream.Position = streamStart;
        stream.Read(buffer, 0, buffer.Length);

        foreach (var item in buffer)
           builder.Append($"{item}|");

        Debug.Assert(builder.ToString().Equals("|1|2|1|2|3|4|5|6|"));
     }

答案 1 :(得分:-1)

想要保留字节的声音,您可以通过简单的数学运算获得。

def fibo(n):
    print(1)
    counter = 1
    old_num = 0
    new_num = 1
    sum_fib = 1
    while counter < n:
        fib = old_num + new_num
        print(fib)

        if counter < n:
            old_num = new_num
            new_num = fib
            sum_fib = sum_fib + fib
            counter = counter + 1

    print('sum:' + str(sum_fib))


#fibo(5)