DataInputStream.readInt: примеры (JAVA)

Метод DataInputStream.readInt: практическое руководство
Раздел: Потоки ввода-вывода (Streams) байтовые
DataInputStream.readInt: int

Общее описание DataInputStream.readInt

Метод readInt класса java.io.DataInputStream читает 4 байта из входного потока и возвращает 32-битное целое число со знаком (тип int). Подпись метода:

public final int readInt() throws IOException

Особенности поведения:

  • Чтение производится в порядке big-endian (старший байт первым), то есть соответствие байтов и значений совпадает с сетевым порядком байт.
  • Аргументов не принимает: метод использует уже открытый поток, обёрнутый в DataInputStream.
  • Возвращает значение типа int (32-битное со знаком).
  • При достижении конца потока до получения 4 байт бросается java.io.EOFException. При других проблемах ввода-вывода бросается java.io.IOException.
  • Метод реализует контракт интерфейса DataInput; порядок байт фиксирован и не зависит от платформы JVM.

Частые сценарии применения: чтение бинарных форматов с фиксированной шириной целых, чтение данных, записанных с помощью DataOutputStream.writeInt, обработка сетевых протоколов, где интегер передаётся в 4 байта big-endian.

Примеры простого использования

Чтение значения, записанного с помощью DataOutputStream:

// Java
import java.io.*;

public class Example1 {
    public static void main(String[] args) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        dos.writeInt(0x01020304); // записывает 4 байта
        dos.close();

        byte[] data = baos.toByteArray();
        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
        int v = dis.readInt();
        System.out.println(v);
    }
}
16909060

Чтение из файла (файл содержит последовательность 4-байтовых целых):

// Java
import java.io.*;

public class Example2 {
    public static void main(String[] args) throws Exception {
        try (DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("ints.bin")))) {
            while (true) {
                int x = dis.readInt();
                System.out.println(x);
            }
        } catch (EOFException eof) {
            // конец файла
            System.out.println("Конец файла");
        }
    }
}
(пример вывода - последовательность чисел, затем "Конец файла")

Ситуация, когда байтов не хватает - демонстрация EOFException:

// Java
import java.io.*;

public class Example3 {
    public static void main(String[] args) throws Exception {
        byte[] bytes = new byte[] {0x01, 0x02}; // только 2 байта
        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bytes));
        dis.readInt();
    }
}
java.io.EOFException
	at java.base/java.io.DataInputStream.readInt(DataInputStream.java:...) ...

Похожие методы в Java и их различия

  • ByteBuffer.getInt() - чтение int из буфера байтов с управляемым порядком байт (можно задать ByteOrder.BIG_ENDIAN или LITTLE_ENDIAN). Предпочтение при необходимости управления порядком байт и при работе с NIO.
  • RandomAccessFile.readInt() - похож на DataInputStream.readInt, но позволяет читать по произвольным смещениям в файле (поддерживает seek).
  • DataInput.readInt() - интерфейсный метод; разные реализации могут использовать тот же алгоритм, но поведение зависит от конкретной реализации.
  • ObjectInputStream.readInt() - читает int в контексте сериализованного потока объектов; лишний служебный контекст может присутствовать при чтении сложных объектов.

Выбор между ними зависит от потребностей: для простого последовательного чтения из InputStream - DataInputStream, для управления порядком байт и высокопроизводительных операций с буферами - ByteBuffer, для доступа по смещению в файле - RandomAccessFile.

Аналоги в других языках и отличия

PHP (работа с бинарными данными):

// PHP
$data = chr(0x01).chr(0x02).chr(0x03).chr(0x04);
$val = unpack('N', $data)[1]; // N - unsigned long (big-endian)
echo $val . PHP_EOL;
16909060

JavaScript (Node.js Buffer и Web API DataView):

// Node.js
const buf = Buffer.from([0x01,0x02,0x03,0x04]);
console.log(buf.readInt32BE(0));

// Браузер: DataView
const arr = new Uint8Array([1,2,3,4]);
const v = new DataView(arr.buffer).getInt32(0, false); // false = big-endian
console.log(v);
16909060
16909060

Python (struct и int.from_bytes):

# Python
import struct
b = bytes([1,2,3,4])
print(struct.unpack('>i', b)[0])
# или
print(int.from_bytes(b, byteorder='big', signed=True))
16909060
16909060

C# (.NET):

// C#
using System;
using System.IO;

byte[] bytes = new byte[]{1,2,3,4};
using(var ms = new MemoryStream(bytes)){
    using(var br = new BinaryReader(ms)){
        Console.WriteLine(br.ReadInt32()); // окружение Little-endian у CLR, но BinaryReader читает в порядке платформы; если данные big-endian - требуется перестановка
    }
}
16909060 (если платформа и формат совпадают) или неправильное число, если порядок байт отличается

Go (encoding/binary):

// Go
package main

import (
    "encoding/binary"
    "fmt"
)

func main() {
    b := []byte{1,2,3,4}
    v := int32(binary.BigEndian.Uint32(b))
    fmt.Println(v)
}
16909060

Lua (5.3+):

-- Lua
local s = string.char(1,2,3,4)
local v = string.unpack('>i4', s)
print(v)
16909060

Ключевые различия от Java:

  • Порядок байт может требовать явной настройки (в Java DataInputStream фиксирован как big-endian).
  • Некоторые языки имеют встроенные функции для чтения из буфера с параметризуемым порядком байт.
  • В C# BinaryReader читает в порядке платформы; при работе с big-endian требуется преобразование.

Типичные ошибки и примеры

  • EOFException при чтении недостаточного количества байт. Пример:
// Java
import java.io.*;
public class Err1 {
    public static void main(String[] args) throws Exception {
        byte[] bytes = new byte[]{0x01};
        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bytes));
        dis.readInt(); // бросит EOFException
    }
}
java.io.EOFException
	at java.base/java.io.DataInputStream.readInt(DataInputStream.java:...) ...
  • Неправильный результат при неверном порядке байт (little-endian вместо big-endian). Пример:
// Java
byte[] b = new byte[]{0x01,0x02,0x03,0x04};
int v = new DataInputStream(new ByteArrayInputStream(b)).readInt();
System.out.println(v);
// Если данные были записаны как little-endian, значение будет некорректным
16909060
  • Попытка читать бинарные int через текстовые Reader/BufferedReader ведёт к неверным данным и возможным ошибкам кодирования.
  • Игнорирование закрытия потоков может привести к утечкам ресурсов. Рекомендуется try-with-resources.
  • Смешивание методов чтения (например, чтение байтов и сразу чтение символов без согласования формата) может сместить позицию и испортить последующие readInt.

Изменения в поведении метода в последних версиях JDK

Метод DataInputStream.readInt() существует с ранних версий JDK и сохраняет стабильное поведение: чтение 4 байт в порядке big-endian и выброс EOFException при нехватке байт. В современных релизах Java не было обратимо несовместимых изменений в семантике этого метода. Следует учитывать общие изменения платформы, например, улучшения производительности JDK и модульность (JDK 9), но интерфейс и контракт метода остался прежним.

Расширенные и нестандартные сценарии

1) Быстрое чтение большого массива int: чтение блоками байтов с последующей упаковкой в IntBuffer.

Пример java
// Java
import java.io.*;
import java.nio.*;

public class Adv1 {
    public static void main(String[] args) throws Exception {
        // предположим, что stream содержит 1000 int подряд (big-endian)
        InputStream is = /* источник */ new FileInputStream("ints.bin");
        DataInputStream dis = new DataInputStream(new BufferedInputStream(is));

        int count = 1000;
        byte[] buf = new byte[count * 4];
        dis.readFully(buf); // выбросит EOFException, если байтов меньше

        IntBuffer ib = ByteBuffer.wrap(buf).order(ByteOrder.BIG_ENDIAN).asIntBuffer();
        while (ib.hasRemaining()) {
            System.out.println(ib.get());
        }
        dis.close();
    }
}
(вывод - 1000 чисел из файла)

2) Обработка little-endian входа при помощи ручной перестановки или ByteBuffer.order:

Пример java
// Java
import java.io.*;
import java.nio.*;

byte[] b = new byte[]{0x04,0x03,0x02,0x01}; // little-endian представление 0x01020304
int v = ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN).getInt();
System.out.println(v);
16909060

3) Чтение int из сетевого сокета с обработкой неполных пакетов:

Пример java
// Java
import java.io.*;
import java.net.*;

public class NetRead {
    public static void main(String[] args) throws Exception {
        try (Socket s = new Socket("example.com", 12345);
             DataInputStream dis = new DataInputStream(s.getInputStream())) {
            // цикл чтения, аккуратно обрабатывается EOF и блокировки
            while (true) {
                try {
                    int cmd = dis.readInt();
                    // обработка команды
                } catch (EOFException eof) {
                    break; // соединение закрыто корректно
                }
            }
        }
    }
}
(выполнение зависит от удалённого сервера)

4) Сочетание с MemoryMappedFile для произвольного доступа к большим бинарным файлам:

Пример java
// Java
import java.io.*;
import java.nio.*;
import java.nio.channels.*;

RandomAccessFile raf = new RandomAccessFile("large.bin","r");
FileChannel ch = raf.getChannel();
MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, 0, ch.size());
mb.order(ByteOrder.BIG_ENDIAN);
IntBuffer ib = mb.asIntBuffer();
System.out.println(ib.get(10)); // десятый int в файле
ch.close();
raf.close();
(значение в позиции 10 файла)

5) Обработка смешанных форматов: чтение int, затем строки фиксированной длины и байтовых блоков с контролем смещения.

Пример java
// Java
DataInputStream dis = new DataInputStream(new FileInputStream("mix.bin"));
int header = dis.readInt(); // 4 байта
byte[] nameBytes = new byte[16];
dis.readFully(nameBytes);
String name = new String(nameBytes, "UTF-8").trim();
int payloadLen = dis.readInt();
byte[] payload = new byte[payloadLen];
dis.readFully(payload);
(обработка зависимости от содержимого mix.bin)

В комментариях к примерам приведена типовая обработка ошибок и варианты применения при больших данных.

джава DataInputStream.readInt function comments

En
DataInputStream.readInt Reads an int value from the input stream