C # byte [] substring? (design)

I load some files asynchronously into an array of large bytes, and I have a callback that fires periodically when some data is added to this array. If I want to give developers the opportunity to use the last piece of data that was added to the array, then ... well, how would I do it? In C ++, I could give them a pointer to something in the middle, and then maybe tell them the number of bytes that were added in the last operation, so that they at least know the piece they should look at. I really don't know if you want to give them a 2nd copy of this data, which is simply wasteful.

I just think if people want to process this data before the file completes the download. Does anyone really want to do this? Or is it a useless feature? I already have a callback when the buffer (the entire array of bytes) is full, and then they can flush it all out without worrying about start and end points ...

+3
source share
7 answers

.NET has a framework that does exactly what you want:

System.ArraySegment .

- , , . indexer, , ArraySegment .

+11

, .

, . ? , - -. , - , , , - ?

+3

"", , , - , #, , . . , , , .

, # . . , : "... #, ".

+1

, , , . : (, , ), , ( , , , ). , , , . , . , , . . , .

+1

OP: . , API - , , , .

, , , . , System.ArraySegment, , . . , , .

System.ArraySegment . , , , - , .

System.Array . , ( ):

public struct MyRecord
{
    ArraySegment<byte> header;
    ArraySegment<byte> data;
}


public class Parser
{
    const int HEADER_SIZE = 10;
    const int HDR_OFS_REC_TYPE = 0;
    const int HDR_OFS_REC_LEN = 4;
    byte[] m_fileData;
    List<MyRecord> records = new List<MyRecord>();

    bool Parse(FileStream fs)
    {
        int fileLen = (int)fs.FileLength;
        m_fileData = new byte[fileLen];
        fs.Read(m_fileData, 0, fileLen);
        fs.Close();
        fs.Dispose();
        int offset = 0;
        while (offset + HEADER_SIZE < fileLen)
        {
            int recType = (int)m_fileData[offset];
            switch (recType) { /*puke if not a recognized type*/ }
            int varDataLen = ((int)m_fileData[offset + HDR_OFS_REC_LEN]) * 256
                     + (int)m_fileData[offset + HDR_OFS_REC_LEN + 1];
            if (offset + varDataLen > fileLen) { /*puke as file has odd bytes at end*/}
            MyRecord rec = new MyRecord();
            rec.header = new ArraySegment(m_fileData, offset, HEADER_SIZE);
            rec.data = new ArraySegment(m_fileData, offset + HEADER_SIZE,   
                          varDataLen);
            records.Add(rec);
            offset += HEADER_SIZE + varDataLen;
        } 
    }
}

ArraySegments , . - MyRecord . MyRecord.header.Array MyRecord.data.Array, , [].

+1

, .

- ?

0

, .

public class ArrayChangedEventArgs : EventArgs {
    public (byte[] array, int start, int length) {
        Array = array;
        Start = start;
        Length = length;
    }
    public byte[] Array { get; private set; }
    public int Start { get; private set; }
    public int Length { get; private set; }
}

// ...
// and in your class:

public event EventHandler<ArrayChangedEventArgs> ArrayChanged;

protected virtual void OnArrayChanged(ArrayChangedEventArgs e)
{
    // using a temporary variable avoids a common potential multithreading issue
    // where the multicast delegate changes midstream.
    // Best practice is to grab a copy first, then test for null

    EventHandler<ArrayChangedEventArgs> handler = ArrayChanged;

    if (handler != null)
    {
        handler(this, e);
    }
}

// finally, your code that downloads a chunk just needs to call OnArrayChanged()
// with the appropriate args

Clients connect to the event and get called when something changes. This is what most client code in .NET expects to have in the API ("call me when something happens"). They can connect to the code with something simple:

yourDownloader.ArrayChanged += (sender, e) =>
    Console.WriteLine(String.Format("Just downloaded {0} byte{1} at position {2}.",
            e.Length, e.Length == 1 ? "" : "s", e.Start));
0
source

Source: https://habr.com/ru/post/1726758/


All Articles