exodist has asked for the wisdom of the Perl Monks concerning the following question:

I have an array with 4 elements, each has 512 bytes read into it from different parts of a file.
sysread(DEV,$Array[N],512)

All for places in the file should be exact copies of eachother, as in all 4 elements of the array should now contain the same exact binary data.

The binary data is mixed, it contains a lot of different things, integers, strings, a UUID, etc. I would rather not decode it all for each of them just to compare them. Is there an operator like == or eq or a function that compares them? my searches have been unfruitful. I have already tried eq and ==.

Replies are listed 'Best First'.
Re: Test binary equality?
by graff (Chancellor) on Jun 21, 2007 at 03:12 UTC
    Your actual code does not really contain a bareword "N" between square brackets, does it? That would be bad. Show us more code, because (as the other reply says) the eq comparison of two 512-byte array elements should do the right thing (report true iff the two elements are in fact identical), as demonstrated below:
    #!/usr/bin/perl use strict; my @array; my $bgn = 0; for ( 0..2 ) { push @array, pack( "c*", $bgn .. $bgn+511 ); $bgn += 128; } # pack "c*" will only use the low 8 bits and strip off the higher ones +, so # $array[0] will be identical to $array[2] for ( 1, 2 ) { my $cmp = ( $array[0] eq $array[$_] ) ? "matches" : "differs from" +; print "element 0 $cmp element $_\n"; } __OUTPUT__ element 0 differs from element 1 element 0 matches element 2
Re: Test binary equality?
by ysth (Canon) on Jun 21, 2007 at 02:33 UTC
    eq should do exactly what you want. Can you show how it didn't seem to work for you?
      my @SB; my $Temp; sysopen(DEV, $Device, O_RDWR | O_SYNC) || die("Error: $!\n"); sysseek(DEV,0,0) || die("$!\n"); sysread(DEV,$SB[0],512) || die("1 $!\n"); sysseek(DEV,0,0) || die("$!\n"); sysread(DEV,$SB[1],512) || die("2 $!\n"); sysseek(DEV,-1024,2) || die("$!\n"); sysread(DEV,$SB[2],512) || die("3 $!\n"); sysseek(DEV,-512,2) || die("$!\n"); sysread(DEV,$SB[3],512) || die("4 $!\n"); if (!($SB[0] eq $SB[1])) { my @Pair; warn("Error, First 2 superblocks do not match! Checking third. +.."); foreach my $I (0 .. 1) { @Pair = ($I,2) if ($SB[$I] eq $SB[2]); } if (!((@Pair[0]) && (@Pair[1]))) { warn("Error, First 3 superblocks do not match! Checking fo +urth and final..."); foreach my $I (0 .. 2) { @Pair = ($I,3) if ($SB[$I] eq $SB[3]); } if (!((@Pair[0]) && (@Pair[1]))) { die("All 4 superblock copies are different! This is ma +jior corruption.\n"); } } $SB[0] = $Pair[1]; }
      I know that they are not equal though, here are the first 1024 bytes:
      Abydos OEFS # hexdump -C -n 1024 /dev/sdf1 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |......... +.......| * 00000200 4f 45 46 53 2d 30 30 30 30 2e 30 30 30 30 30 30 |OEFS-0000 +.000000| 00000210 f0 26 3f f0 9d 1f dc 11 93 c2 d9 64 65 f2 e8 c0 |.&?...... +..de...| 00000220 53 74 72 75 01 00 00 00 00 00 00 00 00 00 00 00 |Stru..... +.......| 00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |......... +.......| * 00000400
        Your first two seeks are to the same position.

        !(... eq ...) is usually written ... ne ...

        At the top of this thread, you said:

        All for places in the file should be exact copies of eachother, as in all 4 elements of the array should now contain the same exact binary data.

        (You meant "all four places", right?) But your hexdump of the device/file indicates that the third block of 512 bytes (starting at offset 0x200) is different from the other three (starting at 0, 0x100 and 0x300).

        Meanwhile, in your code snippet, I'm having trouble tracking your intent with the four "sysseek/sysread" pairs -- looks like the first two amount to reading the same block twice (?? -- was that a copy/paste error?).

        And as for the third and fourth pairs, you didn't mention how big the file actually is, and in any case, seeking from the end of the file seems like an unnecessary complication (possibly a mistake).

        Since the first two reads (first two elements of the array) are in fact the exact same data (from the same position in the file), your initial "if" block is never entered. (And why did you say  if (!($SB[0] eq $SB[1])) instead of the simpler  if ( $SB[0] ne $SB[1] )?)

        So, what's the problem again? I don't think it's the "eq" (or "ne") comparison... I think it's a mistake in how you are reading the data from the file.

Re: Test binary equality?
by swampyankee (Parson) on Jun 21, 2007 at 02:56 UTC

    If ysth's answer doesn't work, which seems unlikely (eq is the operator for string equality), you could try Digest, and compare the resulting signatures.

    Of course, the de rigeur comment "Show us your code and data" must be added.

    emc

    Any New York City or Connecticut area jobs? I'm currently unemployed.

    There are some enterprises in which a careful disorderliness is the true method.

    —Herman Melville