I'm trying to create a new byte knowing a certain amount of bits
char prostie1 = theRepChars[j-3];
char prostie2 = theRepChars[j-2];
char prostie3 = theRepChars[j-1];
char prostie4 = theRepChars[j];
String prostiaMare = prostie4 + prostie3 + prostie2 + prostie1 + "";
Byte theChar = new Byte(prostiaMare);
When i do this I get a NumberFormatException value 196.
I have no idea what might be my problem
--EDIT--
Ok I think I might have to give some more details since I wasn't very clear. I'm trying to do an Uuencode algorithm and by following the logic of the algorithm I should stop my byte having a value bigger than 194. Here is a bunch of my code.
if(my_chars.length % 3 == 0)
{
for(int x = 0; x < my_chars.length; x++)
{
if((x+1) % 3 == 0)
{
char first = my_chars[x-2];
char second = my_chars[x-1];
char third = my_chars[x];
int n = (((first << 8) | second) << 8) | third;
String theRep = Integer.toBinaryString(n);
while(theRep.length() < 24 - 1)
{
theRep = 0 + theRep;
}
//0 padded theRep
for(int j = 0; j < theRepChars.length; j++)
{
if((j+1) % 4 == 0)
{
char prostie1 = theRepChars[j-3];
char prostie2 = theRepChars[j-2];
char prostie3 = theRepChars[j-1];
char prostie4 = theRepChars[j];
String prostiaMare = prostie4 + prostie3 + prostie2 + prostie1 + "";
System.out.println(prostiaMare);
}
}
}
}
}
And trying to create a new byte with the value that prostiaMare has gives me the numberFormatException. I'm not sure if I have not followed the algorithm right ( http://www.herongyang.com/encoding/UUEncode-Algorithm.html )
196 is outside the range of byte, a signed value. Bytes can range from -128 to 127.
I'm not sure why you're casting to String. If you just want a byte with bits equivalent those of the sum of the four chars, cast directly to byte:
(byte) (prostie4 + prostie3 + prostie2 + prostie1)
If you intended to construct a String from the four chars, you are not currently doing that. Use:
"" + prostie4 + prostie3 + prostie2 + prostie1
and, if the result is in the range of a byte, you can create a byte as you have been.
Bytes are signed in Java. Which means a byte, which is 8 bits long, has a minimum value of -2^7 (-128) and a max value of 2^7 - 1 (127). Java has no unsigned primitive types apart from char (unsigned, 16bit).
Therefore 196 is unparseable --> NumberFormatException.
You don't have much to work around this except to read into a larger type and do & 0xff to obtain the byte:
final int i = Integer.parseInt(theString);
final byte b = (byte) (i & 0xff);
Or do yourself a favour and use Guava, which has UnsignedBytes:
final byte b = UnsignedBytes.parseUnsignedByte(theString);
But it appears that you want to do comparisons anyway; so just use a larger type than byte. And no, this won't waste memory: don't forget about alignment.
As mentioned in the docs
An exception of type NumberFormatException is thrown if any of the following situations occurs:
The first argument is null or is a string of length zero.
The radix is either smaller than Character.MIN_RADIX or larger than Character.MAX_RADIX.
Any character of the string is not a digit of the specified radix, except that the first - character may be a minus sign '-' ('\u002D') provided that the string is longer than length 1.
The value represented by the string is not a value of type byte.
In your case its the last case since 196 cant be represented as byte..The valid range is -128 to 127
Related
Given an array filled with 4 bytes inside (R,G,B,A), I'm trying to translate this array full of 4 8bits numbers into its translation in 32bits. To be more clear, if I get an array such as:
byte[] tab = {1,2,3,4};
with translated in binary in 8bit :
1 = 0b00000001
2 = 0b00000010
3 = 0b00000011
4 = 0b00000100
Then, my method should return a byte array such as :
newTab = {00000001_00000010_00000011_00000100};
For some reason, I'm trying to do this without using a String to concatenate the bytes.
I've already tried something with binary operators such as <<, >> or |, but without success...
So far, my code looks like this :
byte[] tab = {1,2,3,4};
int tmp,tabToInt = 0;
for (int x = 0 ; x < tab.length ; ++x){
tmp = tmp << (tab.length - 1 - x)*8;
byteToInt = byteToInt | tmp;
}
return tabToInt;
But it didn't seem to work, even less with negatives bytes... (like -1 = 0b11111111)
Thanks in advance for your answers!
You can use ByteBuffer like this.
byte[] tab = {1, 2, 3, 4};
int tabToInt = ByteBuffer.wrap(tab).getInt();
System.out.println("decimal = " + tabToInt);
System.out.println("binary = " + Integer.toBinaryString(tabToInt));
System.out.println("hexadecimal =" + Integer.toHexString(tabToInt));
output
decimal = 16909060
binary = 1000000100000001100000100
hexadecimal =1020304
ByteBuffer can do it, but only if you get passed at least 4 bytes.
The problem with your code is two-fold:
I think you typoed somewhere, your code doesn't even compile. I think you meant tmp = tab[x] << (tab.length - 1 - x)*8;. Your snippet never does anything with tab other than ask for its length.
Negative numbers extend, and java will convert any byte or short to an int the moment you do any math to it. So, 0b1111 1111, if you try to do e.g. << 8 on that, java first turns that -1 byte into a -1 int (so that's now 32 1 bits), and then dutifully left shifts it by 8, so now that's 24 1 bits, followed by 8 0 bits. You then bitwise OR that into your target, and thus now the target is mostly 1 bits. To convert a byte to an int without "sign extension", (b & 0xFF does it:
byte b = (byte) 0b1111_1111;
assert b == -1; // yup, it is
int c = b; // legal
assert c == -1; // yeah, still is. uhoh. That's...
int d = 0b11111111_11111111_11111111_11111111;
assert c == d; // yeah. We don't want that.
int e = (b & 0xFF);
assert e = 255;
int f = 0b0000000_0000000_0000000_11111111;
assert e == f; // yes!
I've been searching for a solution to my problem for days but can't get a spot-on answer when looking at previously answered questions/ blogs / tutorials etc. all over the internet.
My aim is to write a program which takes a decimal number as an input and then calculates the hexadecimal number and also prints the unicode-symbol of said hexadecimal number (\uXXXX).
My problem is I can't "convert" the hexadecimal number to unicode. (It has to be written in this format: \uXXXX)
Example:
Input:
122 (= Decimal)
Output:
Hexadecimal: 7A
Unicode: \u007A | Unicode Symbol: Latin small letter "z"
The only thing I've managed to do is print the unicode (\u007A), but I want the symbol ("z").
I thought if the unicode only has 4 numbers/letters, I would just need to "copy" the hexadecimal into the code and fill up the remaining places with 0's and it kinda worked, but as I said I need the symbol not the code. So I tried and tried, but I just couldn't get the symbol.
By my understanding, if you want the symbol you need to print it as a string.
But when trying it with a string I get the error "illegal unicode escape".
It's like you only can print pre-determined unicodes and not "random" ones generated on the spot in relation of your input.
I'm only a couple days into Java, so apologies if I have missed anything.
Thank you for reading.
My code:
int dec;
int quotient;
int rest;
int[]hex = new int[10];
char[]chars = new char[]{
'F',
'E',
'D',
'C',
'B',
'A'
};
String unicode;
// Input Number
System.out.println("Input decimal number:");
Scanner input = new Scanner(System.in);
dec = input.nextInt();
//
// "Converting to hexadecimal
quotient = dec / 16;
rest = dec % 16;
hex[0] = rest;
int j = 1;
while (quotient != 0) {
rest = quotient % 16;
quotient = quotient / 16;
hex[j] = rest;
j++;
}
//
/*if (j == 1) {
unicode = '\u000';
}
if (j == 2) {
unicode = '\u00';
}
if (j == 3) {
unicode = '\u0';
}*/
System.out.println("Your number: " + dec);
System.out.print("The corresponding Hexadecimal number: ");
for (int i = j - 1; i >= 0; i--) {
if (hex[i] > 9) {
if (j == 1) {
unicode = "\u000" + String.valueOf(chars[16 - hex[i] - 1]);
}
if (j == 2) {
unicode = "\u00" + String.valueOf(chars[16 - hex[i] - 1]);
}
if (j == 3) {
unicode = "\u0" + String.valueOf(chars[16 - hex[i] - 1]);
}
System.out.print(chars[16 - hex[i] - 1]);
} else {
if (j == 1) {
unicode = "\u000" + Character.valueOf[hex[i]);
}
if (j == 2) {
unicode = "\u00" + Character.valueOf(hex[i]);
}
if (j == 3) {
unicode = "\u0" + Character.valueOf(hex[i]);
}
System.out.print(hex[i]);
}
}
System.out.println();
System.out.print("Unicode: " + (unicode));
}
It's not an advanced code whatsoever, I wrote it exactly how I would calculate it on paper.
Dividing the number through 16 until I get a 0 and what remains while doing so is the hexadecimal equivalent.
So I put it in a while loop, since I would divide the number n-times until I got 0, the condition would be to repeat the division until the quotient equals zero.
While doing so the remains of each division would be the numbers/letters of my hexadecimal number, so I need them to be saved. I choose an integer array to do so. Rest (remains) = hex[j].
I also threw a variable in the called "j", so I would now how many times the division was repeated. So I could determine how long the hexadecimal is.
In the example it would 2 letters/numbers long (7A), so j = 2.
The variable would then be used to determine how many 0's I would need to fill up the unicode with.
If I have only 2 letters/numbers, it means there are 2 empty spots after \u, so we add two zeros, to get \u007A instead of \u7A.
Also the next if-command replaces any numbers higher than 9 with a character from the char array above. Basically just like you would do on paper.
I'm very sorry for this insanely long question.
U+007A is the 3 bytes int code pointer.
\u007A is the UTF-16 char.
A Unicode code pointer, symbol, sometimes is converted to two chars and then the hexadecimal numbers do not agree. Using code pointers hence is best. As UTF-16 is just an encoding scheme for two-bytes representation, where the surrogate pairs for 3 byte Unicode numbers do not contain / or such (high bit always 1).
int hex = 0x7A;
hex = Integer.parseUnsignedInt("007A", 16);
char ch = (char) hex;
String stringWith1CodePoint = new String(new int[] { hex }, 0, 1);
int[] codePoints = stringWith1CodePoint.codePoints().toArray();
String s = "๐"; // U+1D11E = "\uD834\uDD1E"
You can simply use System.out.printf or String.format to do what you want.
Example:
int decimal = 122;
System.out.printf("Hexadecimal: %X\n", decimal);
System.out.printf("Unicode: u%04X\n", decimal);
System.out.printf("Latin small letter: %c\n", (char)decimal);
Output:
Hexadecimal: 7A
Unicode: u007A
Latin small letter: z
This question already has an answer here:
What does "possible lossy conversion" mean and how do I fix it?
(1 answer)
Closed 2 years ago.
my simple encryption algorithim i am doing as an exercise is giving me a possible lossy conversion from int to byte? but i dont know why it is giving me this error any ideas?
public class Rot13Crypt extends CryptStream
{
public Rot13Crypt(StreamPair theStreams)
{
super(theStreams);
}
protected byte [] cryptData(byte [] data, int len)
{
byte [] cryptedByte = new byte[len];
for(int i = 0; i < len; i++)
{
cryptedByte[i] = (data[i] + 13) % 256;
}
return cryptedByte;
}
protected byte [] decryptData(byte [] data, int len)
{
byte [] decryptedByte = new byte[len];
for(int i = 0; i < len; i++)
{
decryptedByte[i] = (data[i] * 256) - 13;
}
return decryptedByte;
}
}
It is giving that error message because you are attempting to assign the value of an int-valued expression to a byte. That is a potentially lossy operation: intuitively, you cannot put all possible int values into a byte.
The Java language requires you to use a (byte) cast when you assign an int-valued expression to a byte.
There are two places where you are doing this:
cryptedByte[i] = (data[i] + 13) % 256;
decryptedByte[i] = (data[i] * 256) - 13;
In the first one, the value of the expression is in the range 0 to 255 ... but Java byte values are in the range -128 to +127.
In the second one, the expression values potentially have values in the range (-128 * 256) - 13 to `(+127 * 256) - 13. That clearly won't fit.
But that is actually moot. The Java does not allow variants of the above code even if you (a smart human being) can prove that the range of the expression would "fit" into a byte. The JLS forbids this. (A Java compiler not required to be a general theorem prover!!)
The only situation where an int-valued expression can be assigned to a byte without a type-cast is when the expression is a compile-time constant expression AND the actual value of the expression is in the range of byte.
If you are interested, this is specified in JLS 15.2 Assignment Contexts which states:
In addition, if the expression is a constant expression (ยง15.28) of type byte, short, char, or int:
A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.
(You need to chase down what the spec means by "constant expression" and "narrowing primitive conversion". I'll leave that for interested people to do for themselves.)
so would i add a (byte) cast in front of the 13 and 256?
Nope. You need to cast the entire expression; e.g.
cryptedByte[i] = (byte) ((data[i] + 13) % 256);
In Java, the int type is coded using 32 bits and the byte type using 8 bits. If you convert an int to a byte, you may lose information if your original value is greater than 127 or less than -128.
An integer literal is by default an int and operations on int return int. So the result of data[i] + 13 is an int; the same for (data[i] + 13) % 256. When you try to store that result into a byte (here cryptedByte[i]), Java warns you about the "possible lossy conversion".
A byte has 2^8 = 256 unique states and so the largest range it can represent is -128 to 127.
so assuming that in
decryptedByte[i] = (data[i] * 256) - 13;
the data[i] value is greater than 1 will cause the value to overflow the max value of a byte
You have problems here
cryptedByte[i] = (data[i] + 13) % 256;
and here
decryptedByte[i] = (data[i] * 256) - 13;
256 and 13 are literals of type int. When you perform operations with them and with a type that occupies less memory (in this example, byte), type promotion occurs: data[i] is implicitly converted (promoted) to type int. Thus, both these expressions evaluate to int. And you know what happens when you convert an int to a byte, right? You can lose data. That is because a byte is limited to less memory than int.
You just need to do a cast when assigning each byte when it's inside a variable, so java can assure all are between -127 and 127 which is the ascii range. The folowing should work:
public class Rot13Crypt extends CryptStream
{
public Rot13Crypt(StreamPair theStreams)
{
super(theStreams);
}
protected byte [] cryptData(byte [] data, int len)
{
byte [] cryptedByte = new byte[len];
for(int i = 0; i < len; i++)
{
cryptedByte[i] = (byte) (data[i] + 13) % 256;
}
return cryptedByte;
}
protected byte [] decryptData(byte [] data, int len)
{
byte [] decryptedByte = new byte[len];
for(int i = 0; i < len; i++)
{
decryptedByte[i] = (byte) (data[i] * 256) - 13;
}
return decryptedByte;
}
}
Bytes have a size of 8 bits and ints a size of 32 bits. So some information may be lost by doing this conversion!
byte data type is an 8-bit signed two's complement integer.
int data type is a 32-bit signed two's complement integer.
Can't fit an integer into a byte. Hence, the loss in precision.
I hope it's clear.
A sample reference is here
I'm trying to make a UUencode algorithm and part of my code contains this:
for(int x = 0; x < my_chars.length; x++)
{
if((x+1) % 3 == 0)
{
char first = my_chars[x-2];
char second = my_chars[x-1];
char third = my_chars[x];
int first_binary = Integer.parseInt(Integer.toBinaryString(first));
int second_binary = Integer.parseInt(Integer.toBinaryString(second));
int third_binary = Integer.parseInt(Integer.toBinaryString(third));
int n = (((first << 8) | second) << 8) | third;
System.out.print(my_chars[x-2] + "" + my_chars[x-1] + my_chars[x] + Integer.toBinaryString(n));
}
}
System.out.println();
System.out.println(Integer.toBinaryString('s'));
What I'm trying to achieve is to combine those 8 bits from the chars that I get into a big 24 bits int. The problem I'm facing is that the result is a 23 bit int. Say my first 3 chars were:
'T' with a binary representation of 01010100
'u' with a binary representation of 01110101
'r' with a binary representation of 01110010
The result that I get from my program is a int formed from these bits:
10101000111010101110010
Which is missing the 0 at the beginning from the representation of 'T'.
Also I have included the last 2 lines of code because the binary string that I get from 's' is: 1110011 which is missing the 0 at the beginning.
I have checked if I scrolled by mistake to the right but it does not seem that I have done so.
The method Integer.toBinaryString() does not zero-pad the results on the left; you'll have to zero-pad it yourself.
This value is converted to a string of ASCII digits in binary (base 2)
with no extra leading 0s.
I am trying to convert a HEX-sequence to a String encoded in either, ISO-8859-1, UTF-8 or UTF-16BE. That is, I have a String looking like: "0422043504410442" this represents the characters: "Test" in UTF-16BE.
The code I used to convert between the two formats was:
private static String hex2String(String hex, String encoding) throws UnsupportedEncodingException {
char[] hexArray = hex.toCharArray();
int length = hex.length() / 2;
byte[] rawData = new byte[length];
for(int i=0; i<length; i++){
int high = Character.digit(hexArray[i*2], 16);
int low = Character.digit(hexArray[i*2+1], 16);
int value = (high << 4) | low;
if( value > 127)
value -= 256;
rawData[i] = (byte) value;
}
return new String(rawData, encoding);
}
This seems to work fine for me, but I still have two questions regarding this:
Is there any simpler way (preferably without bit-handling) to do this conversion?
How am I to interpret the line: int value = (high << 4) | low;?
I am familiar with the basics of bit-handling, though not at all with the Java syntax. I believe the first part shift all bits to the left by 4 steps. Though the rest I don't understand and why it would be helpful in this certain situation.
I apologize for any confusion in my question, please let me know if I should clarify anything.
Thank you.
//Abeansits
Is there any simpler way (preferably without bit-handling) to do this conversion?
None I would know of - the only simplification seems to parse the whole byte at once rather than parsing digit by digit (e.g. using int value = Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16);)
public static byte[] hexToBytes(final String hex) {
final byte[] bytes = new byte[hex.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16);
}
return bytes;
}
How am I to interpret the line: int value = (high << 4) | low;?
look at this example for your last two digits (42):
int high = 4; // binary 0100
int low = 2; // binary 0010
int value = (high << 4) | low;
int value = (0100 << 4) | 0010; // shift 4 to left
int value = 01000000 | 0010; // bitwise or
int value = 01000010;
int value = 66; // 01000010 == 0x42 == 66
You can replace the << and | in this case with * and +, but I don't recommend it.
The expression
int value = (high << 4) | low;
is equivalent to
int value = high * 16 + low;
The subtraction of 256 to get a value between -128 and 127 is unnecessary. Simply casting, for example, 128 to a byte will produce the correct result. The lowest 8 bits of the int 128 have the same pattern as the byte -128: 0x80.
I'd write it simply as:
rawData[i] = (byte) ((high << 4) | low);
Is there any simpler way (preferably
without bit-handling) to do this
conversion?
You can use the Hex class in Apache commons, but internally, it will do the same thing, perhaps with minor differences.
How am I to interpret the line: int value = (high << 4) | low;?
This combines two hex digits, each of which represents 4 bits, into one unsigned 8-bit value stored as an int. The next two lines convert this to a signed Java byte.