Hi guys,

I tried to get each line of the text file and convert it to SHA-1 formart then to binary but i could not get the output when i tried to do system.out.println

the code:

package hash;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.io.*;
import java.security.DigestInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

/*Never give up on yourself Anthony*/

public class Hash {

    public static void main(String[] args) throws Exception{

        //open the file
        FileInputStream fstream = new FileInputStream("C://Users//NTU//Desktop//hash.txt");

// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));

String strLine;

try {
//Read File Line By Line
while ((strLine = br.readLine()) != null)   {
  // Print the content on the console
  MessageDigest sha1 = MessageDigest.getInstance("SHA1");
  System.out.println(calculateHash(sha1,strLine));
  //System.out.println(strLine);
}
//Close the input stream
in.close();
  }
catch(IOException e) {

}
}
  public static String calculateHash(MessageDigest algorithm, String file) throws Exception {
      FileInputStream fis = new FileInputStream(file);
      BufferedInputStream bis = new BufferedInputStream(fis);
      DigestInputStream dis = new DigestInputStream(bis, algorithm);

      while(dis.read() != -1);
          byte[] hash = algorithm.digest();

      return byteArray2binary(hash);
  }

  private static String byteArray2binary(byte[] hash) {
      StringBuilder binary = new StringBuilder();

      for(byte b : hash) {
          int val = b;
          for(int i = 0; i < 8; i++) {
              binary.append((val & 128) == 0 ? 0 : 1);
              val <<= 1;
          }      
          binary.append("");
      }
      return binary.toString();
  }
}

my input is like

10,1,20
10,1,30
10,1,40

output i expected should be (example):

0000001111111100100101
0010101010101010101010
1010101010101010101010

any idea whats wrong guys? Thanks.

well, writing code like this

catch(IOException e) {
}

does make it difficult to find your errors. you may be getting error messages, but you are hiding them, making yourself think everything runs smoothly.
(not sure if this is your problem, since you don't clearly state what the problem is)

change the above (for every catch block you (might) have) into:

catch(IOException e) {
e.printStackTrace();
}

and check your prompt to see if you get an error message there.

also, don't allow your main method to throw an exception, that's bad practice. since your main method is your entry point, there's nowhere to throw the exception to: you won't be able to handle the exception and avoid your application to crash.

Edited 4 Years Ago by stultuske: added notion of throwing exception by main method

Can you insert some input into the program (not read a from file) using a StringReader and execute the program using the input from the String. Post the output and add comments to the output showing what output you want to get instead?

Edited 4 Years Ago by NormR1

There's something odd about the file reading.
In main you read a file one line at a time then pass that line to calculateHash as a String. But in calculateHash you treat that String as a file name and try to read lines from that file. Unless C://Users//NTU//Desktop//hash.txt contains file names that you want to process the contents of this is wrong.
Unless you follow stultuske's excellent advice you won't know this is happening because the file not found exception in calculateHash will be thrown up to main where you immediately ignore it.

Hi guys,

Thanks alot for the advice. the output that i get is "build successful" it seems that the file never get detected. hash.txt contain all the values that i want to process.

Do you mean that i should not pass the value over?thanks.

did you add those print statements in the catch blocks? if not, basically all hell can break loose in your application, but you just are not aware of it, because you don't print the error messages you get.

an easy way to see what your code is doing (and to verify it is doing what you want it to do, with the data you want it to use) is to add prints here and there to show the values you encounter.

argh. after i put some exception that you mentioned. i got this error:

java.io.FileNotFoundException: 10,1,20 (The system cannot find the file specified)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:97)
    at hash.Hash.calculateHash(Hash.java:62)
    at hash.Hash.main(Hash.java:43)

Whats wrong with my code here?thanks. i am sure after i read line by line i will pass it to the calculatehash class to compute the hash and convert it to binary.

so, there's your problem. maybe there's an error with the name. an easy way to fix this: right before you read the file, do:

File testF = new File(fileName); // since you have the url for the file in String
if ( !testF.exists()) testF.createNewFile();

and go check where that file is placed. (also beware, there might be more trouble when trying this, if you don't have the folder where it's supposed to be created).

Hmm..strange the file name is definitely correct. I think the problem is because it tries to find my file name however i pass it as a string only.

Please read my earlier post. It explains exactly why you get that error.
If you need some clarification....
suppose the first line of the file is "Hello World"
You read that line into a String and pass it to calculateHash
calculateHash treats this as a file name, not as the data, so it tries to read a file called "Hello World", and you get a file not found exception.

Hi james,

yeah. How do i pass the each string in the file into the calculatehash function? Any tips?Thanks.

didn't study the whole code, but a quick guess is that you should discard all the file reading stuff in main, and just pass the real file name to calculateHash. calculateHash will then read the file itself.

Hi guys,

Another question, i managed to get the SHA1 output:

7c4d66f7652a51c693ae4605ca686346af749c92
d739e726a98f63154b9407a25bb7d7c10ebd35cd
b3957c5148a3b8cc29a7996a634d1bedbc876bf9
089e94bf8ffef5d8b5d0293f3c184677c556a7dd
7b599c349de601d9b5a39e378f6dcc250c389191
bc977149aaf6eb3a51c1769e8cb19901b1829e92

How can i convert this into binary? i dont use the function anymore. Thanks.

Hi it worked now. Now i have the binary in string.

I have another question. if i have values of 0011, 1000, 1010 how do i compare the first bit of each value? thanks. and do i store it string? Thanks.

for (int i = 0; i < byteData.length; i++) {
                    sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 2).substring(1));
                    //System.out.println(sb.toString() + "\n");
                }

When i print out the value of sb, it seems to be getting the binary value but not in the same number of bits. Anyone can give some pointer whats wrong. thanks.

Do you want to compare a bit in one int with a bit in another int?
One way would be to AND the int value with a bit to detect a 0 or 1
For example: (val & 0x01) == 1 to test the low order bit of val (change the 0x value to thr bit to be tested)
Then check compare the results between testing the desired bits in the two int values

seems to be getting the binary value but not in the same number of bits

Can you post the input and output to the method and add comments explaining what is wrong?

Hi norm,

My main idea is to compare two binary values (in string) for eg:

I have

String[] a = new String[] {"0011", "0101", "1000"};
String[] b = new String[] {"1000"};

then i want to compare each of the value first index of that string (a[0] = 0011 i want to get the first bit only). therefore, it will just compare with first bit only 0 AND 1 so i will get 0 and i will insert the value of that string of a into another table for storage.

Any idea how should i do it?i seem cant find suitable structure to begin with. or only can use binary values to compare? Thanks!

Hi guys,

i managed to store the values of the bit according to its table. table 0 only for those bits starting with 0 and table 1 only for those starting with bit 1. Now i want to multiple the table array by 2. so table 0 -> table 00, 01 and table 1 -> table 10, 11. Any ideas how to do this? Thanks.

Maybe its time to put the code that you just wrote into a little method, eg

void split(String[] input, String[] output0, String[] output1, int whichBit)
// takes all the Strings in input and copies them to either output0 or output1
// depending on the value of the bit specified by whichBit

Your code corresponds to that signature with whichBit = 0, but now you can use it for all your splitting:

// create empty tables of a suitable size, then...
split(table, table0, table1, 0);
split(table0, table01, table02, 1);
// etc

i want to multiple the table array by 2

Your examples are of String arrays. I'm not sure why you want the do arithmetic with Strings.

Can you show an example of the input and the output you want from it?

I think he means split it into two (multiply the number of tables by 2), not an arithmetic multiply (but if I'm wrong I just gave him bad advice!)

Hi guys,

thanks alot for the advices. In the end i am changing my String array into ArrayList because it gives me dynamic size. just now when i am using String array with fixed size just realised run into alot of out of bound exception. Therefore i think ArrayList gives more room to manipulate the data. Am i right in using ArrayList? Thanks.

James,

May i know how do i remove the value from the arraylist in my first table for example:

Table 1 has value [0011, 0101, 0111] (since arraylist now) and now i moved the values over to table 2 and 3 which will split the values into table2 [0011] , table3 [0101, 0111]. Thanks.

And if it can be removed, can i revert it back? Thanks!!

  1. Yes, ArrayLists are almost always an easier choice than simple arrays, mainly because you don't have to worry about the number of elements, plus you can insert/delete elements anywhere.
  2. You can remove things from ArrayLists with one of ArrayList's remove methods (now how hard was that, really?). See the ArrayList API doc for details.
  3. Reverting it back needs you to program something. It depends whether you just want to revert the whole thing back to some initial state (in which case just make/keep a copy), or do you want to be able to "step backwards" undoing deletes one at a time (in general that's harder)? Maybe you could wite a simple method to remove the last 1 (or n) entries from from table2 or 3, and add them back to table1?

Hi James,

Regarding no3 sugguestion:

Because i set a condition if the counter >= 100, it will move the values over from table1 to table2 and table3, but i just thinking if i remove the values till the counter less than 100, i want to resize it back to table 1 only. is it possible? Thanks.

I didn't study this in detail, but it seems to me the difficulty is that you may know you moved (eg) 20 entries, but you don't know how many went to table2 and how many to table3, so you don't know which ones to move back.
It's hard to be more specific without knowing exactly why you are trying to do these things. The whole splitting up of 4bit values by processing 4 character strings seems a bit bizarre, but presumably you have your reasons/constraints/project definitions/goals.

Edited 4 Years Ago by JamesCherrill

Hi guys,

I have another question. How do i do SHA-1 with the readline using bufferedreader. it seems SHA-1 only read one line of string instead of text file. Thanks.

MessageDigest knows nothing about strings or lines - it just processes a load of bytes one at a time or in byte arrays, or obtained by reading a DigestInputStream.

Just create a MessageDigest, and keep calling its update method with each line from the file (don't forget the end-of-line delimiters) stored in a byte array. When you've processed all the data in the file, call a digest method (this is documented in the MessageDigest API doc, as well as many sample/tutorial web sites)

ps be very careful about string-oriented reads when what you really want is the actual bytes from the file. Java String methods are designed to handle 16 bit Unicode character sets and their various 8-bit representations, and may end up doing some locale-dependent conversion on the original data.

This article has been dead for over six months. Start a new discussion instead.