I have a problem with the method that aims to print a hypothetical new hashCode for my class. I am trying to create for each object a hashcode that will be composed of the hashCodes of two String variables of my class. That's my code:
public void printHashCodes(){
String plateNumber = String.valueOf(this.liNumber.hashCode()) + String.valueOf(this.country.hashCode());
int hashCodeToConvert = Integer.valueOf(plateNumber);
System.out.println(hashCodeToConvert);
System.out.println(plateNumber);
}
Whenever I delete "hashCodeToConvert" lines and print a String called "plateNumber" method works fine. From that I understand that conversion of joined hashCodes to String was succesful.
Whenever I replace the content of the "plateNumber" String with some constant value like "123456789" the method works fine too so the code must be working well but in the form above it just doesn't work.
I assume there must be some limitation in conversion of potentially unlimited String into limited primitive int but what is the actual reason and what is the solution for that problem?
Clarification: My actual aim is to make a hashCode for an object but I am using printHashCodes method to verify those hashCodes. Since hashCode must be an int I have to reconvert it into int. It cannot stay as String(as farest I know)
I can see two reasons why your code is failing.
First, the result of String.valueOf(this.liNumber.hashCode()) + String.valueOf(this.country.hashCode()) could be too big.
The maximum value for an integer is 2147483647.
Secondly, the output of the hashCode() method could be below zero, and the value of plateNumbercould be 2147483647-1164645587, which is not easy to transform into an integer.
In both cases, it will throw a java.lang.NumberFormatException.
For me, the easiest solution would be to create a hashcode for an object that would contain these two values.
Or to use this:
return Objects.hash(liNumber, country);
I need to set byte value as method parameter. I have boolean variable isGenerated, that determines the logic to be executed within this method. But I can pass directly boolean as byte parameter this is not allowed and can't be cast in java. So the solution I have now looks like this:
myObj.setIsVisible(isGenerated ? (byte)1 : (byte)0);
But it seems odd for me. Maybe some better solution exists to do this?
your solution is correct.
if you like you may avoid one cast by doing it the following way:
myObj.setIsVisible((byte) (isGenerated ? 1 : 0 ));
additionally you should consider one of the following changes to your implementation:
change your method to something like setVisiblityState(byte state) if you need to consider more than 2 possible states
change your method to setIsVisible(boolean value) if your method does what it's looking like
You can use this solution. I found it on this very useful page
boolean vIn = true;
byte vOut = (byte)(vIn?1:0);
It is not odd. It is OK.
The odd is that you need to transform typed boolean value to not self explainable byte. However sometimes we have to do this when working with legacy APIs.
BTW if you want to save memory you can use 1 bit instead of byte, so you can group several boolean flags together while using bit for each boolean value. But this technique is relevant for huge amounts of data only when saving several bytes can be significant.
Hi In My application I need to calcluate the md5 Hash Value for a string value... for that I have called DigestUtils.md5Hex(String string) method... But it is not produced same result always for a same string... The result is inconsistent. In that md5Hex() method internally md5(string) called. That method returns the different byteArray values for a same string. I am not able to get what exactly happening? Please clarify the issue...
As you can guess, this is not possible. You are probably passing different strings, but you don't know it. They may differ by a whitespace, for example, or some invisible character.
HI,
I have methods each of them requires integer ,string respectively. I read the inputs from my xml file. I will not be aware of what the type of inputs it will be. I am using reflection to invoke the method. I read the xml and store it as string. I invoke the method by passing in the parameter. One of the method expects an integer, but I pass in string. When I try to do the getType and cast, it is throwing class cast exception.
Anyhelp would be appreciated.
Thanks,
Priya.R
Java is strongly typed language. You can not pass a string to integer expecting method. You should convert string to integer, you can use Integer.parseInt() ..
If all inputs are Strings in the XML file, then there really is no difference between an XML file and a normal text file, is there?
The main problem is the representation of data types: you are not using XML as it's meant to be. XML files should represent the particular data type an input has. For example, a person's age should be represented as an int. You lose type semantics when you encode everything as a String.
As for actual code, use the XMLEncoder and XMLDecoder java classes located here and here, respectively.
Basically, you'll do something like:
XMLEncoder encoder = new XMLEncoder();
XMLDecoder decoder = new XMLDecoder();
Encoding (aka: Storing the data to the XML File)
- Write the first input as an integer type (encoder.writeInt(someIntValue))
- Write the second input as a String: encoder.writeString(someStrValue)
- etc
When decoding, you decode an integer first, then a String, etc.
I know this sounds like a broad question but I can narrow it down with an example. I am VERY new at Java. For one of my "learning" projects, I wanted to create an in-house MD5 file hasher for us to use. I started off very simple by attempting to hash a string and then moving on to a file later. I created a file called MD5Hasher.java and wrote the following:
import java.security.*;
import java.io.*;
public class MD5Hasher{
public static void main(String[] args){
String myString = "Hello, World!";
byte[] myBA = myString.getBytes();
MessageDigest myMD;
try{
myMD = MessageDigest.getInstance("MD5");
myMD.update(myBA);
byte[] newBA = myMD.digest();
String output = newBA.toString();
System.out.println("The Answer Is: " + output);
} catch(NoSuchAlgorithmException nsae){
// print error here
}
}
}
I visited java.sun.com to view the javadocs for java.security to find out how to use MessageDigest class. After reading I knew that I had to use a "getInstance" method to get a usable MessageDigest object I could use. The Javadoc went on to say "The data is processed through it using the update methods." So I looked at the update methods and determined that I needed to use the one where I fed it a byte array of my string, so I added that part. The Javadoc went on to say "Once all the data to be updated has been updated, one of the digest methods should be called to complete the hash computation." I, again, looked at the methods and saw that digest returned a byte array, so I added that part. Then I used the "toString" method on the new byte array to get a string I could print. However, when I compiled and ran the code all that printed out was this:
The Answer Is: [B#4cb162d5
I have done some looking around here on StackOverflow and found some information here:
How can I generate an MD5 hash?
that gave the following example:
String plaintext = 'your text here';
MessageDigest m = MessageDigest.getInstance("MD5");
m.reset();
m.update(plaintext.getBytes());
byte[] digest = m.digest();
BigInteger bigInt = new BigInteger(1,digest);
String hashtext = bigInt.toString(16);
// Now we need to zero pad it if you actually want the full 32 chars.
while(hashtext.length() < 32 ){
hashtext = "0"+hashtext;
}
It seems the only part I MAY be missing is the "BigInteger" part, but I'm not sure.
So, after all of this, I guess what I am asking is, how do you know to use the "BigInteger" part? I wrongly assumed that the "toString" method on my newBA object would convert it to a readable output, but I was, apparently, wrong. How is a person supposed to know which way to go in Java? I have a background in C so this Java thing seems pretty weird. Any advice on how I can get better without having to "cheat" by Googling how to do something all the time?
Thank you all for taking the time to read. :-)
The key in this particular case is that you need to realize that bytes are not "human readable", but characters are. So you need to convert bytes to characters in a certain format. For arbitrary bytes like hashes, usually hexadecimal is been used as "human readable" format. Every byte is then to be converted to a 2-character hexadecimal string which you in turn concatenate together.
This is unrelated to the language you use. You just have to understand/realize how it works "under the hoods" in a language agnostic way. You have to understand what you have (a byte array) and what you want (a hexstring). The programming language is just a tool to achieve the desired result. You just google the "functional requirement" along with the programming language you'd like to use to achieve the requirement. E.g. "convert byte array to hex string in java".
That said, the code example you found is wrong. You should actually determine each byte inside a loop and test if it is less than 0x10 and then pad it with zero instead of only padding the zero depending on the length of the resulting string (which may not necessarily be caused by the first byte being less than 0x10!).
StringBuilder hex = new StringBuilder(bytes.length * 2);
for (byte b : bytes) {
if ((b & 0xff) < 0x10) hex.append("0");
hex.append(Integer.toHexString(b & 0xff));
}
String hexString = hex.toString();
Update as per the comments on the answer of #extraneon, using new BigInteger(byte[]) is also the wrong solution. This doesn't unsign the bytes. Bytes (as all primitive numbers) in Java are signed. They have a negative range. The byte in Java ranges from -128 to 127 while you want to have a range of 0 to 255 to get a proper hexstring. You basically just need to remove the sign to make them unsigned. The & 0xff in the above example does exactly that.
The hexstring as obtained from new BigInteger(bytes).toString(16) is NOT compatible with the result of all other hexstring producing MD5 generators the world is aware of. They will differ whenever you've a negative byte in the MD5 digest.
You have actually successfully digested the message. You just don't know how to present the found digest value properly. What you have is a byte array. That's a bit difficult to read, and a toString of a byte array yields [B#somewhere which is not useful at all.
The BigInteger comes into it as a tool to format the byte array to a single number.
What you do is:
construct a BigInteger with the proper value (in this case that value happens to be encoded in the form of a byte array - your digest
Instruct the BigInteger object to return a String representation (e.g. plain, readable text) of that number, base 16 (e.g. hex)
And the while loop prefixes that value with 0-characters to get a width of 32. I'd probably use String.format for that, but whatever floats your boat :)
MessageDigests compute a byte array of something, the string that you usually see (such as 1f3870be274f6c49b3e31a0c6728957f) is actually just a conversion of the byte array to a hexadecimal string.
When you call MessageDigest.toString(), it calls MessageDigest.digest().toString(), and in Java, the toString method for a byte[] (returned by MessageDigest.digest()) returns a sort of reference to the bytes, not the actual bytes.
In the code you posted, the byte array is changed to an integer (in this case a BigInteger because it would be extremely large), and then converted to hexadecimal to be printed to a String.
The byte array computed by the digest represents a number (a 128-bit number according to http://en.wikipedia.org/wiki/MD5), and that number can be converted to any other base, so the result of the MD5 could be represented as a base-10 number, a base-2 number (as in a byte array), or, most commonly, a base-16 number.
It is OK to google for answers as long as you (eventually) understand what you copy-pasted into your app :-)
In general, I recommend starting with a good Java introductory book, or web tutorial. See these threads for more tips:
https://stackoverflow.com/questions/77839/what-are-the-best-resources-for-learning-java-books-websites-etc
Learning Java
https://stackoverflow.com/questions/78293/good-book-to-learn-to-program-well-in-java-engineering-or-architecture-wise-not
Though I'm afraid that I have no experience whatsoever using Java to play with MD5 hashes, I can recommend Sun's Java Tutorials as a fantastic resource for learning Java. They go through most of the language, and helped me out a ton when I was learing Java.
Also look around for other posts asking the same thing and see what suggestions popped up there.
The reason BigInteger is used is because the byte array is very long, too big too fit into an int or long. However, if you do want to see everything in the byte array, there's an alternate approach. You could just replace the line:
String output = newBA.toString();
with:
String output = Arrays.toString(newBA);
This will print out the contents of the array, not the reference address.
Use an IDE that shows you where the "toString()" method is coming from. In most cases it's just from the Object class and won't be very useful. It's generally recommended to overwrite the toString-method to provide some clean output, but many classes don't do this.
I'm also a newbie to development. For the current problem, I suggest the Book "Introduction To Cryptography With Java Applets" by David Bishop. It demonstrates what you need and so forth...
Any advice on how I can get better
without having to "cheat" by Googling
how to do something all the time?
By by not starting out with an MD5 hasher! Seriously, work your way up little by little on programs that you can complete without worrying about domain-specific stuff like MD5.
If you're dumping everything into main, you're not programming Java.
In a program of this scale, your main() should do one thing: create an MD5Hasher object and then call some methods on it. You should have a constructor that takes an initial string, a method to "do the work" (update, digest), and a method to print the result.
Get some tutorials and spend time on simple, traditional exercises (a Fibonacci generator, a program to solve some logic puzzle), so you understand the language basics before bothering with the libraries, which is what you are struggling with now. Then you can start doing useful stuff.
I wrongly assumed that the "toString" method on my newBA object would convert it to a readable output, but I was, apparently, wrong. How is a person supposed to know which way to go in Java?
You could replace here Java with the language of your choice that you don't know/haven't mastered yet. Even if you worked 10 years in a specific language, you will still get those "Aha! This is the way it's working!"-effects, though not that often as in the beginning.
The point you need to learn here is that toString() is not returning the representation you want/expect, but any the implementer has chosen. The default implementation of toString() is like this (javadoc):
Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
How is a person supposed to know which
way to go in Java? I have a background
in C so this Java thing seems pretty
weird. Any advice on how I can get
better without having to "cheat" by
Googling how to do something all the
time?
Obvious answers are 1- google when you have questions (and it's not considered cheating imo) and 2- read books on the subject matter.
Apart from these two, I would recommend trying to find a mentor for yourself. If you do not have experienced Java developers at work, then try to join a local Java developer user group. You can find more experienced developers there and perhaps pick their brains to get answers to your questions.