0

I have a SmartCard project that requires saving 16 bytes each time for wider range of SC readers use, not sure about the bytes size to be saved every time restriction, but i have failed using higher numbers of encoding data using the Identive SCL011 reader, and since not all data comes in 16 multiples, of course some looping and assigning after re-sizing the data should take a place.

so the simplest loop i have come up with is as follows

int Index = 0;
for(int i =0; i < blocksNumber; i++)
{
    byte temp = new byte[16];
    for(int x = 0; x < 16; x++, Index++)
        temp[x] = data[Index];
//and encode/write data to the card
}

or

foreach(var item in blocksList)
{
    byte temp = new byte[16];
    for(int x = 0; x < 16; x++)
        temp[x] = data[Index];
//and encode/write data to the card
}

so, in each time i will have to loop through the data to assign it to the Temp array then encode that data, so my questions are:

  1. it better to for example use Array.Copy and
  2. is it faster than looping within the main loop?
  3. or is there another, faster way?

Edit,,

The updated loop comes with less loops and more readable

            int DestinationIndex = 0;
            int BlockSize = 16;
            int SourceIndex = 0;
            try
            {
                byte[] Data = Encoding.UTF8.GetBytes(txtData.Text.Trim());
                Array.Resize(ref Data, 320);
                for (int i = 0; i < 20; i++, SourceIndex = SourceIndex + 16)
                {
                    byte[] temp = new byte[16];
                    Buffer.BlockCopy(Data, SourceIndex, temp, DestinationIndex, BlockSize);
                    mf.Write(BlocksList[i], temp);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
Ameer Adel
  • 82
  • 1
  • 1
  • 12
  • 3
    Not sure how to interpret your first paragraph –  Feb 17 '16 at 08:46
  • `Encoding`/`LINQ` could be the most elegant solution for such case – Ian Feb 17 '16 at 08:47
  • the question is, i have size restriction and therefore i cant save more than 16bytes each time, so i will have to resize -> loop within the blocks -> loop to get the data in a temp array -> encode – Ameer Adel Feb 17 '16 at 08:48
  • where have you assigned `[Index]` – Carbine Feb 17 '16 at 08:48
  • the Index is just a variable, i have skipped renaming it, its just an example for the outer variable to assign each byte to the next temp array – Ameer Adel Feb 17 '16 at 08:49
  • I'm not quite sure what you're getting at / what your question is, but couldn't you pass in a Stream on one end, and chunk it 16 bytes at a time as you write? – lc. Feb 17 '16 at 08:49
  • To copy into the temp array, I guess you could use `var temp = data.Take(16).ToArray()` using `System.Linq` to eliminate the inner loop. – Georg Patscheider Feb 17 '16 at 08:49
  • Why should `Array.Copy` be faster then your current approach? Even with Linq it would not be "faster" but maybe better readable. In any way there is one point where you have to loop your input-collection so simply go with your current code. – MakePeaceGreatAgain Feb 17 '16 at 08:49
  • thats exactly what i m looking for, a faster more elegant way to copy the data to the temp byte array instead of looping While saving some time. – Ameer Adel Feb 17 '16 at 08:50
  • @HimBromBeere `Array.Copy()` may be faster because it may be implemented in native code using an assembler block copy instruction. – Matthew Watson Feb 17 '16 at 08:50
  • 1
    Possible duplicate of [Any faster way of copying arrays in C#?](http://stackoverflow.com/questions/5099604/any-faster-way-of-copying-arrays-in-c) if your question is _"so my question is it better to for example use Array.Copy and is it faster than looping within the main loop, or is there another, faster way"_. –  Feb 17 '16 at 08:51

1 Answers1

3

Here's how I would do it:

int blockSize = 16;
byte[] data = new byte[blockSize * 1000]; // Just for example.

// Fill data[] somehow.

byte[] buffer = new byte[blockSize];

for (int i = 0; i < data.Length - blockSize; i += blockSize)
{
    Buffer.BlockCopy(data, i, buffer, 0, blockSize);

    // Do something with buffer[];
}

Buffer.BlockCopy() is extremely fast. And you don't need to keep recreating the 16 byte buffer - you can create it once outside the loop.

Note that this code will ignore extra bytes at the end of the input data if it isn't a multiple of the block size.

Also note that for byte arrays, Array.Copy() is probably around the same speed (since it is internally optimised for such things), but Buffer.BlockCopy() probably better describes what you're doing in this particular case.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276