Ich lese eine Binärdatei wie folgt:
InputStream in = new FileInputStream( file );
byte[] buffer = new byte[1024];
while( ( in.read(buffer ) > -1 ) {
int a = // ???
}
Was ich tun möchte, um bis zu 4 Bytes zu lesen und daraus einen int-Wert zu erstellen, aber ich weiß nicht, wie es geht.
Ich habe das Gefühl, ich muss 4 Bytes gleichzeitig greifen und eine "Byte" -Operation ausführen (wie >> << >> & FF und ähnliches), um das neue Int zu erstellen
Was ist die Redewendung dafür?
BEARBEITEN
Hoppla, das ist etwas komplexer (um es zu erklären).
Ich versuche, eine Datei zu lesen (kann ASCII, binär sein, spielt keine Rolle) und die Ganzzahlen zu extrahieren, die sie möglicherweise hat.
Angenommen, der binäre Inhalt (in Basis 2):
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010
Die ganzzahlige Darstellung sollte sein 1
, 2
oder? : - / 1 für die ersten 32 Bits und 2 für die verbleibenden 32 Bits.
11111111 11111111 11111111 11111111
Wäre -1
und
01111111 11111111 11111111 11111111
Wäre Integer.MAX_VALUE ( 2147483647 )
quelle
Wenn Sie sie bereits in einem Byte [] -Array haben, können Sie Folgendes verwenden:
int result = ByteBuffer.wrap(bytes).getInt();
Quelle: hier
quelle
Sie sollten es in eine Funktion wie diese einfügen:
public static int toInt(byte[] bytes, int offset) { int ret = 0; for (int i=0; i<4 && i+offset<bytes.length; i++) { ret <<= 8; ret |= (int)bytes[i] & 0xFF; } return ret; }
Beispiel:
byte[] bytes = new byte[]{-2, -4, -8, -16}; System.out.println(Integer.toBinaryString(toInt(bytes, 0)));
Ausgabe:
11111110111111001111100011110000
Dies sorgt dafür, dass keine Bytes mehr zur Verfügung stehen und negative Bytewerte korrekt behandelt werden.
Mir ist keine Standardfunktion dafür bekannt.
Zu berücksichtigende Punkte:
Endianness: Verschiedene CPU-Architekturen ordnen die Bytes, aus denen ein Int besteht, in unterschiedlicher Reihenfolge an. Abhängig davon, wie Sie zunächst auf das Byte-Array gekommen sind, müssen Sie sich möglicherweise darüber Gedanken machen. und
Pufferung: Wenn Sie jeweils 1024 Bytes erfassen und eine Sequenz bei Element 1022 starten, erreichen Sie das Ende des Puffers, bevor Sie 4 Bytes erhalten. Es ist wahrscheinlich besser, einen gepufferten Eingabestream zu verwenden, der den gepufferten automatisch ausführt, sodass Sie ihn nur
readByte()
wiederholt verwenden können und sich sonst keine Sorgen machen müssen.Trailing Buffer: Das Ende der Eingabe kann je nach Quelle eine ungerade Anzahl von Bytes (nicht ein Vielfaches von 4) sein. Wenn Sie jedoch zunächst die Eingabe erstellen und ein Vielfaches von 4 "garantiert" (oder zumindest eine Voraussetzung) ist, müssen Sie sich möglicherweise nicht damit befassen.
Um den Punkt der Pufferung weiter zu erläutern, betrachten Sie Folgendes
BufferedInputStream
:InputStream in = new BufferedInputStream(new FileInputStream(file), 1024);
Jetzt haben Sie eine
InputStream
, die automatisch 1024 Bytes gleichzeitig puffert, was viel weniger umständlich ist. Auf diese Weise können Sie glücklich 4 Bytes gleichzeitig lesen und müssen sich nicht um zu viele E / A sorgen.Zweitens können Sie auch verwenden
DataInputStream
:InputStream in = new DataInputStream(new BufferedInputStream( new FileInputStream(file), 1024)); byte b = in.readByte();
oder auch:
int i = in.readInt();
und mach dir
int
überhaupt keine Sorgen darüber, s zu konstruieren .quelle
% 4
Bytes liest, oder?(bytes[0] & 0xff) | ((bytes[1] & 0xff) << 8) | ...
ret |= (int)bytes[i] & 0xFF;
sollte es wirklich seinret |= (int)bytes[i + offset] & 0xFF;
- sonst wird der Offset-Parameter komplett ignoriert.sehen Sie einfach, wie DataInputStream.readInt () implementiert wird;
int ch1 = in.read(); int ch2 = in.read(); int ch3 = in.read(); int ch4 = in.read(); if ((ch1 | ch2 | ch3 | ch4) < 0) throw new EOFException(); return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
quelle
Der einfachste Weg ist:
RandomAccessFile in = new RandomAccessFile("filename", "r"); int i = in.readInt();
-- oder --
DataInputStream in = new DataInputStream(new BufferedInputStream( new FileInputStream("filename"))); int i = in.readInt();
quelle
versuchen Sie so etwas:
a = buffer[3]; a = a*256 + buffer[2]; a = a*256 + buffer[1]; a = a*256 + buffer[0];
Dies setzt voraus, dass das niedrigste Byte an erster Stelle steht. Wenn das höchste Byte zuerst kommt, müssen Sie möglicherweise die Indizes austauschen (von 0 auf 3 gehen).
Grundsätzlich multiplizieren Sie für jedes Byte, das Sie hinzufügen möchten, zuerst a mit 256 (was einer Verschiebung nach links mit 8 Bit entspricht) und fügen dann das neue Byte hinzu.
quelle
x * 256
inx << 8
automatisch.<<
, sondern an der Lesbarkeit. Durch die Verwendung<<
ist klar, dass wir eher Bitoperationen als Multiplikationen ausführen. Tatsächlich würde ich sogar das+
s in|
s ändernfor (int i = 0; i < buffer.length; i++) { a = (a << 8) | buffer[i]; if (i % 3 == 0) { //a is ready a = 0; } }
quelle
Sie können BigInteger auch für Bytes variabler Länge verwenden. Sie können es in Long, Integer oder Short konvertieren, je nachdem, was Ihren Anforderungen entspricht.
new BigInteger(bytes).intValue();
oder um die Polarität zu bezeichnen:
new BigInteger(1, bytes).intValue();
quelle
Zum Lesen von 4 Bytes ohne Vorzeichen als Ganzzahl sollten wir eine lange Variable verwenden, da das Vorzeichenbit als Teil der vorzeichenlosen Zahl betrachtet wird.
long result = (((bytes[0] << 8 & bytes[1]) << 8 & bytes[2]) << 8) & bytes[3]; result = result & 0xFFFFFFFF;
Dies ist gut funktionierte Funktion getestet
quelle
Der folgende Code liest 4 Bytes von
array
(abyte[]
) an Positionindex
und gibt a zurückint
. Ich habe den größten Teil des Codes aus den anderen Antworten auf Java 10 und einigen anderen Varianten ausprobiert, die ich mir ausgedacht habe.Dieser Code verwendet die geringste CPU-Zeit, weist jedoch a zu,
ByteBuffer
bis die JIT von Java 10 die Zuordnung beseitigt.int result; result = ByteBuffer. wrap(array). getInt(index);
Dieser Code ist der Code mit der besten Leistung, der nichts zuweist. Leider verbraucht es 56% mehr CPU-Zeit als der obige Code.
int result; short data0, data1, data2, data3; data0 = (short) (array[index++] & 0x00FF); data1 = (short) (array[index++] & 0x00FF); data2 = (short) (array[index++] & 0x00FF); data3 = (short) (array[index++] & 0x00FF); result = (data0 << 24) | (data1 << 16) | (data2 << 8) | data3;
quelle
(array[i] << 24) | ((array[i + 1] & 0xff) << 16) | ((array[i + 2] & 0xff) << 8) | (array[i + 3] & 0xff)
(dh keine Konvertierung in dieshort
erste), ist die Leistung im Vergleich zurByteBuffer
Lösung gleich gut . Ich denke, es könnte als allgemeines Muster optimiert werden.Konvertieren eines 4-Byte-Arrays in eine Ganzzahl:
//Explictly declaring anInt=-4, byte-by-byte byte[] anInt = {(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xfc}; // Equals -4 //And now you have a 4-byte array with an integer equaling -4... //Converting back to integer from 4-bytes... result = (int) ( anInt[0]<<24 | ( (anInt[1]<<24)>>>8 ) | ( (anInt[2]<<24)>>>16) | ( (anInt[3]<<24)>>>24) );
quelle