Toon posts:

[Java] bytes vergelijken

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik wil van een bestand bepalen of het een WP bestand is. Daarvoor moet ik de eerste 4 bytes van het bestand bekijken. Ik heb een bestand bekeken met Ultra edit, en ben er daardoor achter gekomen dat een WP bestand altijd begint met de volgende 4 bytes (in hex): FF 57 50 43

Maar, hoe vergelijk ik nu die 4 bytes met de waarden die ik wil hebben?
Ik zat zelf te denken aan het volgende:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  public File convert(File input, File output){
    // check if it's a WPCorp file
    try {
      FileInputStream fis = new FileInputStream(input);
      byte[] bytes = new byte[4];
      fis.read(bytes);
      if (bytes[0] == 0xFF && bytes[1] == 0x57 && bytes[2] == 0x50 && bytes[3] == 0x43){
        System.out.println(input.getName()+" is a WPCorp. file");
      } else {
        System.out.println(input.getName()+" is not a WPCorp. file. Expected FF 57 50 43. Found: "+
                           Integer.toHexString(bytes[0])+" "+
                           Integer.toHexString(bytes[1])+" "+
                           Integer.toHexString(bytes[2])+" "+
                           Integer.toHexString(bytes[3])+" ");
      }
// nog wat niet relevante code
}


resultaat:
260057z.001 is not a WPCorp. file. Expected FF 57 50 43. Found: ffffffff 57 50 43

Dat gaat dus niet goed.Ik gebruik overigens Integer.toHexString() omdat Byte en Short geen toHexString hebben.

Mijn vraag: hoe maak ik het zo dat het wel werkt?

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15-05 06:45
Ik vermoed dat het fout gaat bij de vergelijking in de eerste byte. Java bytes zijn signed, maar het zou zomaar kunnen dat Java bij vergelijkingen waarden converteert naar integers (dat is in ieder geval in C++ zo). Op die manier wordt de byte 0xFF dus 0xFFFFFFFF die je vervolgens vergelijkt met de integer 0x000000FF.

Om te testen of het daar mis gaat, kun je de eerste controle eruit halen om te zien of het dan wel goed gaat. Zo ja, dan zou je moeten vergelijken met -1 in plaats van 0xFF ofzoiets.

Overigens begint volgens de UNIX file magic library een WordPerfect bestand met de string "\377WPC\020\000\000\000\022\012\001\001\000\000\000\000"; die eerste vier karakters komen dus overeen, maar je zou nog wat extra karakters mee kunnen nemen om false positives uit te sluiten.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:08

.oisyn

Moderator Devschuur®

Demotivational Speaker

Als je slim bent definieer je die bytes waarmee je wilt vergelijken als een array en loop je ze gewoon simpelweg af. Geen conflicten met bytes die naar ints gecast worden en ook geen lange onleesbare if-statements :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Soultaker: Ik heb het nu opgelost door de eerste byte te vergelijken met 0xFFFFFFFF. Dat werkt, maar ik vind het niet echt een mooie oplossing...

Overigens heb ik voor dit programma niet meer dan 4 bytes nodig, maar bedankt voor de info :)

.oisyn: goed idee, maar hoe? Geeft Byte.parseByte("FF", 16) de byte terug die ik wil hebben?

Verwijderd

een integer is signed 2's complement 32 bits , dus als je een "platte" byte cast naar een integer... juistem, dan gaat het fout, zoals je al merkte
zie hier voor een beschrijving van hoe een Integer eruit ziet in java inclusief handleiding hoe en wat er gebeurt met casten naar andere types

0xFF in signed 2's complement is -1 als decimale waarde
vandaar dat als je naar Integer cast het 0xFFFFFFFF wordt
(ook -1, maar dan 32 ipv 8 bits)

soultaker zei al hetzelfde 8)7

[ Voor 45% gewijzigd door Verwijderd op 23-11-2004 18:17 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:08

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op dinsdag 23 november 2004 @ 15:22:
.oisyn: goed idee, maar hoe? Geeft Byte.parseByte("FF", 16) de byte terug die ik wil hebben?
Waar heb je die parseByte functie voor nodig dan?

Java:
1
2
3
4
5
6
7
8
9
byte[] magic = { 0x01, 0x02, 0x03, 0x04, 0x05 };  // de magic data

byte[] buf = new byte[magic.length];
file.read (buf);
for (int i = 0; i < magic.length; i++)
    if (buf[i] != magic[i])
        throw new NotAWordPerfectFileException ();

// all ok

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

en om de ingelezen waardes om te zetten in een Hex string doe je
code:
1
2
3
4
5
6
7
8
System.out.println(
   Integer.toHexString(
              bytes[0] * 256*256*256 + 
              bytes[1] * 256*256 + 
              bytes[2] * 256 + 
              bytes[3]
              ).toUpperCase()
   );

de spaties moet je er wel ff zelf tussen friemelen dan ;)

[ Voor 14% gewijzigd door Verwijderd op 23-11-2004 18:03 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:08

.oisyn

Moderator Devschuur®

Demotivational Speaker

Niet zo handig, dan zit je altijd aan 4 bytes vast

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1