[java] FileInputStream.read() geeft negatieve waarde

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • IceM
  • Registratie: Juni 2003
  • Laatst online: 17:43
Hallo,

Voor het parsen van een binair bestand moet ik een aantal bytes inlezen waarna deze omgezet worden naar de integer waarde die ze representeren (16, 24 en 32 bits integers).

Om de byte waarden in te lezen gebruik ik in java een FileInputReader waarmee ik via read() 1 byte in kan lezen of via read(byte[] buffer) een X aantal bytes in te lezen.

Dit lijkt goed te gaan, echter, ik krijg negatieve waarden terug in een aantal gevallen. Als ik de java documentatie er op na lees moet dit helemaal niet kunnen (-1 bij een fout, of anders een waarde tussen van 0 tot 255). Het omzetten van de ingelezen waarden gaat dus ook niet goed, de int waarde klopt niet (logisch).

Ik heb bijna exact dezelfde code in C# gemaakt waarmee alles wel goed gaat.

Voorbeeld code java:
Java:
1
2
3
4
5
    private int bigEndInt16(BufferedInputStream  fs) throws IOException {
        byte[] buffer = new byte[2];
        int bytesRead = fs.read(buffer);
        return (buffer[1] + (buffer[0] << 8));
    }


Voorbeeld code C#:
C#:
1
2
3
4
5
6
        private int BigEndianInt16(ref FileStream fs)
        {
            byte[] buffer = new byte[2];
            fs.Read(buffer, 0, 2);
            return (buffer[1] + (buffer[0] << 8));
        }


Doe ik iets fout of is dit een bug in java? Het vage is dat de java code soms wel gewoon correct werkt.
Hij gaat onder andere fout op de volgende 2 byte waarden: 03 0F. Het resultaat dat ik krijg is: 03 -58 (decimaal). Voor de controle heb ik de returnwaarde van read in Java ook bekeken, maar hij geeft gewoon aan dat er 2 bytes gelezen zijn. Uit wanhoop nog gekeken of fs.read(buffer); en fs.read(buffer, 0, 2); wat uit maakt, maar beiden geven hetzelfde (foute) resultaat.

...


Acties:
  • 0 Henk 'm!

  • bobo1on1
  • Registratie: Juli 2001
  • Laatst online: 18-05 17:57
Moet je de byte niet eerst casten naar int voor je gaat shiften?

edit: wel zorgen dat byte unsigned is, anders loopt de cast in de soep.

[ Voor 36% gewijzigd door bobo1on1 op 30-01-2009 20:35 ]

Impedance, a measure of opposition to time-varying electric current in an electric circuit.
Not to be confused with impotence.


Acties:
  • 0 Henk 'm!

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 19:03

Robtimus

me Robtimus no like you

De return waarde van read() (zonder parameters) geeft idd alleen -1 als negatieve waarde terug. Zodra je echter bytes inleest dan is de waarde van elke byte nog steeds beperkt tot de range voor bytes: -128 tot 127. Als de waarde negatief is zul je er dus 256 bij moeten optellen.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


Acties:
  • 0 Henk 'm!

  • Salandur
  • Registratie: Mei 2003
  • Laatst online: 00:23

Salandur

Software Engineer

een negatieve waarde betekend niets meer en niets minder dan dat het einde van het bestand is bereikt.

je moet toch een manier hebben om het einde van een bestand te detecteren. met de methode availible() kan je zien hoeveel bytes er nog beschikbaar zijn in je input stream.

het staat trouwens gewoon in de javadocs:
http://java.sun.com/javas...edInputStream.html#read()
IceManX schreef op vrijdag 30 januari 2009 @ 20:34:
De return waarde van read() (zonder parameters) geeft idd alleen -1 als negatieve waarde terug. Zodra je echter bytes inleest dan is de waarde van elke byte nog steeds beperkt tot de range voor bytes: -128 tot 127. Als de waarde negatief is zul je er dus 256 bij moeten optellen.
bytes in java zijn altijd unsigned. int's zijn signed geloof ik. ik maak er zelf niet zovaak gebruik van om precies teweten hoe het een en ander zit.

[ Voor 58% gewijzigd door Salandur op 30-01-2009 21:02 . Reden: javadoc ]

Assumptions are the mother of all fuck ups | iRacing Profiel


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 21:37

Creepy

Tactical Espionage Splatterer

Salandur schreef op vrijdag 30 januari 2009 @ 20:54:

bytes in java zijn altijd unsigned. int's zijn signed geloof ik. ik maak er zelf niet zovaak gebruik van om precies teweten hoe het een en ander zit.
No offence maar als je het niet weet, zoek het dan op. Een byte in java is altijd signed. Dus 128 tot 255 terugkrijgen kan niet, dat wordt een negatieve waarde. Met een beetje ge-google kom je al snel uit op iets als http://www.lykkenborg.no/...nsigned-byte-in-java.html

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 05:13

Gerco

Professional Newbie

Salandur schreef op vrijdag 30 januari 2009 @ 20:54:
een negatieve waarde betekend niets meer en niets minder dan dat het einde van het bestand is bereikt.
Alleen via de method "int read()". Er is geen method read() die een enkele byte terug geeft, er is wel een read(byte[], int, int) method die een buffer volleest. Deze method returnt ook -1 wanneer de stream op is, maar een -1 in de buffer is gewoon de waarde uit de stream.
bytes in java zijn altijd unsigned. int's zijn signed geloof ik. ik maak er zelf niet zovaak gebruik van om precies teweten hoe het een en ander zit.
Java kent geen unsigned types, een byte in Java is dus net zo signed als een int. -128 t/m 127 zijn de geldige waardes voor een byte. Als je een signed byte waarde wilt omzetten naar de unsigned representatie (hier moet je dan een groter type voor gebruiken, zoals int of short) kun je zoiets doen:
Java:
1
2
  byte signedByte = -100;
  int unsignedByte = signedByte & 0xFF;

[ Voor 3% gewijzigd door Gerco op 30-01-2009 21:22 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


Acties:
  • 0 Henk 'm!

  • IceM
  • Registratie: Juni 2003
  • Laatst online: 17:43
Het einde van het bestand is helemaal niet bereikt, het bestand is > 10MB en deze test is uitgevoerd op byte 47. read() geeft ook gewoon 2 terug wat aangeeft dat er 2 bytes zijn gelezen. Ik kan ook gewoon de volgende bytes uitlezen (dat gaat dus alleen niet altijd goed). -1 geeft aan dat het einde van het bestand bereikt is, -58 niet -> "The character read, as an integer in the range 0 to 65535 (0x00-0xffff), or -1 if the end of the stream has been reached".

Edit: Ik heb nu even geen tijd om te testen of het idd te maken heeft met het feit dat bytes signed zijn, ik zal het morgen even testen

[ Voor 14% gewijzigd door IceM op 30-01-2009 21:29 ]

...


Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

IceM schreef op vrijdag 30 januari 2009 @ 21:25:
Het einde van het bestand is helemaal niet bereikt, het bestand is > 10MB en deze test is uitgevoerd op byte 47. read() geeft ook gewoon 2 terug wat aangeeft dat er 2 bytes zijn gelezen.
Geeft read(buffer) ook 2 terug op het moment dat je die twee bytes in kwestie inleest? Je controleert het in de code niet en het eenmalig by debuggen controleren is niet afdoende: je moet het iedere keer controleren, omdat read(buffer) niet garandeert dat de buffer geheel gevuld wordt.
Ik kan ook gewoon de volgende bytes uitlezen (dat gaat dus alleen niet altijd goed). -1 geeft aan dat het einde van het bestand bereikt is, -58 niet -> "The character read, as an integer in the range 0 to 65535 (0x00-0xffff), or -1 if the end of the stream has been reached".
Je haalt nu dingen door elkaar, want read() en read(buffer) geven bytes terug, geen characters.

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • Salandur
  • Registratie: Mei 2003
  • Laatst online: 00:23

Salandur

Software Engineer

Creepy schreef op vrijdag 30 januari 2009 @ 21:17:
[...]

No offence maar als je het niet weet, zoek het dan op. Een byte in java is altijd signed. Dus 128 tot 255 terugkrijgen kan niet, dat wordt een negatieve waarde. Met een beetje ge-google kom je al snel uit op iets als http://www.lykkenborg.no/...nsigned-byte-in-java.html
Je hebt gelijk, heb het even opgezocht in de language specificaties. (http://java.sun.com/docs/...html/typesValues.html#4.2). Altijd nuttig om even je kennis op te frissen :)

Assumptions are the mother of all fuck ups | iRacing Profiel


Acties:
  • 0 Henk 'm!

  • IceM
  • Registratie: Juni 2003
  • Laatst online: 17:43
Bedankt voor de hulp, het had inderdaad te maken met het feit dat bytes signed zijn in java. Het omzetten naar een int en de and operatie uitvoeren geeft het juiste resultaat. Beetje stom dat ik daar zelf niet aan gedacht heb omdat ik eigenlijk wel wist dat java geen unsigned types kent :/.

...


Acties:
  • 0 Henk 'm!

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 19:03

Robtimus

me Robtimus no like you

Salandur schreef op vrijdag 30 januari 2009 @ 20:54:
een negatieve waarde betekend niets meer en niets minder dan dat het einde van het bestand is bereikt.

je moet toch een manier hebben om het einde van een bestand te detecteren. met de methode availible() kan je zien hoeveel bytes er nog beschikbaar zijn in je input stream.
Het gebruik van available() werkt zelden zoals je bedoelt. Deze method returned niet het aantal bytes dat in totaal beschikbaar is, maar het aantal bytes dat kan worden gelezen zonder te blocken. Als de return waarde 0 is betekent dat alleen dat er op dat moment niets beschikbaar is.

De return waarde van read(), read(byte[]) en read(byte[], int, int) is het enige dat je kunt gebruiken om te bepalen of je echt alles hebt gelezen.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


Acties:
  • 0 Henk 'm!

  • Jaap-Jan
  • Registratie: Februari 2001
  • Laatst online: 23:24
offtopic:
Ik lees al een paar keer dat Java geen unsigned datatypes heeft, maar Java er wel degelijk 1, namelijk char. :)

| Last.fm | "Mr Bent liked counting. You could trust numbers, except perhaps for pi, but he was working on that in his spare time and it was bound to give in sooner or later." -Terry Pratchett


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 22-09 14:14

Matis

Rubber Rocket

Jaap-Jan schreef op zondag 01 februari 2009 @ 12:27:
offtopic:
Ik lees al een paar keer dat Java geen unsigned datatypes heeft, maar Java er wel degelijk 1, namelijk char. :)
Klopt, een char loopt van 0 tm 255.

Char komt van karakter ;) en dat hangt dan weer aan ASCII en ASCII loopt (je raad het nooit ;)) van 0 tm 255 waardes.

Ik doe readlines (of read) altijd in char(arrays) opslaan, vooral omdat het altijd een waarde van 0 tm 255 is en om die reden je altijd karakters inleest

[ Voor 16% gewijzigd door Matis op 01-02-2009 14:08 ]

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 05:13

Gerco

Professional Newbie

toaomatis schreef op zondag 01 februari 2009 @ 14:08:
Klopt, een char loopt van 0 tm 255.

Char komt van karakter ;) en dat hangt dan weer aan ASCII en ASCII loopt (je raad het nooit ;)) van 0 tm 255 waardes.
Sorry, maar dat klopt niet.
char: The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).
Een char heeft helemaal *niets* met ASCII te maken. Dat is precies de denkwijze die er voor zorgt dat de wereld stampvol zit met encoding en charset issues en dat niemand er meer iets van begrijpt wanneer er accenten of andere non-ascii tekens gebruikt worden. Zie ook The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) (Joel Spolsky).

Overigens is een boolean ook unsigned en een String ook. Een char is geen numeriek type dus signedness heeft er weinig mee te maken. Dat je het redelijk makkelijk als numeriek kan gebruiken maakt het nog niet zo :)

Ik weet dat een String geen primitive type is, dat doet er even niet toe...

[ Voor 25% gewijzigd door Gerco op 01-02-2009 14:34 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


Acties:
  • 0 Henk 'm!

  • larsvliet
  • Registratie: April 2006
  • Laatst online: 03-10-2023
Waarom gebruik je geen DataInputStream?
Hiermee kan je namelijk unsigned waardes inlezen bijv readUnsignedByte.

http://java.sun.com/j2se/...a/io/DataInputStream.html

Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
larsvliet schreef op zondag 01 februari 2009 @ 15:28:
Waarom gebruik je geen DataInputStream?
Hiermee kan je namelijk unsigned waardes inlezen bijv readUnsignedByte.

http://java.sun.com/j2se/...a/io/DataInputStream.html
Niet doen, dat werkt alleen als de input gemaakt is met een DataOutputStream.

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 22-09 14:14

Matis

Rubber Rocket

Gerco schreef op zondag 01 februari 2009 @ 14:30:
Sorry, maar dat klopt niet.
Ik weet dat een String geen primitive type is, dat doet er even niet toe...
Damn you got me on that :$

Ik wist dat niet eens, maargoed weer wat geleerd *O*

Wat betreft die string, slecht voorbeeld, maar je geeft wel aan dat het geen primitief type is.

een string is dan weer een char* of een char[] (c++).

En wat betreft die DataInputStream, nooit!!! gebruiken wanneer je niet weet wat de stream gemaakt heeft.

Dat kan wel eens nare gevolgen hebben voor je output (of input :p)

If money talks then I'm a mime
If time is money then I'm out of time

Pagina: 1