byte to int conversion & vice versa java - java

I am trying to convert a integer into byte and retrieving the integer back in my code.
code:
ByteArrayOutputStream barrayStream = null;
DataOutputStream outputStream = null;
try {
initSequence();
barrayStream = new ByteArrayOutputStream();
outputStream = new DataOutputStream(barrayStream);
outputStream.writeByte(4);
outputStream.writeInt(xxxx);
System.out.println(" String = "
+ Arrays.toString(barrayStream.toByteArray()));
handlePacket(barrayStream.toByteArray());
}catch (IOException ie) {
ie.printStackTrace();
} finally {
try {
if (barrayStream != null) {
barrayStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
void handlePacket(byte[] byteArray) throws IOException {
byte[] portArray = new byte[4];
System.arraycopy(byteArray, 1, portArray, 0, 4);
int byteToIntValue = 0;
for (int i = 0; i < portArray.length; i++) {
byteToIntValue = (byteToIntValue << 8) | portArray[i];
}
System.out.println("Port Number = " + byteToIntValue);
}
integer greater than 5120 gives the correct value while retrieving. But below 5119 gives the negative value
Is there any specific reason for this. Any help will be appreciated.
output: for integer 5100 the output is
[0, 0, 19, -20]
for integer greater than 5120
[0, 0, 20, 0]

Try this:
Byte to int:
Byte b = new Byte(rno[0]);
int i = b.intValue();
int to byte:
int i = 234;
byte b = (byte) i;
A byte is always signed in Java. You may get its unsigned value by binary-anding it with 0xFF, though:

This is happening because a Java byte is a signed value, between -128 and 127. You're parsing the port number correctly. It's just when you use Arrays.toString that the bytes get displayed as signed numbers.

Related

java.lang.NumberFormatException: Value out of range. Value:"8C" Radix:16 while converting from String to byte[] [duplicate]

This question already has answers here:
Why does Byte.parseByte("80", 16) fail?
(2 answers)
why Java throws a NumberFormatException
(3 answers)
Closed 1 year ago.
Getting the following error from following code. What I am trying to achieve is printing a series of hex code to a file as bytes itself. How do I fix it, So that I can print 8C in the file
public static void process() {
System.out.println("File to print");
String hexString = "418C";
try {
byte value[] = getByte(hexString);
try (FileOutputStream outputStream = new FileOutputStream(filePath)) {
outputStream.write(value);
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
private static byte[] getByte(String str) {
byte[] val = new byte[str.length() / 2];
for (int i = 0; i < val.length; i++) {
int index = i * 2;
byte byt = Byte.parseByte(str.substring(index, index + 2), 16);
val[i] = byt;
}
return val;
}
Exception
java.lang.NumberFormatException: Value out of range. Value:"8C" Radix:16
at java.base/java.lang.Byte.parseByte(Byte.java:154)
Based on the following link, I changed to Character.MAX_RADIX, but getting another error.
https://www.tutorialspoint.com/java/lang/byte_parsebyte_radix.htm
The following link was helpful
Why does Byte.parseByte("80", 16) fail?
Byte.parseByte(str, 16) expects signed input. You can write Byte.parseByte("-1", 16), for example, because -1 fits into Java byte type, but not Byte.parseByte("80", 16), because 128 does not fit into Java byte type.
You can replace Byte.parseByte(str.substring(index, index + 2), 16) with (byte) Integer.parseInt(str.substring(index, index + 2), 16) and it'll work fine.
If you're using Java 17, you can use java.util.HexFormat.of().parseHex(hexString) instead of getByte(hexString).
You can use a int to convert and truncate it down to 8 bit length. Look at the two lines in getByte which do the convertion.
public class Temp {
public static void process() {
System.out.println("File to print");
String hexString = "418C";
byte value[] = getByte(hexString);
for(byte v: value) {
System.out.printf("v: %2x\t", v);
}
}
private static byte[] getByte(String str) {
byte[] val = new byte[str.length() / 2];
for (int i = 0; i < val.length; i++) {
int index = i * 2;
int byt = Integer.parseInt(str.substring(index, index + 2), 16);
val[i] = (byte) (byt & 0xff);
}
return val;
}
public static void main(String[] args) {
process();
}
}
The output is
File to print
v: 41 v: 8c

Caused by: java.lang.StringIndexOutOfBoundsException: length=7; index=7 Android java

Hi i use function to hex string to byte array and it gives me this error sometimes it works some times it gives error
Caused by: java.lang.StringIndexOutOfBoundsException: length=7;index=7 > at java.lang.String.indexAndLength(String.java:500)
at java.lang.String.charAt(String.java:494)
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len/2];
for(int i = 0; i < len; i+=2){
data[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
}
return data;
}
error comes in this code and
why it works most of the time and only sometimes it makes application force close,can anybody fix this so that it can work always
i use this function above to make crc32 checsum to bytearray
here is the function i use to get crc32 checsum
private String chesum() {
String fileName = "file.bin";
try {
CheckedInputStream cis = null;
try {
// Compute CRC32 checksum
cis = new CheckedInputStream(
new FileInputStream(fileName), new CRC32());
} catch (FileNotFoundException e) {
System.err.println("File not found.");
}
byte[] buf = new byte[128];
while(cis.read(buf) >= 0) {
}
long checksum = cis.getChecksum().getValue();
String ss = Long.toHexString(checksum);
cis.close();
return ss;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
after this method i call hexstringtobytearray function
for(int i = 0; i < len-1 ; i+=2){
data[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
}
Change the condition len to len -1

Quickest way to get bytes from type long

this is
Long number = 0x001122334455667788L;
i need create byte[] of last 6 bytes of Long.
So its will be look like
byte[] bytes = {0x22,0x33,0x44,0x55,0x66,0x77,0x88};
What is the right way to make something like this?
Thanks for any responnse
byte[] buffer = new byte[6];
buffer[0] = (byte)(v >>> 40);
buffer[1] = (byte)(v >>> 32);
buffer[2] = (byte)(v >>> 24);
buffer[3] = (byte)(v >>> 16);
buffer[4] = (byte)(v >>> 8);
buffer[5] = (byte)(v >>> 0);
That's how DataOutputStream.writeLong() does (except it writes all the bytes, or course)
You can use a ByteBuffer
Long number = 0x001122334455667788L;
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putLong(number);
byte[] full = buffer.array();
byte[] shorter = Arrays.copyOfRange(full, 2, 8); // get only the lower 6
How about using DataOutputStream?
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // This will be handy.
DataOutputStream os = new DataOutputStream(baos);
try {
os.writeLong(number); // Write our number.
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
os.close(); // close it.
} catch (IOException e) {
e.printStackTrace();
}
}
return Arrays.copyOfRange(baos.toByteArray(), 2, 8); // Copy out the last 6 elements.
A BigInteger will do it too.
BigInteger number = new BigInteger("001122334455667788", 16);
byte[] b = number.toByteArray();
// May need to tweak the `b.length - 6` if the number is less than 6 bytes long.
byte[] shortened = Arrays.copyOfRange(b, b.length - 6, b.length);
System.out.println(Arrays.toString(shortened));
java.lang.BigInteger toByteArray()

I'm generating a SHA256 hash of few files and some of them return 63 characters instead of 64. How can it be possible?

I need the hash function always to return 64 char hex but sometimes, depending on a file, it returns 63 and that's a problem for me. Due to business reasons I need always 64 chars. And that happens completely random with Any kind and size of file. Does anyone know why it happens? Follow my code:
public static String geraHash(File f) throws NoSuchAlgorithmException, FileNotFoundException
{
MessageDigest digest = MessageDigest.getInstance("SHA-256");
InputStream is = new FileInputStream(f);
byte[] buffer = new byte[8192];
int read = 0;
String output = null;
try
{
while( (read = is.read(buffer)) > 0)
{
digest.update(buffer, 0, read);
}
byte[] md5sum = digest.digest();
BigInteger bigInt = new BigInteger(1,md5sum);
output = bigInt.toString(16);
}
catch(IOException e)
{
throw new RuntimeException("Não foi possivel processar o arquivo.", e);
}
finally
{
try
{
is.close();
}
catch(IOException e)
{
throw new RuntimeException("Não foi possivel fechar o arquivo", e);
}
}
return output;
}
In fact, there is 32 byte. Just first half of first byte is zero. (first byte looks like: 0000 xxxx)
So, when you are converting it to string, it has 63 hex value which is 31.5 bytes, so it is 32 bytes in bytes. This (32 byte) is exactly what it should to be.
You can just write 0 start of string when its length is 63.
if (output.length == 63){
output = "0" + output;
}
or
while (output.length < 64){
output = "0" + output;
}

Converting a Hex String to an image file [duplicate]

This question already has answers here:
Convert a string representation of a hex dump to a byte array using Java?
(25 answers)
Closed 5 years ago.
I have a requirement to read a Hex String with leading zeros which represents a JPEG file, from an xml file received and save it as an image file. The image data looks like
0000005000000050FF191818FF151715FF111413FF0E1...........................FF2A2322FF292221
In xml file The length of String between the tag is 51216 I read the Hex data in between the Photo tag as a String and Converted it to a byte[], and the using a FileOutputStream I am writing to a file. But when I try to open the image file it tells "the file appears to be damaged,corrupted or file is too large" I have tried many methods to save the image, but no success. I am listing the methods used below. Please help me out from this.
String photo="0000005000000050FF191818FF15"; //this is just a sample.The photo String actually contains the full Hex String which is 51216 long
//METHOD 1
String[] v = photo.split(" ");
byte[] arr = new byte[v.length];
int x = 0;
for(String val: v) {
arr[x++] = Integer.decode("0x" + val).byteValue();
}
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(arr);
fos.flush();
fos.close();
//METHOD 2
byte[] arr = new byte[photo.length()/2];
for ( int start = 0; start < photo.length(); start += 2 )
{
String thisByte = photo.substring(start, start+2);
arr[start/2] = Byte.parseByte(thisByte, 16);
}
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(arr);
fos.flush();
fos.close();
//METHOD 3
if ((photo.length() % 2) != 0)
throw new IllegalArgumentException("Input string must contain an even number of characters");
final byte result[] = new byte[photo.length()/2];
final char enc[] = photo.toCharArray();
for (int x = 0; x < enc.length; x += 2)
{
StringBuilder curr = new StringBuilder(2);
curr.append(enc[x]).append(enc[x + 1]);
result[x/2] = (byte) Integer.parseInt(curr.toString(), 16);
}
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(result);
fos.flush();
fos.close();
//METHOD 4
byte result[] = new byte[photo.length()/2];
char enc[] = photo.toUpperCase().toCharArray();
StringBuffer curr;
for (int x = 0; x < enc.length; x += 2)
{
curr = new StringBuffer("");
curr.append(String.valueOf(enc[x]));
curr.append(String.valueOf(enc[x + 1]));
result[x] = (byte) Integer.parseInt(curr.toString(), 16);
}
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(result);
fos.flush();
fos.close();
//METHOD 5
int len = photo.length();
byte[] data = new byte[len / 2];
for (int x = 0; x < len; x += 2)
{
data[x / 2] = (byte) ((Character.digit(photo.charAt(x), 16) << 4)
+ Character.digit(photo.charAt(x+1), 16));
}
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(data);
fos.flush();
fos.close();
//METHOD 6
byte[] bytes=new BigInteger(photo, 16).toByteArray();
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(bytes);
fos.flush();
fos.close();
//METHOD 7
byte[] bytes =DatatypeConverter.parseHexBinary(photo);
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(bytes);
fos.flush();
fos.close();
//METHOD 8
HexBinaryAdapter adapter = new HexBinaryAdapter();
byte[] bytes = adapter.unmarshal(photo);
FileOutputStream fos=new FileOutputStream("D:/Images/image6.png");
fos.write(bytes);
fos.flush();
fos.close();
//METHOD 9
byte data[] = new byte[photo.length()/2];
for(int x=0;i < photo.length();x+=2) {
data[x/2] = (Integer.decode("0x"+photo.charAt(x)+photo.charAt(x+1))).byteValue();
}
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(data);
fos.flush();
fos.close();
//METHOD 10
byte[] data = new byte[photo.length()/2];
for (int x=0;i<photo.length()/2;x++)
{
data[x] = (Integer.decode(
"0x"+photo.substring(x*2, (x+1)*2))).byteValue();
}
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(data);
fos.flush();
fos.close();
//METHOD 11
String hexVal ="0000005000000050FF";
//String hexVal = "0123456789ABCDEF";
byte[] out = new byte[photo.length() / 2];
int n = photo.length();
for( int x = 0; x < n; x += 2 ) {
int hn = hexVal.indexOf( photo.charAt( x ) );
int ln = hexVal.indexOf( photo.charAt( x + 1 ) );
out[x/2] = (byte)( ( hn << 4 ) | ln );
}
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(out);
fos.flush();
fos.close();
//METHOD 12
byte[] array=photo.getBytes();
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(array);
fos.flush();
fos.close();
//METHOD 13
byte[] array=photo.getBytes();
byte[] bytes = Base64.decode(array);
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(bytes);
fos.flush();
fos.close();
//METHOD 14
byte[] array=photo.getBytes();
Charset csets = Charset.forName("UTF-8");
ByteBuffer bb=ByteBuffer.wrap(array);
csets.decode(bb);
bb.rewind();
byte[] array1=bb.array();
FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
fos.write(array1);
fos.flush();
fos.close();
The shortest way might be this.
String photo = "0000005000000050FF191818FF151715FF111413FF0E100FF2A2322FF292221";
// adds a dummy byte at the start to avoid truncation of leading zeros.
byte[] bytes = new BigInteger("10" + photo, 16).toByteArray();
System.out.println(Arrays.toString(bytes));
prints
[1, 0, 0, 0, 5, 0, 0, 0, 5, 15, -15, -111, -127, -113, -15, 81, 113, 95, -15, 17, 65, 63, -16, -31, 0, -1, 42, 35, 34, -1, 41, 34, 33]
public class test {
static String HEX_STRING = "0123456789ABCDEF";
public static byte[] convertHexadecimal2Binary(byte[] hex) {
int block = 0;
byte[] data = new byte[hex.length / 2];
int index = 0;
boolean next = false;
for (int i = 0; i < hex.length; i++) {
block <<= 4;
int pos = HEX_STRING.indexOf(Character.toUpperCase((char) hex[i]));
if (pos > -1) {
block += pos;
}
if (next) {
data[index] = (byte) (block & 0xff);
index++;
next = false;
} else {
next = true;
}
}
return data;
}
public static void main(String args[]) {
String line = "";
String line_final = "";
try {
String sCurrentLine;
BufferedReader br = new BufferedReader(new FileReader("D:\\test.txt"));//test.txt hex code string
DataOutputStream os = new DataOutputStream(new FileOutputStream("D:\\mohit.jpg"));
while ((sCurrentLine = br.readLine()) != null) {
line = StringUtils.deleteWhitespace(sCurrentLine);
byte[] temp = convertHexadecimal2Binary(line.getBytes());
os.write(temp);
}
os.close();
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
When you retrieve a file a space will be appended at the beginning of the hex string so remove the space and store it in another byte array and it works fine:
here is code for removing starting space
byte a3[] = new BigInteger(str, 16).toByteArray();
byte a[] = new byte[a3.length - 1];
for (int i = 1; i < a3.length; i++)
a[i - 1] = a3[i];
Here a3 contains retrieved byte data;
a1 contains actual byte stream
Method 2 looks correct (haven't checked all others) -- your problem is probably elsewhere. Are you sure the string extracted from the XML is complete? Which parser are you using? Perhaps it returns long strings in multiple parts (I think this might be the case for SAX parsers), and you are extracting only the first part?
Here is how I would implement the decoding part (avoiding unneeded extra allocations via substring, BigInteger, char[] etc...; for performance, you may want to use a BufferedOutputStream though):
String photo = "0000005000000050FF191818FF15";
FileOutputStream fos = new FileOutputStream("D:/Images/image6.jpg");
for (int i = 0; i < photo.length; i += 2) {
int byte = Character.digit(photo.charAt(i), 16) * 16 +
Character.digit(photo.charAt(i + 1), 16);
fos.write(byte);
}
fos.close();

Categories