So I have a list full of integers. These integers are hexadecimals. I would like to convert this list to ASCII Chars. Once that is done I would like to write the ASCII chars to a file. Here is what I have so far:
public byte[] buffer;
public List<int> list= new List<int>(new int[3]);
list[0] = 5445535420; //AKA header[0] represents the hex integers for Test_ where _ is a space
list[1] = 0; // so the char would be null
list[2] = 4a4153; // would be JAS
System.IO.FileStream fs;
fs = new FileStream(filename, FileMode.OpenOrCreate);
if (fs.CanWrite)
{
for (int i=0;i<list.Count();i++)
{
buffer = Encoding.ASCII.GetBytes(list[i].ToString());
Convert.ToChar(header[i]);
fs.Write(buffer, 0, buffer.Length);
}
}
Would this work for you? Hope comments are self-explenatory
int intFromHexLiteral = 0x4a4153;
var hexString = intFromHexLiteral.ToString("X"); // "4A4153"
var hexCharsList = Split(hexString, 2).ToList(); // ["4A", "41", "53"]
var charsArray = hexCharsList
.Select(hexChar => Convert.ToInt32(hexChar, 16)) // [74, 65, 83]
.Select(i => (char) i) // ['J', 'A', 'S']
.ToArray();
var word = new string(charsArray); // "JAS"
private static IEnumerable<string> Split(string str, int chunkSize) =>
Enumerable.Range(0, str.Length / chunkSize)
.Select(i => str.Substring(i * chunkSize, chunkSize));
An integer does not equal the bytes of the ASCII characters. I.e 1010 is not 0x1010 in hex. In your case it would make more sense to use byte[] an write each hex character explicitly.
class Program
{
static void Main(string[] args)
{
List<byte[]> list = new List<byte[]>();
list.Add(new byte[]{0x54, 0x45, 0x53, 0x54, 0x20}); //AKA header[0] represents the hex integers for Test_ where _ is a space
list.Add(new byte[]{0x0}); // so the char would be null
list.Add(new byte[]{ 0x4a, 0x41, 0x53 }); // would be JAS
foreach (var b in list)
{
var chars = Encoding.ASCII.GetChars(b);
var s = new string(chars);
Console.WriteLine(s);
}
}
}
I see that you've selected an answer, but I wanted to show you this method of solving your problem dealing with your data strictly as numeric data. The values you stick into your List<int> are small enough to fit into a long so I changed it to a List<long>. If they ever become bigger than that, than this solution would not work.
See how I broke each long element, byte by byte, in reverse and stored the conversion into a StringBuilder before writing it to the screen. In your case, you would write to a file instead, but could use the same conversion method.
using System;
using System.Collections.Generic;
using System.Text;
public class Program
{
public static void Main(string[] args)
{
List<long> list = new List<long>(new long[3]);
list[0] = 0x5445535420; // AKA header[0] represents the hex integers for Test_ where _ is a space
list[1] = 0; // so the char would be null
list[2] = 0x4a4153; // would be JAS
for (int i = 0; i < list.Count; i++)
{
StringBuilder sb = new StringBuilder();
// Break down each element byte by byte in reverse
while (list[i] > 0)
{
// Anding against 0xFF to only have the least significant byte to convert into a char
sb.Insert(0, Convert.ToChar(list[i] & 0xFF));
list[i] >>= 8; // Remove the least significant byte
}
Console.WriteLine(sb);
}
}
}
Result:
TEST
JAS
I have to do a program that read and image and puts it into a byte array
var Imagenoriginal = File.ReadAllBytes("10M.bmp");
And Divide That byte Array into 3 Diferent Arrays in order to send each one of this new arrays to other computer ( Using Pipes ) to process them there and finally take them back to the origial computer and finally give the result.
But my question Is how do I do an Algorithm able to divide the byte array in three different bytes arrays if the image selected can have diferent size.
Thanks for your help, have a nice day. =)
You can divide length of array, so you have three integers n1, n2 and n3 with all of them summing up to array.Length. Then, this snippet, using LINQ should be of help:
var arr1 = sourceArray.Take(n1).ToArray();
var arr2 = sourceArray.Skip(n1).Take(n2).ToArray();
var arr3 = sourceArray.Skip(n1+n2).Take(n3).ToArray();
Now, in arr1,arr2 and arr3 you will have three parts of your source array. You need to use LINQ, so in the beginning of the code don't forget using System.Linq;.
You can try like this:
public static IEnumerable<IEnumerable<T>> DivideArray<T>(this T[] array, int size)
{
for (var i = 0; i < (float)array.Length / size; i++)
{
yield return array.Skip(i * size).Take(size);
}
}
The call like this:
var arr = new byte[] {1, 2, 3, 4, 5,6};
var dividedArray = arr.DivideArray(3);
Here is a LINQ approach:
public List<List<byte>> DivideArray(List<byte> arr)
{
return arr
.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / 100)
.Select(x => x.Select(v => v.Value).ToList())
.ToList();
}
Have you considered using Streams? You could extend the Stream class to provide the desired behavior, as follows:
public static class Utilities
{
public static IEnumerable<byte[]> ReadBytes(this Stream input, long bufferSize)
{
byte[] buffer = new byte[bufferSize];
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
using (MemoryStream tempStream = new MemoryStream())
{
tempStream.Write(buffer, 0, read);
yield return tempStream.ToArray();
}
}
}
public static IEnumerable<byte[]> ReadBlocks(this Stream input, int nblocks)
{
long bufferSize = (long)Math.Ceiling((double)input.Length / nblocks);
return input.ReadBytes(bufferSize);
}
}
The ReadBytes extension method reads the input Stream and returns its data as a sequence of byte arrays, using the specified bufferSize.
The ReadBlocks extension method calls ReadBytes with the appropriate buffer size, so that the number of elements in the sequence equals nblocks.
You could then use ReadBlocks to achieve what you want:
public class Program
{
static void Main()
{
FileStream inputStream = File.Open(#"E:\10M.bmp", FileMode.Open);
const int nblocks = 3;
foreach (byte[] block in inputStream.ReadBlocks(nblocks))
{
Console.WriteLine("{0} bytes", block.Length);
}
}
}
Note how ReadBytes uses tempStream and read to write in memory the bytes read from the input stream before converting them into an array of bytes, it solves the problem with the leftover bytes mentioned in the comments.
Say I have an array like this:
byte[] arr = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}
Can I somehow iterate through it with elements treated like Uint16? I want to make my application to treat it like {0x1122, 0x3344, 0x5566, 0x7788}.
Tried using as keyword but the compiler woudn't let me:
byte[] bytearray = new byte[10];
UInt16[] uint16array = bytearray as UInt16[];
Is there any way to do it? (without creating another array or casting two bytes into one uint16 every iteration)
this little helper method should help you
public static class helper
{
public static UInt16[] ToUnit16(this byte[] arr)
{
if (arr == null)
return null;
var len = arr.Length;
if ((len % 2) != 0)
throw new ArgumentException("Must divide by 2");
var count = len / 2;
var result = new UInt16[count];
do
{
result[--count] = (UInt16)((arr[--len]) | arr[--len] << 8);
} while (count > 0);
return result;
}
}
No, C# doesn't offer a way to safely reinterpret one object as if it were some different type of object (you can do it with unsafe code, but then the whole assembly winds up "unsafe").
You can use BitConverter.ToUInt16(), or even wrap the byte[] in a MemoryStream and use the BinaryReader.ReadUInt16() method to read from the byte[] object. But judging from the wording of the question, you don't want to use any method like that.
You can do it with unsafe code:
fixed(byte* p = bytearray)
{
ushort* ptr=(ushort*)p;
for(int i = 0; i < bytearray.Length/2; i++)
{
//...
}
}
You cannot cast the entire array like that, at least not in managed code. You can convert this using BitConverter.ToUInt16, like this:
UInt16[] uint16array = Enumerable
.Range(0, arr.Length/2)
.Select(i => BitConverter.ToUInt16(arr, 2*i))
.ToArray();
How to add a byte to the beginning of an existing byte array?
My goal is to make array what's 3 bytes long to 4 bytes. So that's why I need to add 00 padding in the beginning of it.
You can't do that. It's not possible to resize an array. You have to create a new array and copy the data to it:
bArray = AddByteToArray(bArray, newByte);
code:
public byte[] AddByteToArray(byte[] bArray, byte newByte)
{
byte[] newArray = new byte[bArray.Length + 1];
bArray.CopyTo(newArray, 1);
newArray[0] = newByte;
return newArray;
}
As many people here have pointed out, arrays in C#, as well as in most other common languages, are statically sized. If you're looking for something more like PHP's arrays, which I'm just going to guess you are, since it's a popular language with dynamically sized (and typed!) arrays, you should use an ArrayList:
var mahByteArray = new ArrayList<byte>();
If you have a byte array from elsewhere, you can use the AddRange function.
mahByteArray.AddRange(mahOldByteArray);
Then you can use Add() and Insert() to add elements.
mahByteArray.Add(0x00); // Adds 0x00 to the end.
mahByteArray.Insert(0, 0xCA) // Adds 0xCA to the beginning.
Need it back in an array? .ToArray() has you covered!
mahOldByteArray = mahByteArray.ToArray();
Arrays can't be resized, so you need to allocte a new array that is larger, write the new byte at the beginning of it, and use Buffer.BlockCopy to transfer the contents of the old array across.
To prevent recopy the array every time which isn't efficient
What about using Stack
csharp> var i = new Stack<byte>();
csharp> i.Push(1);
csharp> i.Push(2);
csharp> i.Push(3);
csharp> i; { 3, 2, 1 }
csharp> foreach(var x in i) {
> Console.WriteLine(x);
> }
3
2
1
Although internally it creates a new array and copies values into it, you can use Array.Resize<byte>() for more readable code. Also you might want to consider checking the MemoryStream class depending on what you're trying to achieve.
Simple, just use the code below, as I do:
public void AppendSpecifiedBytes(ref byte[] dst, byte[] src)
{
// Get the starting length of dst
int i = dst.Length;
// Resize dst so it can hold the bytes in src
Array.Resize(ref dst, dst.Length + src.Length);
// For each element in src
for (int j = 0; j < src.Length; j++)
{
// Add the element to dst
dst[i] = src[j];
// Increment dst index
i++;
}
}
// Appends src byte to the dst array
public void AppendSpecifiedByte(ref byte[] dst, byte src)
{
// Resize dst so that it can hold src
Array.Resize(ref dst, dst.Length + 1);
// Add src to dst
dst[dst.Length - 1] = src;
}
I think it is a more complete function
/// <summary>
/// add a new byte to end or start of a byte array
/// </summary>
/// <param name="_input_bArray"></param>
/// <param name="_newByte"></param>
/// <param name="_add_to_start_of_array">if this parameter is True then the byte will be added to the beginning of array otherwise
/// to the end of the array</param>
/// <returns>result byte array</returns>
public byte[] addByteToArray(byte[] _input_bArray, byte _newByte, Boolean _add_to_start_of_array)
{
byte[] newArray;
if (_add_to_start_of_array)
{
newArray = new byte[_input_bArray.Length + 1];
_input_bArray.CopyTo(newArray, 1);
newArray[0] = _newByte;
}
else
{
newArray = new byte[_input_bArray.Length + 1];
_input_bArray.CopyTo(newArray, 0);
newArray[_input_bArray.Length] = _newByte;
}
return newArray;
}
I have 3 byte arrays in C# that I need to combine into one. What would be the most efficient method to complete this task?
For primitive types (including bytes), use System.Buffer.BlockCopy instead of System.Array.Copy. It's faster.
I timed each of the suggested methods in a loop executed 1 million times using 3 arrays of 10 bytes each. Here are the results:
New Byte Array using System.Array.Copy - 0.2187556 seconds
New Byte Array using System.Buffer.BlockCopy - 0.1406286 seconds
IEnumerable<byte> using C# yield operator - 0.0781270 seconds
IEnumerable<byte> using LINQ's Concat<> - 0.0781270 seconds
I increased the size of each array to 100 elements and re-ran the test:
New Byte Array using System.Array.Copy - 0.2812554 seconds
New Byte Array using System.Buffer.BlockCopy - 0.2500048 seconds
IEnumerable<byte> using C# yield operator - 0.0625012 seconds
IEnumerable<byte> using LINQ's Concat<> - 0.0781265 seconds
I increased the size of each array to 1000 elements and re-ran the test:
New Byte Array using System.Array.Copy - 1.0781457 seconds
New Byte Array using System.Buffer.BlockCopy - 1.0156445 seconds
IEnumerable<byte> using C# yield operator - 0.0625012 seconds
IEnumerable<byte> using LINQ's Concat<> - 0.0781265 seconds
Finally, I increased the size of each array to 1 million elements and re-ran the test, executing each loop only 4000 times:
New Byte Array using System.Array.Copy - 13.4533833 seconds
New Byte Array using System.Buffer.BlockCopy - 13.1096267 seconds
IEnumerable<byte> using C# yield operator - 0 seconds
IEnumerable<byte> using LINQ's Concat<> - 0 seconds
So, if you need a new byte array, use
byte[] rv = new byte[a1.Length + a2.Length + a3.Length];
System.Buffer.BlockCopy(a1, 0, rv, 0, a1.Length);
System.Buffer.BlockCopy(a2, 0, rv, a1.Length, a2.Length);
System.Buffer.BlockCopy(a3, 0, rv, a1.Length + a2.Length, a3.Length);
But, if you can use an IEnumerable<byte>, DEFINITELY prefer LINQ's Concat<> method. It's only slightly slower than the C# yield operator, but is more concise and more elegant.
IEnumerable<byte> rv = a1.Concat(a2).Concat(a3);
If you have an arbitrary number of arrays and are using .NET 3.5, you can make the System.Buffer.BlockCopy solution more generic like this:
private byte[] Combine(params byte[][] arrays)
{
byte[] rv = new byte[arrays.Sum(a => a.Length)];
int offset = 0;
foreach (byte[] array in arrays) {
System.Buffer.BlockCopy(array, 0, rv, offset, array.Length);
offset += array.Length;
}
return rv;
}
*Note: The above block requires you adding the following namespace at the the top for it to work.
using System.Linq;
To Jon Skeet's point regarding iteration of the subsequent data structures (byte array vs. IEnumerable<byte>), I re-ran the last timing test (1 million elements, 4000 iterations), adding a loop that iterates over the full array with each pass:
New Byte Array using System.Array.Copy - 78.20550510 seconds
New Byte Array using System.Buffer.BlockCopy - 77.89261900 seconds
IEnumerable<byte> using C# yield operator - 551.7150161 seconds
IEnumerable<byte> using LINQ's Concat<> - 448.1804799 seconds
The point is, it is VERY important to understand the efficiency of both the creation and the usage of the resulting data structure. Simply focusing on the efficiency of the creation may overlook the inefficiency associated with the usage. Kudos, Jon.
Many of the answers seem to me to be ignoring the stated requirements:
The result should be a byte array
It should be as efficient as possible
These two together rule out a LINQ sequence of bytes - anything with yield is going to make it impossible to get the final size without iterating through the whole sequence.
If those aren't the real requirements of course, LINQ could be a perfectly good solution (or the IList<T> implementation). However, I'll assume that Superdumbell knows what he wants.
(EDIT: I've just had another thought. There's a big semantic difference between making a copy of the arrays and reading them lazily. Consider what happens if you change the data in one of the "source" arrays after calling the Combine (or whatever) method but before using the result - with lazy evaluation, that change will be visible. With an immediate copy, it won't. Different situations will call for different behaviour - just something to be aware of.)
Here are my proposed methods - which are very similar to those contained in some of the other answers, certainly :)
public static byte[] Combine(byte[] first, byte[] second)
{
byte[] ret = new byte[first.Length + second.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
return ret;
}
public static byte[] Combine(byte[] first, byte[] second, byte[] third)
{
byte[] ret = new byte[first.Length + second.Length + third.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
Buffer.BlockCopy(third, 0, ret, first.Length + second.Length,
third.Length);
return ret;
}
public static byte[] Combine(params byte[][] arrays)
{
byte[] ret = new byte[arrays.Sum(x => x.Length)];
int offset = 0;
foreach (byte[] data in arrays)
{
Buffer.BlockCopy(data, 0, ret, offset, data.Length);
offset += data.Length;
}
return ret;
}
Of course the "params" version requires creating an array of the byte arrays first, which introduces extra inefficiency.
I took Matt's LINQ example one step further for code cleanliness:
byte[] rv = a1.Concat(a2).Concat(a3).ToArray();
In my case, the arrays are small, so I'm not concerned about performance.
If you simply need a new byte array, then use the following:
byte[] Combine(byte[] a1, byte[] a2, byte[] a3)
{
byte[] ret = new byte[a1.Length + a2.Length + a3.Length];
Array.Copy(a1, 0, ret, 0, a1.Length);
Array.Copy(a2, 0, ret, a1.Length, a2.Length);
Array.Copy(a3, 0, ret, a1.Length + a2.Length, a3.Length);
return ret;
}
Alternatively, if you just need a single IEnumerable, consider using the C# 2.0 yield operator:
IEnumerable<byte> Combine(byte[] a1, byte[] a2, byte[] a3)
{
foreach (byte b in a1)
yield return b;
foreach (byte b in a2)
yield return b;
foreach (byte b in a3)
yield return b;
}
I actually ran into some issues with using Concat... (with arrays in the 10-million, it actually crashed).
I found the following to be simple, easy and works well enough without crashing on me, and it works for ANY number of arrays (not just three) (It uses LINQ):
public static byte[] ConcatByteArrays(params byte[][] arrays)
{
return arrays.SelectMany(x => x).ToArray();
}
The memorystream class does this job pretty nicely for me. I couldn't get the buffer class to run as fast as memorystream.
using (MemoryStream ms = new MemoryStream())
{
ms.Write(BitConverter.GetBytes(22),0,4);
ms.Write(BitConverter.GetBytes(44),0,4);
ms.ToArray();
}
public static byte[] Concat(params byte[][] arrays) {
using (var mem = new MemoryStream(arrays.Sum(a => a.Length))) {
foreach (var array in arrays) {
mem.Write(array, 0, array.Length);
}
return mem.ToArray();
}
}
public static bool MyConcat<T>(ref T[] base_arr, ref T[] add_arr)
{
try
{
int base_size = base_arr.Length;
int size_T = System.Runtime.InteropServices.Marshal.SizeOf(base_arr[0]);
Array.Resize(ref base_arr, base_size + add_arr.Length);
Buffer.BlockCopy(add_arr, 0, base_arr, base_size * size_T, add_arr.Length * size_T);
}
catch (IndexOutOfRangeException ioor)
{
MessageBox.Show(ioor.Message);
return false;
}
return true;
}
Can use generics to combine arrays. Following code can easily be expanded to three arrays. This way you never need to duplicate code for different type of arrays. Some of the above answers seem overly complex to me.
private static T[] CombineTwoArrays<T>(T[] a1, T[] a2)
{
T[] arrayCombined = new T[a1.Length + a2.Length];
Array.Copy(a1, 0, arrayCombined, 0, a1.Length);
Array.Copy(a2, 0, arrayCombined, a1.Length, a2.Length);
return arrayCombined;
}
/// <summary>
/// Combine two Arrays with offset and count
/// </summary>
/// <param name="src1"></param>
/// <param name="offset1"></param>
/// <param name="count1"></param>
/// <param name="src2"></param>
/// <param name="offset2"></param>
/// <param name="count2"></param>
/// <returns></returns>
public static T[] Combine<T>(this T[] src1, int offset1, int count1, T[] src2, int offset2, int count2)
=> Enumerable.Range(0, count1 + count2).Select(a => (a < count1) ? src1[offset1 + a] : src2[offset2 + a - count1]).ToArray();
Here's a generalization of the answer provided by #Jon Skeet.
It is basically the same, only it is usable for any type of array, not only bytes:
public static T[] Combine<T>(T[] first, T[] second)
{
T[] ret = new T[first.Length + second.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
return ret;
}
public static T[] Combine<T>(T[] first, T[] second, T[] third)
{
T[] ret = new T[first.Length + second.Length + third.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
Buffer.BlockCopy(third, 0, ret, first.Length + second.Length,
third.Length);
return ret;
}
public static T[] Combine<T>(params T[][] arrays)
{
T[] ret = new T[arrays.Sum(x => x.Length)];
int offset = 0;
foreach (T[] data in arrays)
{
Buffer.BlockCopy(data, 0, ret, offset, data.Length);
offset += data.Length;
}
return ret;
}
All you need to pass list of Byte Arrays and this function will return you the Array of Bytes (Merged).
This is the best solution i think :).
public static byte[] CombineMultipleByteArrays(List<byte[]> lstByteArray)
{
using (var ms = new MemoryStream())
{
using (var doc = new iTextSharp.text.Document())
{
using (var copy = new PdfSmartCopy(doc, ms))
{
doc.Open();
foreach (var p in lstByteArray)
{
using (var reader = new PdfReader(p))
{
copy.AddDocument(reader);
}
}
doc.Close();
}
}
return ms.ToArray();
}
}
Concat is the right answer, but for some reason a handrolled thing is getting the most votes. If you like that answer, perhaps you'd like this more general solution even more:
IEnumerable<byte> Combine(params byte[][] arrays)
{
foreach (byte[] a in arrays)
foreach (byte b in a)
yield return b;
}
which would let you do things like:
byte[] c = Combine(new byte[] { 0, 1, 2 }, new byte[] { 3, 4, 5 }).ToArray();