HomeSearch

C# Buffer BlockCopy Example

Use methods on the Buffer type, including Buffer.BlockCopy and ByteLength.

Buffer.

The Buffer type handles ranges of bytes. It includes the optimized Buffer.BlockCopy method. This copies a range of bytes from one array to another.

Buffer methods.

The Buffer class also provides the ByteLength, GetByte and SetByte methods. Usually BlockCopy is the most interesting.

BlockCopy.

To begin, Buffer.BlockCopy does not copy logical elements in arrays. Instead it copies bytes. We call it to copy the bytes in one byte array to another.

Note: This is useful for compression, images, or many other types of binary data.

Byte

Here: The ints are actually used as bytes, not 4-byte ints. The byte array arr2 is automatically initialized to all zero bytes.

Byte Array
C# program that uses BlockCopy on bytes using System; class Program { static void Main() { byte[] arr1 = new byte[] { 1, 2, 3, 4, 5 }; byte[] arr2 = new byte[10]; // Copy the first five bytes from arr1 to arr2 Buffer.BlockCopy(arr1, 0, arr2, 0, 5); Display(arr2); } static void Display(byte[] arr) { for (int i = 0; i < arr.Length; i++) { Console.Write(arr[i]); } Console.WriteLine(); } } Output 1234500000

Example 2.

Buffer.BlockCopy can act on a data type that is not 1 byte. An int is 4 bytes. The fifth parameter of Buffer.BlockCopy is the number of bytes to copy.

Note: We need to pass in the number of bytes to copy, not the array element count. We must multiply it by 4, or the sizeof(int).

Note 2: In this example, the sizeof() operator returns the byte length of a primitive data type like int. Here it returns 4.

And: The multiplication of sizeof(int) * 4 can be resolved by the C# compiler—it won't cause any slowdowns.

C# program that copies ints using System; class Program { static void Main() { int[] arr1 = new int[] { 1, 2, 3, 4, 5 }; int[] arr2 = new int[10]; // Copy the first twenty bytes from arr1 to arr2 Buffer.BlockCopy(arr1, 0, arr2, 0, 5 * sizeof(int)); Display(arr2); } static void Display(int[] arr) { for (int i = 0; i < arr.Length; i++) { Console.Write(arr[i]); } Console.WriteLine(); } } Output 1234500000

Benchmark.

To test Buffer.BlockCopy further, I benchmarked it on a 1000-element array. I found it has a significant performance advantage over Array.Copy.

Also: Copying the elements in a for-loop was far slower. So using BlockCopy is a significant win.

Array.CopyFor
Method that returns byte arrays: C# static byte[] GetSourceArray() { // [Note] You can populate data here return new byte[_len]; } Code that copies byte arrays: C# const int _len = 1000; Buffer.BlockCopy(source, 0, target, 0, _len); Array.Copy(source, target, _len); Benchmark results: Buffer.BlockCopy: 1113 ms [faster] Array.Copy: 1343 ms

Notes, benchmark.

The benchmark tested an array of 1000 random byte values, but these did not affect behavior in any way, as expected. The code here doesn't include that part.

ByteLength.

ByteLength returns the byte count for an array. In this example there are 2 arrays—an integer array and a byte array—allocated on the managed heap.

Note: We use Buffer.ByteLength to count the total number of bytes in each array. Each int is 4 bytes. Each byte is a single byte.

C# program that uses Buffer.ByteLength method using System; class Program { static void Main() { // Example arrays for program. // ... Each array has three elements. int[] array1 = { 1, 2, 3 }; byte[] array2 = { 1, 2, 3 }; // Get lengths of arrays. // ... This counts the bytes in all elements. int length1 = Buffer.ByteLength(array1); int length2 = Buffer.ByteLength(array2); // Write results. Console.WriteLine(length1); Console.WriteLine(length2); } } Output 12 3

Internally,

the Buffer.ByteLength method accesses external code in the .NET Framework. The Buffer class uses lower-level methods such as memcpy. This can provide performance advantages.

Note: The Buffer.ByteLength method likely uses some lower-level functions in native code to compute the byte length.

In earlier releases

of the .NET Framework, sizeof was limited to unsafe code contexts. Buffer.ByteLength could provide a way for element sizes to be computed without using sizeof.

However: In current .NET releases, the sizeof operator is available in all contexts for value types. It evaluates to a constant.

Tip: ByteLength is useful when you want to encode an array of value types as an array of bytes directly.

Also: Please see the BitConverter class for information on how you can change representations of value types.

BitConverter

GetByte, SetByte.

Next we use Buffer.GetByte and SetByte. We have an array of 3 integer values (an int array). Note that integers (int variables) in C# code are represented by 4 bytes.Int ArrayInt, uint

Note: By using GetByte and SetByte, we read and assign the individual bytes in each integer directly.

Tip: This changes the decimal representation of the integer by changing the bytes in the integer.

And: This is used to treat an integer array as a bitmask or other structure. One bit is used to indicate true or false.

True, False
C# program that uses Buffer.GetByte and Buffer.SetByte using System; class Program { static void Main() { // Use an array of three integers for testing. // ... Loop through the bytes in the array and write their values. int[] array1 = { 1, 1, 256 }; for (int i = 0; i < Buffer.ByteLength(array1); i++) { Console.WriteLine(Buffer.GetByte(array1, i)); } // Set certain byte values at indexes in the array. Buffer.SetByte(array1, 0, 55); Buffer.SetByte(array1, 4, 55); Buffer.SetByte(array1, 8, 55); // Render the modified array. Console.WriteLine("---"); for (int i = 0; i < Buffer.ByteLength(array1); i++) { Console.WriteLine(Buffer.GetByte(array1, i)); } } } Output 1 0 0 0 1 0 0 0 0 1 0 0 --- 55 0 0 0 55 0 0 0 55 1 0 0

Notes, memory.

In the .NET Framework, arrays are stored in a single memory region and this is on the managed heap. GetByte and SetByte act upon this region.

Tip: You can read and manipulate data in an array memory region just by indexes.

Tip 2: These methods are implemented in C or C++, and this is faster for operations on large arrays.

A summary.

The Buffer type contains low-level methods that act upon bytes. A buffer is a range of bytes. With BlockCopy, we optimize large array copies of value types.OptimizationArray
Home
Dot Net Perls
© 2007-2019 Sam Allen. All rights reserved. Written by Sam Allen, info@dotnetperls.com.