I get hex strings of 14 bytes, e.g. a55a0b05000000000022366420ec.
I use javax.xml.bind.DatatypeConverter.parseHexBinary(String s) to get an array of 14 bytes.
Unfortunately those are unsigend bytes like the last one 0xEC = 236 for example.
But I would like to compare them to bytes like this:
if(byteArray[13] == 0xec)
Since 235 is bigger than a signed byte this if statement would fail.
Any idea how to solve this in java?
Thx!
Try if(byteArray[13] == (byte)0xec)
You can promote the byte to integer:
if((byteArray[13] & 0xff) == 0xec)
since java doesn't support (atleast with primitives) any unsigned data types, you should look at using int as your data type to parse the string..
String str = "a55a0b05000000000022366420ec";
int[] arrayOfValues = new int[str.length() / 2];
int counter = 0;
for (int i = 0; i < str.length(); i += 2) {
String s = str.substring(i, i + 2);
arrayOfValues[counter] = Integer.parseInt(s, 16);
counter++;
}
work with the arrayOfValues...
Related
I have a key for a cipher in the form "XY XY+1 XY+2 XY+3 XY+4 XY+5 FF FF" where XY is an unknown byte, for example, XY could be 00000000 so XY+1 is 00000001.
Also, FF is a constant so always 11111111.
l have an addBinary() method which simply adds 1 to any binary string I give it, however, I'm finding it hard to generate all binary strings composing of "xxxx... 11111111 11111111".
I also found this printB() method on StackOverflow which generates the strings but just not sure how to hard code the FF's into it.
static void printB()
{
for(int i = 0; i < Math.pow(2,8); i++)
{
String format="%0"+8+"d";
System.out.printf(format,Integer.valueOf(Integer.toBinaryString(i)));
System.out.println();
}
}
Any help on how to generate this strings would be appreciated
If you want to have the binary number to be prefixed with 0-s you have to do a bit of work. Here I used a StringBuilder filled with 0s, replacing from the end the binary representation without 0 padding.
for (int i = 0; i <= 0xFF; i++) {
StringBuilder builder = new StringBuilder("00000000");
String binary = Integer.toBinaryString(i);
builder.replace(8 - binary.length(), 8, binary);
System.out.println(builder);
}
I recommend not working with strings of "1" and "0" except for formatting output. Internally you should store your "key" as a byte[8], so:
byte[] key = new byte[8];
for(int i=0; i<6; i++) {
key[i] = (byte) x + i;
}
key[6] = (byte) 0xff;
key[7] = (byte) 0xff;
As a first shot at converting this to a printable string, you just need:
String result = IntStream.range(0,8)
.map(i -> key[i])
.mapToObj(n -> intToBinaryString(n))
.collect(Collectors.joining(" "));
... and then you need an intToBinaryString() method. There are plenty of SO answers describing how to do this - for example: Print an integer in binary format in Java
In order to send a chunk of bits from a 4 words String, I'm doing getting the byte array from the String and calculating the bit string.
StringBuilder binaryStr = new StringBuilder();
byte[] bytesFromStr = str.getBytes("UTF-8");
for (int i = 0, l = bytesFromStr.length; i < l; i++) {
binaryStr.append(Integer.toBinaryString(bytesFromStr[i]));
}
String result = binaryStr.toString();
The problem appears when I want to do the reverse operation: converting a bit string to a Java String encoded using UTF-8.
Please, Is there someone that can explain me the best way to do that?
Thanks in advance!
TL;DR Don't use toBinaryString(). See solution at the end.
Your problem is that Integer.toBinaryString() doesn't return leading zeroes, e.g.
System.out.println(Integer.toBinaryString(1)); // prints: 1
System.out.println(Integer.toBinaryString(10)); // prints: 1010
System.out.println(Integer.toBinaryString(100)); // prints: 1100100
For your purpose, you want to always get 8 bits for each byte.
You also need to prevent negative values from causing errors, e.g.
System.out.println(Integer.toBinaryString((byte)129)); // prints: 11111111111111111111111110000001
Easiest way to accomplish that is like this:
Integer.toBinaryString((b & 0xFF) | 0x100).substring(1)
First, it coerces the byte b to int, then retains only lower 8 bits, and finally sets the 9th bit, e.g. 129 (decimal) becomes 1 1000 0001 (binary, spaces added for clarity). It then excludes that 9th bit, in effect ensuring that leading zeroes are in place.
It's better to have that as a helper method:
private static String toBinary(byte b) {
return Integer.toBinaryString((b & 0xFF) | 0x100).substring(1);
}
In which case your code becomes:
StringBuilder binaryStr = new StringBuilder();
for (byte b : str.getBytes("UTF-8"))
binaryStr.append(toBinary(b));
String result = binaryStr.toString();
E.g. if str = "Hello World", you get:
0100100001100101011011000110110001101111001000000101011101101111011100100110110001100100
You could of course just do it yourself, without resorting to toBinaryString():
StringBuilder binaryStr = new StringBuilder();
for (byte b : str.getBytes("UTF-8"))
for (int i = 7; i >= 0; i--)
binaryStr.append((b >> i) & 1);
String result = binaryStr.toString();
That will probably run faster too.
Thanks #Andreas for your code. I test using your function and "decoding" again to UTF-8 using this:
StringBuilder revealStr = new StringBuilder();
for (int i = 0; i < result.length(); i += 8) {
revealStr.append((char) Integer.parseUnsignedInt(result.substring(i, i + 8), 2));
}
Thanks for all folks to help me.
I have a byte array read over a network connection that I need to transform into a String without any encoding, that is, simply by treating each byte as the low end of a character and leaving the high end zero. I also need to do the converse where I know that the high end of the character will always be zero.
Searching the web yields several similar questions that have all got responses indicating that the original data source must be changed. This is not an option so please don't suggest it.
This is trivial in C but Java appears to require me to write a conversion routine of my own that is likely to be very inefficient. Is there an easy way that I have missed?
No, you aren't missing anything. There is no easy way to do that because String and char are for text. You apparently don't want to handle your data as text—which would make complete sense if it isn't text. You could do it the hard way that you propose.
An alternative is to assume a character encoding that allows arbitrary sequences of arbitrary byte values (0-255). ISO-8859-1 or IBM437 both qualify. (Windows-1252 only has 251 codepoints. UTF-8 doesn't allow arbitrary sequences.) If you use ISO-8859-1, the resulting string will be the same as your hard way.
As for efficiency, the most efficient way to handle an array of bytes is to keep it as an array of bytes.
This will convert a byte array to a String while only filling the upper 8 bits.
public static String stringFromBytes(byte byteData[]) {
char charData[] = new char[byteData.length];
for(int i = 0; i < charData.length; i++) {
charData[i] = (char) (((int) byteData[i]) & 0xFF);
}
return new String(charData);
}
The efficiency should be quite good. Like Ben Thurley said, if performance is really such an issue don't convert to a String in the first place but work with the byte array instead.
Here is a sample code which will convert String to byte array and back to String without encoding.
public class Test
{
public static void main(String[] args)
{
Test t = new Test();
t.Test();
}
public void Test()
{
String input = "Hèllo world";
byte[] inputBytes = GetBytes(input);
String output = GetString(inputBytes);
System.out.println(output);
}
public byte[] GetBytes(String str)
{
char[] chars = str.toCharArray();
byte[] bytes = new byte[chars.length * 2];
for (int i = 0; i < chars.length; i++)
{
bytes[i * 2] = (byte) (chars[i] >> 8);
bytes[i * 2 + 1] = (byte) chars[i];
}
return bytes;
}
public String GetString(byte[] bytes)
{
char[] chars = new char[bytes.length / 2];
char[] chars2 = new char[bytes.length / 2];
for (int i = 0; i < chars2.length; i++)
chars2[i] = (char) ((bytes[i * 2] << 8) + (bytes[i * 2 + 1] & 0xFF));
return new String(chars2);
}
}
Using deprecated constructor String(byte[] ascii, int hibyte)
String string = new String(byteArray, 0);
String is already encoded as Unicode/UTF-16. UTF-16 means that it can take up to 2 string "characters"(char) to make one displayable character. What you really want is to use is:
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(myString);
to convert a String to an array of bytes. This does exactly what you did above except it is 10 times faster in performance. If you would like to cut the transmission data nearly in half, I would recommend converting it to UTF8 (ASCII is a subset of UTF8) - the format the internet uses 90% of the time, by calling:
byte[] bytes = Encoding.UTF8.GetBytes(myString);
To convert back to a string use:
String myString = Encoding.Unicode.GetString(bytes);
or
String myString = Encoding.UTF8.GetString(bytes);
I want to write a java program which takes a text field with byte data. Output of my program should be string. How can I achieve that. Any inputs are appreciated.
Input is
85f960f0 82868260 f4f78486 60f8f6f
Output is string format like customer, hero, english..
I am planning to write a simple java program.
Thanks in advance.
Sorry for missing out details first time. I am in learning stages now.
Your question doesn't provide enough detail for a full answer. Assuming the fragment "85f960f0 82868260 f4f78486 60f8f6f" is the output you want...
convert a byte array to hexadecimal string using String.format() using the %x pattern within a loop.
Use %02x to pad each octet to 2 digits if necessary
if you need spaces every 8 characters you could do this by checking to see if the counter is divisible by 4 using the % operator.
For example.
byte[] valueFromTextField = "hello world foo bar".getBytes();
StringBuilder builder = new StringBuilder();
int i = 0;
for (byte element : valueFromTextField) {
if (i % 4 == 0 && builder.length() > 0) {
builder.append(" ");
}
builder.append(String.format("%02x", element));
i++;
}
System.out.println(builder.toString());
Output
68656c6c 6f20776f 726c6420 666f6f20 626172
Assuming you are having byte[] bytes and you can convert it using bytes.toString() OR you can change byte by byte
byte[] bites = new byte[]{24,4,72,56};
for(int i = 0; i < bites.length; i++)
System.out.println(new String(bites, i,1));
String hexadecimals = textField.getText();
hexadecimals = hexadecimals.replaceAll("[^0-9A-Fa-f]", ""); // Remove garbage
int nn = hexadecimals.length();
if (nn % 2 != 0) {
JOptionPane.showMessageDialog(null, "... must be even", JOptionPane.ERROR_MESSAGE);
return "";
}
byte[] bytes = new byte[nn / 2];
for (int i = 0; i < nn - 1; i += 2) {
int b = Integer.parseInt(hexadecimals.substring(i, i + 2), 16);
bytes[i] = (byte) b;
}
return new String(bytes, StandardCharsets.UTF_8);
This uses Integer.parseInt with base 16 (0-9A-F) in integer range to ignore negative byte values.
To convert those bytes to text (which in Java is Unicode to hold any combination of chars), one needs to know which text encoding those bytes are in. Here I use UTF-8, which however requires adherance to the UTF-8 multibyte format.
I have a question about converting String type binary number to bit and write in the txt file.
For example we have String like "0101011" and want to convert to bit type "0101011"
then write in to the file on the disk.
I would like to know is there anyway to covert to string to bit..
i was searching on the web they suggest to use bitarray but i am not sure
thanks
Try this:
int value = Integer.parseInt("0101011", 2); // parse base 2
Then the bit pattern in value will correspond to the binary interpretation of the string "0101011". You can then write value out to a file as a byte (assuming the string is no more than 8 binary digits).
EDIT You could also use Byte.parseByte("0101011", 2);. However, byte values in Java are always signed. If you tried to parse an 8-bit value with the 8th bit set (like "10010110", which is 150 decimal), you would get a NumberFormatException because values above +127 do not fit in a byte. If you don't need to handle bit patterns greater than "01111111", then Byte.parseByte works just as well as Integer.parseInt.
Recall, though, that to write a byte to a file, you use OutputStream.write(int), which takes an int (not byte) value—even though it only writes one byte. Might as well go with an int value to start with.
You can try the below code to avoid overflows of the numbers.
long avoidOverflows = Long.parseLong("11000000000000000000000000000000", 2);
int thisShouldBeANegativeNumber = (int) avoidOverflows;
System.out.println("Currect value : " + avoidOverflows + " -> " + "Int value : " + thisShouldBeANegativeNumber);
you can see the output
Currect value : 3221225472 -> Int value : -1073741824
//Converting String to Bytes
bytes[] cipherText= new String("0101011").getBytes()
//Converting bytes to Bits and Convert to String
StringBuilder sb = new StringBuilder(cipherText.length * Byte.SIZE);
for( int i = 0; i < Byte.SIZE * cipherText .length; i++ )
sb.append((cipherText [i / Byte.SIZE] << i % Byte.SIZE & 0x80) == 0 ? '0' : '1');
//Byte code of input in Stirn form
System.out.println("Bytecode="+sb.toString()); // some binary data
//Convert Byte To characters
String bin = sb.toString();
StringBuilder b = new StringBuilder();
int len = bin.length();
int i = 0;
while (i + 8 <= len) {
char c = convert(bin.substring(i, i+8));
i+=8;
b.append(c);
}
//String format of Binary data
System.out.println(b.toString());