There is an algorithm for calculating the CRC function written in C. It is necessary to add this function to an application written in Java. The problem is that in C, unsigned int is commonly used, and in Java, int is always signed. Because of this copy-paste (of course, with adaptation to the Java syntax), the code cannot be transferred. Quickly googled found an alternative in the form of JNI, but this is a "crutch bolted to the bike," and I would like to implement it in Java. Tell me how to make the transfer without changing the original logic?

// Include Files #include <stdlib.h> #include <stdio.h> // Preprocessor Constants #define byte char #define word_32 unsigned long int #define BUFSIZE 1024 // Size of file buffer in bytes #define G 0x04C11DB7 // The generator G #define Init 0xFFFFFFFF // Initialization value for CRC_value #define TABLEN 256 // Length of look-up table #define XorOut 0xFFFFFFFF // To be XORed to final CRC_value // Global (file scope) Variables static byte Buffer[BUFSIZE]; // The file buffer static word_32 CRC_value; // Holds the running CRC value static FILE* fp; // File pointer static size_t nb; // Number of bytes read from file static word_32 table[TABLEN]; // Look-up Table // Function Prototypes to Resolve Forward Referencing (See below) static void CRCBuffer (int); static void InitTable (void); void main(int argc, char* argv[]) // argv[1] is FILENAME { // The operator must supply a FILENAME if (argc != 2) { printf("Error: Command line must contain a FILENAME\n"); } // We must be able to open that file else if ((fp=fopen(argv[1],"rb"))== NULL) { printf("Error: Can't open input file\n"); } // Otherwise compute CRC else { // Initialize the look-up table InitTable(); // Initialize the CRC value CRC_value = Init; // Loop for each BUFSIZE (or less) block of bytes in FILENAME while (!feof(fp)) { // Attempt to read a block of BUFSIZE bytes nb=fread(Buffer,sizeof(char),BUFSIZE,fp); // If any bytes were read, compute the running CRC_value // for them if (nb>0) { CRCBuffer(nb); } } // Apply XorOut CRC_value ^= XorOut; // Close FILENAME fclose(fp); // Report printf("CRC = %08X\n",CRC_value); } } static void InitTable(void) { word_32 generator = G; // CRC generator word_32 shift_reg; // A shift register word_32 leading_bit; // MSB of shift_reg before shift int i; // Index into table 0..TABLEN int k; // Bit index into byte 7..0 for (i=0; i<TABLEN; i++) { shift_reg = ((word_32)i << 24); for (k=7; k>=0; k--) { leading_bit = shift_reg & 0x80000000; shift_reg = shift_reg << 1; if (leading_bit) { shift_reg = shift_reg ^ generator; } } table[i] = shift_reg; } } static void CRCBuffer(int nb) { int i; // Byte index into buffer int k; // Index into look-up table // Loop for each byte in Buffer for (i=0; i<nb; i++) { // Compute index into look-up table for the current byte k = ( (CRC_value>>24) ^ (int)Buffer[i] ) & 0xFF; // Update the running CRC_value for the curtrent byte CRC_value = (CRC_value << 8) ^ table[k]; } } 
  • one
    Or maybe you have a ready implementation suitable? For example docs.oracle.com/javase/7/docs/api/java/util/zip/CRC32.html - Vladimir Martyanov
  • @ Vladimir Martiyanov In the docks are not listed in. parameters (the same polynomial), and the test results in a different value. I need the same values. - I. Perevoz
  • And you specify for the byte string 0x31, 0x32, 0x33, 0x34, 0x35 (that is, "12345") what the result should be. Your 0x04C11DB7 is a standard CRC32, which makes me think about the misuse of the Java implementation. - Vladimir Martyanov
  • one
    @ I.Perevoz, so checking something is a matter of a couple of seconds ... Either remove xor xor, add javascript to the result, or something else :) - PinkTux
  • one
    Probably when converting a negative Int (type crc int) to a long, the character is preserved, which is why the most significant 32 bits out of 64 will be filled with ones. & ffffffffL to clear these bits. - Sergey

1 answer 1

Here is an example

 CRC32 crc32 = new CRC32(); FileChannel fc = FileChannel.open(Paths.get("path/to/file.ext"), StandardOpenOption.READ); MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); for (int i = 0; i < mbb.limit(); i++) crc32.update(mbb.get(i)); // Π±Π°ΠΉΡ‚ Π·Π° Π±Π°ΠΉΡ‚ΠΎΠΌ скармливаСм crc32 fc.close(); // ΠΊΠΎΠ³Π΄Π° всё соТрал, ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ ΠΊΠ°ΠΊ ΠΎΠ½ ΠΈΡ… ΠΏΠ΅Ρ€Π΅Π²Π°Ρ€ΠΈΠ» long checksum = crc32.getValue(); System.out.println(checksum);