How to combine two byte arrays [duplicate] - java

This question already has answers here:
Easy way to concatenate two byte arrays
(13 answers)
Closed 4 years ago.
I have two byte arrays and I am wondering how I would go about adding one to the other or combining them to form a new byte array.

You're just trying to concatenate the two byte arrays?
byte[] one = getBytesForOne();
byte[] two = getBytesForTwo();
byte[] combined = new byte[one.length + two.length];
for (int i = 0; i < combined.length; ++i)
{
combined[i] = i < one.length ? one[i] : two[i - one.length];
}
Or you could use System.arraycopy:
byte[] one = getBytesForOne();
byte[] two = getBytesForTwo();
byte[] combined = new byte[one.length + two.length];
System.arraycopy(one,0,combined,0 ,one.length);
System.arraycopy(two,0,combined,one.length,two.length);
Or you could just use a List to do the work:
byte[] one = getBytesForOne();
byte[] two = getBytesForTwo();
List<Byte> list = new ArrayList<Byte>(Arrays.<Byte>asList(one));
list.addAll(Arrays.<Byte>asList(two));
byte[] combined = list.toArray(new byte[list.size()]);
Or you could simply use ByteBuffer with the advantage of adding many arrays.
byte[] allByteArray = new byte[one.length + two.length + three.length];
ByteBuffer buff = ByteBuffer.wrap(allByteArray);
buff.put(one);
buff.put(two);
buff.put(three);
byte[] combined = buff.array();

You can do this by using Apace common lang package (org.apache.commons.lang.ArrayUtils class ). You need to do the following
byte[] concatBytes = ArrayUtils.addAll(one,two);

I think it is best approach,
public static byte[] addAll(final byte[] array1, byte[] array2) {
byte[] joinedArray = Arrays.copyOf(array1, array1.length + array2.length);
System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
return joinedArray;
}

The simplest method (inline, assuming a and b are two given arrays):
byte[] c = (new String(a, cch) + new String(b, cch)).getBytes(cch);
This, of course, works with more than two summands and uses a concatenation charset, defined somewhere in your code:
static final java.nio.charset.Charset cch = java.nio.charset.StandardCharsets.ISO_8859_1;
Or, in more simple form, without this charset:
byte[] c = (new String(a, "l1") + new String(b, "l1")).getBytes("l1");
But you need to suppress UnsupportedEncodingException which is unlikely to be thrown.
The fastest method:
public static byte[] concat(byte[] a, byte[] b) {
int lenA = a.length;
int lenB = b.length;
byte[] c = Arrays.copyOf(a, lenA + lenB);
System.arraycopy(b, 0, c, lenA, lenB);
return c;
}

String temp = passwordSalt;
byte[] byteSalt = temp.getBytes();
int start = 32;
for (int i = 0; i < byteData.length; i ++)
{
byteData[start + i] = byteSalt[i];
}
The problem with your code here is that the variable i that is being used to index the arrays is going past both the byteSalt array and the byteData array. So, Make sure that byteData is dimensioned to be at least the maximum length of the passwordSalt string plus 32. What will correct it is replacing the following line:
for (int i = 0; i < byteData.length; i ++)
with:
for (int i = 0; i < byteSalt.length; i ++)

Assuming your byteData array is biger than 32 + byteSalt.length()...you're going to it's length, not byteSalt.length. You're trying to copy from beyond the array end.

I've used this code which works quite well just do appendData and either pass a single byte with an array, or two arrays to combine them :
protected byte[] appendData(byte firstObject,byte[] secondObject){
byte[] byteArray= {firstObject};
return appendData(byteArray,secondObject);
}
protected byte[] appendData(byte[] firstObject,byte secondByte){
byte[] byteArray= {secondByte};
return appendData(firstObject,byteArray);
}
protected byte[] appendData(byte[] firstObject,byte[] secondObject){
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
try {
if (firstObject!=null && firstObject.length!=0)
outputStream.write(firstObject);
if (secondObject!=null && secondObject.length!=0)
outputStream.write(secondObject);
} catch (IOException e) {
e.printStackTrace();
}
return outputStream.toByteArray();
}

Related

How to read and write Bytes without skipping the zeros in Java

Does anyone know how to input or output bytes without skipping the zeros
I am trying to write a program that exports an array of ints to unsigned shorts.
I have written code to write and read wave files, but they aren't formatted right.
Read Example
// dwChunkSize
byteConvertedLong = extractBytes(4);
dwFormatChunkSize = convertBytesToLong(byteConvertedLong);
System.out.println("Format Chunk size: " + dwFormatChunkSize);
// wFormatTag
byteConvertedInt = extractBytes(2);
System.out.println("Format Tag: " + convertBytesToInt(byteConvertedInt));
functions for reading data:
// convert byte to long
public long convertBytesToLong(byte[] values) {
byte[] spliceToArray = {0, 0, 0, 0,
values[0], values[1], values[2], values[3]};
ByteBuffer debuffer = ByteBuffer.wrap(spliceToArray);
long returnValue = (long)debuffer.getLong();
return returnValue;
}
// convert byte to int
public int convertBytesToInt(byte[] values) {
byte[] spliceToArray = {0, 0, values[0], values[1]};
ByteBuffer debuffer = ByteBuffer.wrap(spliceToArray);
int returnValue = debuffer.getInt();
return returnValue;
}
// extract bytes to DataOutputStream
public byte[] extractBytes(int bytesToExtract)
throws IOException {
// define byte array
byte[] extractedBytes = new byte[bytesToExtract];
// extract bytes
dis.read(extractedBytes, byteTracker, bytesToExtract);
return extractedBytes;
}
Write example
// dwChunkSize
byteConvertedLong = convertLongToBytes(dwFormatChunkSize);
appendBytes(byteConvertedLong, 4, 8);
// wFormatTag
byteConvertedInt = convertIntToByte(W_FORMAT_TAG);
appendBytes(byteConvertedInt, 2, 4);
Functions for writing;
// convert long to byte
public byte[] convertLongToBytes(long value) {
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putLong(value);
return buffer.array();
}
// convert int to byte
public byte[] convertIntToByte(int value) {
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.putInt(value);
return buffer.array();
}
// append bytes to DataOutputStream
public void appendBytes(byte[] bytesToAppend, int start, int end)
throws IOException {
for (int i = start; i < end; i++) {
dos.writeByte(bytesToAppend[i]);
}
}
I have to use Long and int variabls to read and write ints and shorts respectively so that they are written as unsigned numbers.
I have been following instructions on this site https://blogs.msdn.microsoft.com/dawate/2009/06/23/intro-to-audio-programming-part-2-demystifying-the-wav-format/ to make sure all the data is formatted right
The main problem with both reading and writing is that if I read 1 as a short (0000000000000001), it will skip the zeros and start reading from 1 (10000000000000000).
If that isn't the problem I don't know what is?
It turned out that Wave files are written in little endian and I was writing in big endian. I needed to implement a function that reversed the bytes of the byte array.
I came up with this.
// bigToLittleEndien method
public byte[] bigToLittleEndien(byte[] oldArray) {
// new array
byte[] newArray = new byte[oldArray.length];
// reverse the order of byes
for (int i = 0, j = oldArray.length - 1; i < oldArray.length; i++, j--) {
newArray[i] = oldArray[j];
}
// return the new bytes
return newArray;
}
I had some other problems that were small but I fixed them all.

How to convert this Python code into Java?

I wish to convert following python code into Java. This code encodes credit card data using hash algorithms and keys. I have written some Java code based on my understanding below that. I think mainly its about panmackey. I am not sure how to generate its value for Java.
Python Code:
panmackey = bytes.fromhex('449E5A196233A43819A028770880E814DC420BFFC428295787302E6285FDD685')
def pandgstsha(track2, pan_mac_key=panmackey):
h = hmac.HMAC(pan_mac_key, hashes.SHA256(), backend=default_backend())
h. (bytes(track2.split('=')[0]+track2.split('=')[1][:4],'UTF-8'))
return base64.b64encode(h.finalize())
Java code:
String tokenPan = ccNum + expiryStr;
String panmackey= "?????????????????????";//pan_mac_key from python code
Mac mac = Mac.getInstance("HmacSHA512");
byte[] decodedBytes = Base64.decodeBase64(panmackey.getBytes("UTF-16LE"));
SecretKeySpec sk = new SecretKeySpec(decodedBytes, mac.getAlgorithm());
mac.init(sk);
byte[] resultBase64 = Base64.encodeBase64(mac.doFinal(tokenPan.getBytes("ASCII")));
String sB64 = new String(resultBase64, "UTF-8");
I need to figure out panmackey and if the 2 codes do exactly same function.
Your best bet would be to use:
https://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/binary/Hex.html
import org.apache.commons.codec.binary.Hex;
...
byte[] panmackey= Hex.decodeHex("Hex string goes here");
Otherwise, you'll have to implement your own conversion function like this;
public static byte[] hexStringToByteArray(String hex) {
byte[] decoded = new byte[hex.length() / 2];
for (int i = 0; i < b.length; i++) {
int index = i * 2;
int value = Integer.parseInt(hex.substring(index, index + 2), 16);
decoded[i] = (byte) value;
}
return decoded;
}

concatenate long and bytearray to another bytearray

I am trying to concatenate long and bytearray to another bytearray.
I tried like this :
byte[] value1= new byte[16];
byte[] value2= new byte[16];
byte[] finalvalue = new byte[value1.length + value2.length];
long ts = System.currentTimeMillis();
int val = 100;
ByteBuffer.wrap(value1).order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().put(ts);
ByteBuffer.wrap(value2).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer().put(val);
System.arraycopy(value1, 0, finalvalue, 0, value1.length);
System.arraycopy(value2, 0, finalvalue, value1.length,value2.length);
When I tried to print this, I am not getting the correct values. It printing like this
BYTEVALUE -95-15-4410659100000000002000000000000000
it should print like this
- BYTEVALUE- 1354707038625,100
Can anyone help me out where I am going wrong.
Help will be appreciated.
Update:
Use to print values using StringBuffer like this:
StringBuffer sb = new StringBuffer(finalvalue.length);
for (int i = 0; i < finalvalue.length; i++) {
sb.append(finalvalue[i]);
}
Your code is not doing what you think it is. Consider the following self-contained application:
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class ByteArrayTest {
public static void main(String[] args) {
byte[] value1 = new byte[16];
byte[] value2 = new byte[16];
byte[] finalvalue = new byte[value1.length + value2.length];
long ts = System.currentTimeMillis();
int val = 100;
ByteBuffer.wrap(value1).order(ByteOrder.LITTLE_ENDIAN).asLongBuffer()
.put(ts);
ByteBuffer.wrap(value2).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer()
.put(val);
System.arraycopy(value1, 0, finalvalue, 0, value1.length);
System.arraycopy(value2, 0, finalvalue, value1.length, value2.length);
printByteArray(finalvalue);
}
private static void printByteArray(final byte[] array) {
StringBuilder sb = new StringBuilder(array.length);
for (byte b : array) {
sb.append(String.format("%02X", b));
}
System.out.println(sb.toString());
}
}
The output of this is:
BE26086B3B010000000000000000000064000000000000000000000000000000
Splitting this into component parts, we can see why:
The first sixteen bytes are BE26086B3B0100000000000000000000. This is your timestamp in little endian order. If you ignore the zero bytes, this converts to 1,354,710,394,558 in decimal, which is correct.
The second sixteen bytes are 64000000000000000000000000000000, which is your hard-coded value 100.
The zeroes represent the space in the byte arrays that you didn't use.

How to convert byte[] to Byte[] and the other way around?

How to convert byte[] to Byte[] and also Byte[] to byte[], in the case of not using any 3rd party library?
Is there a way to do it fast just using the standard library?
byte[] to Byte[] :
byte[] bytes = ...;
Byte[] byteObject = ArrayUtils.toObject(bytes);
Byte[] to byte[] :
Byte[] byteObject = new Byte[0];
byte[] bytes = ArrayUtils.toPrimitive(byteObject);
Byte class is a wrapper for the primitive byte. This should do the work:
byte[] bytes = new byte[10];
Byte[] byteObjects = new Byte[bytes.length];
int i=0;
// Associating Byte array values with bytes. (byte[] to Byte[])
for(byte b: bytes)
byteObjects[i++] = b; // Autoboxing.
....
int j=0;
// Unboxing Byte values. (Byte[] to byte[])
for(Byte b: byteObjects)
bytes[j++] = b.byteValue();
Java 8 solution:
Byte[] toObjects(byte[] bytesPrim) {
Byte[] bytes = new Byte[bytesPrim.length];
Arrays.setAll(bytes, n -> bytesPrim[n]);
return bytes;
}
Unfortunately, you can't do this to convert from Byte[] to byte[]. Arrays has setAll for double[], int[], and long[], but not for other primitive types.
You could use the toPrimitive method in the Apache Commons lang library ArrayUtils class,
As suggested here - Java - Byte[] to byte[]
byte[] toPrimitives(Byte[] oBytes)
{
byte[] bytes = new byte[oBytes.length];
for(int i = 0; i < oBytes.length; i++){
bytes[i] = oBytes[i];
}
return bytes;
}
Inverse:
//byte[] to Byte[]
Byte[] toObjects(byte[] bytesPrim) {
Byte[] bytes = new Byte[bytesPrim.length];
int i = 0;
for (byte b : bytesPrim) bytes[i++] = b; //Autoboxing
return bytes;
}
From byte[] to Byte[]:
byte[] b = new byte[]{1,2};
Byte[] B = new Byte[b.length];
for (int i = 0; i < b.length; i++)
{
B[i] = Byte.valueOf(b[i]);
}
From Byte[] to byte[] (using our previously-defined B):
byte[] b2 = new byte[B.length];
for (int i = 0; i < B.length; i++)
{
b2[i] = B[i];
}
If someone preferes Stream API over ordinary loops.
private Byte[] toObjects(byte[] bytes) {
return IntStream.range(0, bytes.length)
.mapToObj(i -> bytes[i])
.toArray(Byte[]::new);
}
Step back. Look at the bigger picture. You're stuck converting byte[] to Byte[] or vice versa because of Java's strict type casing with something like this
List< Byte>
or
List<Byte[]>
Now you have byte[] and Byte[] and have to convert. This will help.
Keep all your byte[]s in a list like this: List<byte[]> instead of List< Byte> or List<Byte[]>. (byte is a primitive, byte[] is an object)
As you acquire bytes do this (networking socket example):
ArrayList<byte[]> compiledMessage = new ArrayList<byte[]>;
...
compiledMessage.add(packet.getData());
Then, when you want to put all your bytes in a single message, do this:
byte[] fromListOfNotByteArray (List<byte[]> list) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(list);
} catch (IOException e) {
e.printStackTrace();
}
return baos.toByteArray();
}
That way, you can keep all your parts in List<byte[]> and your whole in byte[] without a bunch of crazy copy tasks in for loops with little baby byte[]s everywhere. ;)
Now you know -- teach others.
Since Java 8:
byte[] bytes = new bytes[byteObject.length];
IntStream.range(0, byteObject.length).forEach(x -> bytes [x] = byteObject[x]);

Hex-encoded String to Byte Array

String str = "9B7D2C34A366BF890C730641E6CECF6F";
I want to convert str into byte array, but str.getBytes() returns 32 bytes instead of 16.
I think what the questioner is after is converting the string representation of a hexadecimal value to a byte array representing that hexadecimal value.
The apache commons-codec has a class for that, Hex.
String s = "9B7D2C34A366BF890C730641E6CECF6F";
byte[] bytes = Hex.decodeHex(s.toCharArray());
Java SE 6 or Java EE 5 provides a method to do this now so there is no need for extra libraries.
The method is DatatypeConverter.parseHexBinary
In this case it can be used as follows:
String str = "9B7D2C34A366BF890C730641E6CECF6F";
byte[] bytes = DatatypeConverter.parseHexBinary(str);
The class also provides type conversions for many other formats that are generally used in XML.
Use:
str.getBytes("UTF-16LE");
I know it's late but hope it will help someone else...
This is my code: It takes two by two hex representations contained in String and add those into byte array.
It works perfectly for me.
public byte[] stringToByteArray (String s) {
byte[] byteArray = new byte[s.length()/2];
String[] strBytes = new String[s.length()/2];
int k = 0;
for (int i = 0; i < s.length(); i=i+2) {
int j = i+2;
strBytes[k] = s.substring(i,j);
byteArray[k] = (byte)Integer.parseInt(strBytes[k], 16);
k++;
}
return byteArray;
}
That should do the trick :
byte[] bytes = toByteArray(Str.toCharArray());
public static byte[] toByteArray(char[] array) {
return toByteArray(array, Charset.defaultCharset());
}
public static byte[] toByteArray(char[] array, Charset charset) {
CharBuffer cbuf = CharBuffer.wrap(array);
ByteBuffer bbuf = charset.encode(cbuf);
return bbuf.array();
}
try this:
String str = "9B7D2C34A366BF890C730641E6CECF6F";
String[] temp = str.split(",");
bytesArray = new byte[temp.length];
int index = 0;
for (String item: temp) {
bytesArray[index] = Byte.parseByte(item);
index++;
}
I assume what you need is to convert a hex string into a byte array that equals that means the same thing as that hex string?
Adding this method should do it for you, without any extra library importing:
public static byte[] hexToByteArray(String s) {
String[] strBytes = s.split("(?<=\\G.{2})");
byte[] bytes = new byte[strBytes.length];
for(int i = 0; i < strBytes.length; i++)
bytes[i] = (byte)Integer.parseInt(strBytes[i], 16);
return bytes;
}

Categories

Resources