Hallo,
ich möchte ein Programm erstellen, dass Bytes aus einer Datei ausliest.
Das kriege ich noch hin. Doch ich scheitere daran, dass jeweils 2 Bytes zu einer 16Bit Integerzahl zusammengelegt werden, und das im LittleEndian Format.
Wie geht das am besten?
Vielen Dank!
danke.
das mit dem shiften << habe ich schon öfters gelesen, was genau ist das?
und wieso addieren? ich addiere die Zahlen ja nicht ich hänge ihre Bytes nur aneinander.
Gibt es keine KLase dafür (in .Net z.b. BitConverter). Was ist denn mit der KLasse ByteBuffer,
kann die sowas nicht? Davon habe ich nämlich mal was gelesen ...
Das besser Verfahren statt der Addition ist das binäre OR. Um sauber mit negativen Zahlen arbeiten zu können, ist die Maskierung mit dem binären AND notwendig.
Da Du Litte Endian wünschst (also kleinstes Byte ist zuerst im "Stream"), musst Du wie folgt vorgehen:
Code:
byte [] yourArray;
int size = yourArray.length>>1; // gleich / 2
int [] resultArray = new int[size];
for (int index=0; i<size; i++)
{
int index = i<<1;
resultArray[i] = ((byte)(yourArray[index] & 0xFF)) | (((byte)(yourArray[index+1] & 0xFF))<<8) & 0xFFFF;
// Signed nachvollziehen:
if ((resultArray[i] & 0x8000) != 0) resultArray[i] |= 0xFFFF0000;
}
Das Zweierkomplement wird hier nachträglich getrickst, da andernfalls keine negativen Zahlen kommen würden.
Was ist Shiften?!
Das mit dem Shiften ist im Zehnersystem auch möglich. Dort kommt es einer Multiplikation/Division mit 10 gleich. 3*10 = 30, 30*10 = 300 und so weiter.
Da das Binärsystem zur Basis zwei ist, ist Shiften mit einer Multiplikation/Division mit 2 gleichzusetzen. Intern werden die Bits allerdings tatsächlich roliert. Das aus der Zahlendarstellung herausfallende Bit kommt dabei in's Carry-Flag, so daß man Überläufe auch erkennen kann.
super danke quippy so werde ich das jetzt mal machen.
nur deinen letzten schritt verstehe ich nicht :cry:
warum verknüpfe ich meine zahl noch mal mit 0xFFFF0000 um das vorzeichen rauszukriegen?
dadurch kriege ich doch einfach eine 4 Byte Zahl, die erste 2 Bytes alles Einsen und der Rest ist meine eigentliche Zahl?
das passiert ja auch nur bei 0x8000, also wenn das 16. Bit eine 1 ist, was für eine negative Zahl steht,
und damit das dann auch in Java-32-bit-int eine negative Zahl ist müsssen die Einsen da rein:
Code:
public class Test
{
public static void main(String[] args)
throws Exception
{
int k = (int)Math.pow(2, 15);
System.out.println(k + " - " + Integer.toBinaryString(k));
if ((k & 0x8000) != 0)
{
k |= 0xFFFF0000;
}
System.out.println(k + " - " + Integer.toBinaryString(k));
}
}
achso ok danke also bei ner 32 Bit Zahl zählen die ersten 16 bits praktisch als -wert richtig? ist das nur bei 32 bit werten so?
und @ gast was ist das für ein beispiel? da versteh ich ja mal gar nix -.-
achso ok danke also bei ner 32 Bit Zahl zählen die ersten 16 bits praktisch als -wert richtig? ist das nur bei 32 bit werten so?
und @ gast was ist das für ein beispiel? da versteh ich ja mal gar nix -.-
Damit kanst du die ganze Datei, unter brücksichtigung von Byte-Order, komplett auslesen, statt die Bytes "von Hand"
zu Integern zusammen zu kleistern. Java bietet mit der NIO API die nötige Funkionalität, warum diese nicht auch
verwenden.
Die Pufferung ist sauschnell. Ich kann damit z.B. 100 TIFF - Header innerhalb von 150ms auslesen und darin sämtliche
IFD-Einträge auswerten. Darauf basierend ein Index mit Offsets der Thumbnails, EXIFs und IPTC-Daten aufbauen, um
diese bei Bedarf schnell laden zu können.
häh, und wie kann ich dann eine 8 Bit lange Zahl negativ darstellen? und woher weiß java die zahl nicht einfach 32Bits lang ist anstatt der negtiven darstellung?
> häh, und wie kann ich dann eine 8 Bit lange Zahl negativ darstellen?
nach dem gleichen System, dann sind die ersten 24 Bits eine 1
> und woher weiß java die zahl nicht einfach 32Bits lang ist anstatt der negtiven darstellung?
was hat die negative Darstellung mit der Länge der Zahl zu tun bzw. wo siehst du da einen Konflikt?
das ist ein konsistentes System,
nur wenn man die Zahl wie in diesem Thread aus Bytes zusammenbaut ist die Negation noch nicht korrekt,
deshalb ja der Code von quippy:
> if ((resultArray & 0x8000) != 0) resultArray |= 0xFFFF0000;
hm jo danke ich probiers erstmal mit methode 1.
es klappt auch, nur komischerweise erhalte ich teilweise andere ergebnisse als mit c# -.-
denn die eingelesen bits sind teilweise unterschiedlich.
Ich lese meine Bits so ein:
import java.io.*;
public class fileReader
{
public byte[] einlesen(String datei)
{
try
{
BufferedReader reader = new BufferedReader(new FileReader(datei));
byte line;
byte[] binhalt = new byte[(int)new File(datei).length()];
int c;
int i = 0;
while ((c = reader.read()) != -1)
{
binhalt = (byte)c;
i++;
}
hm ja gut ich machs mal mit dem mappedbytebuffer
nur wollte erstmal das "manuell" probieren, die bits mit dem bufferedreader einlesen( das müsste doch gehn oder?) und dann selber shiften und so ...
Merkst du was? Du hast eine Binärdatei, kannst daher diesen Reader nicht verwenden.
Wenn du es von Hand machen möchtest, mach's so, wie 'SlaterB' vorgeschlagen hat. Ansonsten mit NIO,
wie in meinem Beispiel (ich war mal wieder als Dauergast nicht eingelogt) gezeigt.