views:

162

answers:

3

I received this python script that generates a file checksum:

import sys,os

if __name__=="__main__":
#filename=os.path.abspath(sys.argv[1])
#filename=r"H:\Javier Ortiz\559-7 From Pump.bin"
cksum=0
offset=0
pfi=open(filename,'rb')
while 1:
  icks=0
  chunk=pfi.read(256)
  if not chunk:  break     #if EOF exit loop

  for iter in chunk:
    icks+=ord(iter)
    print ord(iter)
  cksum=(cksum+icks) & 0xffff
pfi.close()
print "cksum=0x%4.4x"%cksum

And I'm trying to convert it to Java but I'm not geting the same results.

Here's my Java code:

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ChecksumCalculator {

private ChecksumCalculator() {
}

public static int getChecksum(File file) {
    int cksum = 0;
    FileInputStream fis = null;
    BufferedInputStream bis = null;
    DataInputStream dis = null;
    try {
        fis = new FileInputStream(file);

        // Here BufferedInputStream is added for fast reading.
        bis = new BufferedInputStream(fis);
        dis = new DataInputStream(bis);
        byte[] buffer = new byte[256];
        // dis.available() returns 0 if the file does not have more lines.
        while (dis.read(buffer) != -1) {
            int icks = 0;
            for (byte b : buffer) {
                icks += b & 0xff;
                System.out.println(b & 0xff);
            }
            cksum = (cksum + icks) & 0xffff;
            System.out.println("Checksum: " + cksum);
        }

        // dispose all the resources after using them.
        fis.close();
        bis.close();
        dis.close();
        return cksum;
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        return -1;
    } catch (IOException e) {
        e.printStackTrace();
        return -1;
    }
}

static public void main(String[] s) {
    System.out.println("0x" + getChecksum(new File("H:\\Javier Ortiz\\559-7 From Pump.bin")));
}

}

But I get different results on a file. For example if I run it on a plain txt file containing only the word test it gives out the following result:

python: cksum=0x01c0 java: cksum=0x448

Any idea?

+5  A: 

Your Python version prints the checksum in hex, while your Java version prints it in decimal. You should make your Java version print in hex, too. 0x1c0 == 448.

To use the cksum=0x%4.4x format string as you had in your Python version, use this:

System.out.printf("cksum=0x%4.4x%n", ...);

or even better

System.out.printf("cksum=%#04x%n", ...);

Also, you don't need a DataInputStream for this. Just use bis.read(buffer) instead of dis.read(buffer).

Chris Jester-Young
Using bis.reader gave me the same icks values. Any idea on how to print hex in Java as well? I tried java.lang.Integer.toHexString without seeing a change.
javydreamercsw
Using your System.out format still outputs 0x448
javydreamercsw
Don't mind the last comment. I just needed to clean and build. Thanks!
javydreamercsw
+3  A: 

1C016 = 44810

I think that's your problem.

jdmichal
+1  A: 
  1. dis.read(buffer) returns the number of bytes that was actually read. For the last chunk, it will probably be less than 256. So the for loop shouldn't always be performed 256 times - it should be performed as many times as the actual byte count that was read from the stream.

  2. I'm not a Python developer, but it doesn't look like ord(icks) in Python does the same as b & 0xff in Java.

  3. Keep in mind that all Java types are signed; this might affect the calculation.

Also, although this doesn't affect correctness - it's a good practice to clean all the resources (i.e. to close the streams) in a finally block.

Eli Acherkan
Thanks. Changed that line to:for (int i = 0; i < bis.read(buffer); i++) {
javydreamercsw
javydreamercsw