Simple writing and reading bytes - java

Hey I cant figure out what is wrong here.
Write to file:
byte[] dim = new byte[2];
dim[0] = (byte) deImgWidth; // Input 384
dim[1] = (byte) deImgHeight; // Input 216
out.write(dim);
Read from File
byte[] file = new byte[(int) f.length()];
FileInputStream fs = new FileInputStream(f);
fs.read(file);
deImgWidth = ((file[0]) & 0xFF); // output 128
deImgHeight = ((file[1]) & 0xFF); // output 216
How come I can retrieve the same deImgHeight value but not the same deImgWidth value?

384 doesn't fit into an unsigned byte while 216 does. That's why when casting the former you must lose information.
Narrowing conversions just preserve the lowest bits of a number, so if you do the extra & 0xFF when you read your value, you can later restore the sign (since Java uses two's complement for negative numbers). 216 = 0b11011000 (fits into 8 bits) can be losslessly transformed, but 384 = 0b110000000 (that's 9 bits) - when you take the lower 8 bits, you end up with 128.

Related

Conversion python to Java

I need to convert this Python code in Java but the '\x00' hexcode is a real problem.
How can I do the export data to bytes[] ?
message__FirstPart = '\x45\x55\x43\x45\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00'
# event_par = key number (5+ 0..9
message__event_par = chr(key+5)
message__filler = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
# mit link state = 1
message__link_status = chr(int(GroupID))
# mit link state = 1
#message__link_status = '\x01'
# the sender’s mac-address
message__mac = '\x00\x00\x00\x00\x00\x00'
data = message__FirstPart + message__event_par + message__filler + message__link_status + message__mac
Thanks !
Strings in Java are made up of char, not byte. Though a char is really just two bytes, it is interpreted as UTF-16 and this can cause all sorts of trouble when you really want to talk about a series of bytes as it appears in your example.
You can express literal bytes as hexadecimal in Java as 0x00, 0x01, ..., 0xFF though these usually get interpreted as int and must be cast to byte:
byte[] arr = new byte[] { (byte) 0x01, (byte) 0x02 };
You can also look into the ByteBuffer class for assembling streams of bytes.

convert string with hexa to byte

I've a String with value 0xE20x800x93.
I try to convert them like this and it works
byte[] bs = new byte[]{
(byte) 0xE2,(byte) 0x80, (byte) 0x93
};
But what I want is without doing the explicit casting, I need to convert it into a byte array.
Or at least a way to convert into a byte object, and not a byte[] object.
You can do it in one (albeit long) line:
byte[] bytes = Arrays.copyOfRange(new ByteBuffer().putInt(Integer.parseInt(str.replace("0x", ""), 16)).array(), 1, 4);
This assumes you have exactly 3 bytes to get. If it's a variable length, the following code is more generic, but slightly more verbose, because it uses the length of the input to determine the eventual result size:
byte[] bytes = Arrays.copyOfRange(new ByteBuffer().putInt(Integer.parseInt(str.replace("0x", ""), 16)).array(), 4 - str.length() / 4, 4);
try DatatypeConverter.parseHexBinary(str) from javax.xml.bind package

Java MessageDigest providing 31 bit instead of 32 bit

I am trying to generate the MD5 hashcode using MessageDigest in java. Please find the sample code below. The String I am trying is combined with some code (KO00001) and system date.
String s = "KO00001"+"25/10/2012";
byte[] buffer = s.getBytes();
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(buffer);
String str = new BigInteger(1,md5.digest()).toString(16).toUpperCase();
System.out.println(str+" length:"+str.length());
I am getting the length as 32 for all the string like KO0000126/10/2012, KO0000126/10/2012. But for the string "KO0000125/10/2012" the result length is 31.
What could be the reason?
I recommend org.apache.commons.codec.digest.DigestUtils.md5Hex() for this task.
It is just because of the number, which you get from the byte-array representation of the hashcode using BigInteger, is less than others by one position. In other words, the first (high) digit in this representation is ZERO.
Just compare:
KO0000125/10/2012:
10 radix: 14105476919805249323079848858308382190 length:38
16 radix: A9C9DB4AA1D19A4126E63A7ECFD0DEE length:31
KO0000124/10/2012:
10 radix: 132805232305710448716177011414649345991 length:39
16 radix: 63E95B7C6574B57A3FD202484D0D17C7 length:32
KO0000126/10/2012:
10 radix: 256722737628903394348650044729556126214 length:39
16 radix: C123003325E6846E04656C2F3E7ECA06 length:32
md5.digest() is 16 bytes.
I suspect that you then try to output it as a 32 character hex string.
For that purpose you should do something like.
public static String toHexString(byte[] bytes) {
if (bytes == null) {
throw new IllegalArgumentException("byte array must not be null");
}
StringBuffer hex = new StringBuffer(bytes.length * 2);
for (int i = 0; i < bytes.length; i++) {
hex.append(Character.forDigit((bytes[i] & 0XF0) >> 4, 16));
hex.append(Character.forDigit((bytes[i] & 0X0F), 16));
}
return hex.toString();
}
And the result is d41d8cd98f00b204e9800998ecf8427e
(edit 1: or as Tichodroma suggested: do not re-invent the wheel, use Apache Commons Codec. Actually the answer to a lot of these questions is 'check Apache Commons first')
(edit 2: do not use getBytes() without specifying an encoding)

Converting from Windows 1252 to UTF8 in Java: null characters with CharsetDecoder/Encoder

I know it's a very general question but I'm becoming mad.
I used this code:
String ucs2Content = new String(bufferToConvert, inputEncoding);
byte[] outputBuf = ucs2Content.getBytes(outputEncoding);
return outputBuf;
But I read that is better to use CharsetDecoder and CharsetEncoder (I have contents with some character probably outside the destination encoding). I've just written this code but that has some problems:
// Create the encoder and decoder for Win1252
Charset charsetInput = Charset.forName(inputEncoding);
CharsetDecoder decoder = charsetInput.newDecoder();
Charset charsetOutput = Charset.forName(outputEncoding);
CharsetEncoder encoder = charsetOutput.newEncoder();
// Convert the byte array from starting inputEncoding into UCS2
CharBuffer cbuf = decoder.decode(ByteBuffer.wrap(bufferToConvert));
// Convert the internal UCS2 representation into outputEncoding
ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(cbuf));
return bbuf.array();
Indeed this code appends to the buffer a sequence of null character!!!!!
Could someone tell me where is the problem? I'm not so skilled with encoding conversion in Java.
Is there a better way to convert encoding in Java?
Your problem is that ByteBuffer.array() returns a direct reference to the array used as backing store for the ByteBuffer and not a copy of the backing array's valid range. You have to obey bbuf.limit() (as Peter did in his response) and just use the array content from index 0 to bbuf.limit()-1.
The reason for the extra 0 values in the backing array is a slight flaw in how the resulting ByteBuffer is created by the CharsetEncoder. Each CharsetEncoder has an "average bytes per character", which for the UCS2 encoder seem to be simple and correct (2 bytes/char). Obeying this fixed value, the CharsetEncoder initially allocates a ByteBuffer with "string length * average bytes per character" bytes, in this case e.g. 20 bytes for a 10 character long string. The UCS2 CharsetEncoder starts however with a BOM (byte order mark), which also occupies 2 bytes, so that only 9 of the 10 characters fit in the allocated ByteBuffer. The CharsetEncoder detects the overflow and allocates a new ByteBuffer with a length of 2*n+1 (n being the original length of the ByteBuffer), in this case 2*20+1 = 41 bytes. Since only 2 of the 21 new bytes are required to encode the remaining character, the array you get from bbuf.array() will have a length of 41 bytes, but bbuf.limit() will indicate that only the first 22 entries are actually used.
I am not sure how you get a sequence of null characters. Try this
String outputEncoding = "UTF-8";
Charset charsetOutput = Charset.forName(outputEncoding);
CharsetEncoder encoder = charsetOutput.newEncoder();
// Convert the byte array from starting inputEncoding into UCS2
byte[] bufferToConvert = "Hello World! £€".getBytes();
CharBuffer cbuf = decoder.decode(ByteBuffer.wrap(bufferToConvert));
// Convert the internal UCS2 representation into outputEncoding
ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(cbuf));
System.out.println(new String(bbuf.array(), 0, bbuf.limit(), charsetOutput));
prints
Hello World! £€

Using java to encrypt integers

I'm trying to encrypt some integers in java using java.security and javax.crypto.
The problem seems to be that the Cipher class only encrypts byte arrays. I can't directly convert an integer to a byte string (or can I?). What is the best way to do this?
Should I convert the integer to a string and the string to byte[]? This seems too inefficient.
Does anyone know a quick/easy or efficient way to do it?
Please let me know.
Thanks in advance.
jbu
You can turn ints into a byte[] using a DataOutputStream, like this:
ByteArrayOutputStream baos = new ByteArrayOutputStream ();
DataOutputStream dos = new DataOutputStream (baos);
dos.writeInt (i);
byte[] data = baos.toByteArray();
// do encryption
Then to decrypt it later:
byte[] decrypted = decrypt (data);
ByteArrayInputStream bais = new ByteArrayInputStream (data);
DataInputStream dis = new DataInputStream (bais);
int j = dis.readInt();
You can also use BigInteger for conversion:
BigInteger.valueOf(integer).toByteArray();
Just use NIO. It's designed for this specific purpose. ByteBuffer and IntBuffer will do what you need quickly, efficiently, and elegantly. It'll handle big/little endian conversion, "direct" buffers for high performance IO, and you can even mix data types into the byte buffer.
Convert integers into bytes:
ByteBuffer bbuffer = ByteBuffer.allocate(4*theIntArray.length);
IntBuffer ibuffer = bbuffer.asIntBuffer(); //wrapper--doesn't allocate more memory
ibuffer.put(theIntArray); //add your int's here; can use
//array if you want
byte[] rawBytes = bbuffer.array(); //returns array backed by bbuffer--
//i.e. *doesn't* allocate more memory
Convert bytes into integers:
ByteBuffer bbuffer = ByteBuffer.wrap(rawBytes);
IntBuffer ibuffer = bbuffer.asIntBuffer();
while(ibuffer.hasRemaining())
System.out.println(ibuffer.get()); //also has bulk operators
I have found the following code that may help you, since Integer in Java is always 4 bytes long.
public static byte[] intToFourBytes(int i, boolean bigEndian) {
if (bigEndian) {
byte[] data = new byte[4];
data[3] = (byte) (i & 0xFF);
data[2] = (byte) ((i >> 8) & 0xFF);
data[1] = (byte) ((i >> 16) & 0xFF);
data[0] = (byte) ((i >> 24) & 0xFF);
return data;
} else {
byte[] data = new byte[4];
data[0] = (byte) (i & 0xFF);
data[1] = (byte) ((i >> 8) & 0xFF);
data[2] = (byte) ((i >> 16) & 0xFF);
data[3] = (byte) ((i >> 24) & 0xFF);
return data;
}
}
You can find more information about the bigEndian parameter here:
http://en.wikipedia.org/wiki/Endianness
create a 4-byte array and copy the int to the array in 4 steps, with bitwise ANDs and bitshifting, like Paulo said.
But remember that block algorithms such as AES and DES work with 8 or 16 byte blocks so you will need to pad the array to what the algorithm needs. Maybe leave the first 4 bytes of an 8-byte array as 0's, and the other 4 bytes contain the integer.
Just use:
Integer.toString(int).getBytes();
Make sure you use your original int and getBytes() will return a byte array. No need to do anything else complicated.
To convert back:
Integer.parseInt(encryptedString);
My Simple Solution is that Encrypt Integer to the String by shifting ASCII Value of the Integer by the secret key you Provide.
Here is the Solution:
public String encodeDiscussionId(int Id) {
String tempEn = Id + "";
String encryptNum ="";
for(int i=0;i<tempEn.length();i++) {
int a = (int)tempEn.charAt(i);
a+=148113;
encryptNum +=(char)a;
}
return encryptNum;
}
public Integer decodeDiscussionId(String encryptText) {
String decodeText = "";
for(int i=0;i<encryptText.length();i++) {
int a= (int)encryptText.charAt(i);
a -= 148113;
decodeText +=(char)a;
}
int decodeId = Integer.parseInt(decodeText);
return decodeId;
}
Steps to Encode:
Here, First you convert the Given Integer into String by: String temp = givenInt + ""
Scan each character of String, Read ASCII of that character and add it with secret key as 148113 in this case.
Convert shifted Integer into Character and concatenate to the String encryptNum and finally return it.
Steps to Decode:
Scan each character of String, Read ASCII of that character and subtract it with secret key as previous.
Convert that value to character and concatenate with decodeText.
As previous encode output is always String '???' and vary according to number of digits of input Id.

Categories

Resources