DataOutputStream.writeInt: примеры (JAVA)
DataOutputStream.writeInt(int v): voidОписание метода
Метод DataOutputStream.writeInt записывает 32-битное целое значение (тип int) в поток в порядке байт big-endian (старший байт первым). Метод реализует контракт интерфейса DataOutput и возвращаемого значения не имеет (возвращает void), но может выбросить исключение при ошибке ввода-вывода.
Сигнатура метода в Java:
public final void writeInt(int v) throws IOException
Аргументы:
v- значение типаint, которое будет разбито на четыре байта и записано в поток.
Возвращаемое значение:
- Метод не возвращает значения; в случае успешной записи управление возвращается вызывающему коду.
Исключения и поведение:
IOException- при ошибках ввода-вывода (например, поток закрыт или проблемы с носителем).
Особенности:
- Запись всегда в порядке big-endian, независимо от эндianness платформы.
- Метод записывает ровно 4 байта для каждого вызова.
- Для потоков, требующих позиционирования (перезаписи заголовков), DataOutputStream сам по себе позиционирования не предоставляет; в таких сценариях используются другие API (например,
RandomAccessFileилиFileChannel).
Краткие примеры использования
Запись в массив байтов с выводом результата в шестнадцатеричном виде.
import java.io.*;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeInt(0x01020304);
dos.flush();
} finally {
dos.close();
}
byte[] bytes = baos.toByteArray();
for (byte b : bytes) System.out.printf("%02X ", b);
01 02 03 04
Запись нескольких целых в файл и чтение назад с помощью DataInputStream.
import java.io.*;
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("ints.bin"))) {
dos.writeInt(123456789);
dos.writeInt(-1);
}
try (DataInputStream dis = new DataInputStream(new FileInputStream("ints.bin"))) {
System.out.println(dis.readInt());
System.out.println(dis.readInt());
}
123456789 -1
Использование поверх сокета (передача 32-битного кода команды).
import java.net.*;
import java.io.*;
Socket s = new Socket("example.com", 12345);
try (DataOutputStream dos = new DataOutputStream(s.getOutputStream())) {
dos.writeInt(42); // отправка кода
}
(нет вывода в стандартный поток; байты отправлены по сети)
Похожие средства в Java
Несколько альтернатив и смежных API:
- ByteBuffer.putInt (java.nio) - обеспечивает контроль порядка байт через
order(ByteOrder). Предпочтительнее для NIO и работы с буферами/мэппингом. - RandomAccessFile.writeInt - похожий метод с поддержкой произвольного позиционирования в файле; удобен при необходимости перезаписи заголовков.
- DataOutputStream.writeLong / writeShort - для других размеров целых; используются при записи 64- или 16-битных значений.
- ObjectOutputStream - для сериализации объектов; не подходит для простого бинарного протокола из-за добавочных метаданных.
Выбор зависит от требований: для простых последовательных записей в поток подходит DataOutputStream; для контроля порядка байт и работы с памятью подойдут ByteBuffer и FileChannel; для перезаписи данных - RandomAccessFile.
Аналоги в других языках
Короткие примеры записи 32-битного целого в big-endian и отличия.
PHP (pack, big-endian):
$bin = pack('N', 16909060); // 0x01020304
echo bin2hex($bin);
01020304
JavaScript в браузере (ArrayBuffer / DataView):
const buf = new ArrayBuffer(4);
const dv = new DataView(buf);
dv.setInt32(0, 0x01020304, false); // false = big-endian
const arr = new Uint8Array(buf);
console.log(Array.from(arr).map(b => b.toString(16).padStart(2,'0')).join(' '));
01 02 03 04
Node.js Buffer:
const buf = Buffer.alloc(4);
buf.writeInt32BE(0x01020304, 0);
console.log(buf.toString('hex'));
01020304
Python (struct):
import struct
b = struct.pack('>i', 0x01020304)
print(b.hex())
01020304
C# (BinaryWriter) - по умолчанию little-endian; для big-endian требуется переворот:
using (var ms = new MemoryStream()) {
using (var bw = new BinaryWriter(ms)) {
int v = 0x01020304;
var bytes = BitConverter.GetBytes(v);
if (BitConverter.IsLittleEndian) Array.Reverse(bytes);
bw.Write(bytes);
Console.WriteLine(BitConverter.ToString(ms.ToArray()).Replace("-"," "));
}
}
01 02 03 04
Go (encoding/binary):
import (
"bytes"
"encoding/binary"
"fmt"
)
buf := new(bytes.Buffer)
_ = binary.Write(buf, binary.BigEndian, int32(0x01020304))
fmt.Printf("% X\n", buf.Bytes())
01 02 03 04
Lua 5.3+ (string.pack):
s = string.pack('>i4', 0x01020304)
for i = 1, #s do io.write(string.format('%02X ', s:byte(i))) end
01 02 03 04
Отличия от Java:
- Некоторые API по умолчанию используют порядок байт платформы (например, BinaryWriter в C#), поэтому может потребоваться явный переворот.
- В языках с встроенной упаковкой (Python, PHP, Go) управление порядком байт реализовано прямо в функциях, что упрощает переносимость.
- В Java DataOutputStream фиксированно использует big-endian; для little-endian требуется дополнительная обёртка или ByteBuffer с соответствующим порядком.
Типичные ошибки при использовании
Наиболее распространённые ошибки и их проявления.
- Запись в закрытый поток: после закрытия поток бросит IOException.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.close();
dos.writeInt(1); // IOException
java.io.IOException: Stream closed
- Неправильный порядок байт: если принимающая сторона ожидает little-endian, а записано big-endian, данные интерпретируются неправильно.
// Записано big-endian
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(1); // 00 00 00 01
// Чтение с little-endian интерпретацией даст 16777216
(расхождение значений при чтении)
- Потеря данных при неправильном приводе типов: попытка записать значение большего типа через приведение может привести к обрезанию.
long big = 0x1_0000_0000L; // 4294967296
dos.writeInt((int) big); // потеря старших бит
записаны только младшие 32 бита
- Отсутствие буферизации: множественные мелкие вызовы записи в поток без буфера могут снизить производительность; применение BufferedOutputStream улучшает ситуацию.
Рекомендации по отладке ошибок: проверять порядок байт, не вызывать запись после закрытия, использовать try-with-resources и при необходимости проверять размер записанных данных.
Изменения за версии Java
Метод DataOutputStream.writeInt существует с ранних версий Java (Java 1.0) и не претерпевал изменений в сигнатуре или семантике. В более новых релизах происходили общие улучшения платформы ввода-вывода и оптимизации, но сам метод остаётся стабильным и не помечен как deprecated. Для функциональных расширений используются соседние API: java.nio, FileChannel, MappedByteBuffer.
Расширенные и нетипичные примеры
1) Перезапись заголовка с длиной записи: сначала резервирование места, запись блока, затем возврат и корректировка заголовка с помощью RandomAccessFile.
import java.io.*;
try (RandomAccessFile raf = new RandomAccessFile("packet.bin", "rw")) {
raf.writeInt(0); // место для длины
long start = raf.getFilePointer();
try (DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(raf.getFD())))) {
dos.writeInt(0xDEADBEEF);
dos.writeInt(42);
dos.flush();
}
long end = raf.length();
int length = (int)(end - start);
raf.seek(0);
raf.writeInt(length);
}
// Чтение для проверки
try (DataInputStream dis = new DataInputStream(new FileInputStream("packet.bin"))) {
System.out.println(dis.readInt()); // длина блока
System.out.printf("%08X\n", dis.readInt());
System.out.println(dis.readInt());
}
8 DEADBEEF 42
2) Запись в little-endian через ByteBuffer и вывод результата (DataOutputStream лишь big-endian).
import java.nio.*;
ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);
bb.putInt(0x01020304);
byte[] arr = bb.array();
for (byte b: arr) System.out.printf("%02X ", b);
04 03 02 01
3) Использование MappedByteBuffer для высокопроизводительной записи большого числа целых (memory-mapped файл).
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
try (RandomAccessFile raf = new RandomAccessFile("map.bin", "rw");
FileChannel fc = raf.getChannel()) {
int count = 1_000_000;
raf.setLength((long)count * 4);
MappedByteBuffer mb = fc.map(FileChannel.MapMode.READ_WRITE, 0, (long)count * 4);
mb.order(ByteOrder.BIG_ENDIAN);
for (int i = 0; i < count; i++) mb.putInt(i);
}
System.out.println("done");
done
4) Сравнение производительности: DataOutputStream vs ByteBuffer bulk - пример сбора в буфер и запись одним write.
// Сбор в ByteBuffer для уменьшения количества системных вызовов
import java.io.*;
import java.nio.*;
int n = 100_000;
ByteBuffer bb = ByteBuffer.allocate(n * 4).order(ByteOrder.BIG_ENDIAN);
for (int i = 0; i < n; i++) bb.putInt(i);
try (FileOutputStream fos = new FileOutputStream("bulk.bin")) {
fos.write(bb.array());
}
(файл записан быстрее при уменьшении числа write-вызовов)
5) Протокол обмена: упаковка заголовка с контрольной суммой (CRC32) и несколькими полями.
import java.io.*;
import java.util.zip.CRC32;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(baos)) {
dos.writeInt(0xABCD); // тип
dos.writeInt(0); // место для длины
dos.writeInt(12345); // payload field
dos.flush();
}
byte[] payload = baos.toByteArray();
CRC32 crc = new CRC32();
crc.update(payload, 8, payload.length - 8); // вычислить по payload
ByteArrayOutputStream packet = new ByteArrayOutputStream();
try (DataOutputStream dos2 = new DataOutputStream(packet)) {
dos2.writeInt(0xABCD);
dos2.writeInt(payload.length - 8);
dos2.write(payload, 8, payload.length - 8);
dos2.writeInt((int) crc.getValue());
}
System.out.println(Integer.toHexString(((packet.toByteArray())[0] & 0xFF)));
(пакет собран; пример показывает способ вычисления и вставки контрольной суммы)
Комментарии к примерам: приведённые расширенные сценарии демонстрируют техники для реальных задач: предварительное резервирование длины, работа с маппингом, изменение порядка байт, уменьшение числа системных вызовов и добавление контрольных сумм.
джава DataOutputStream.writeInt function comments
- джава DataOutputStream.writeInt - аргументы и возвращаемое значение
- Функция java DataOutputStream.writeInt - описание
- DataOutputStream.writeInt - примеры
- DataOutputStream.writeInt - похожие методы на java
- DataOutputStream.writeInt на javascript, c#, python, php
- DataOutputStream.writeInt изменения java
- Примеры DataOutputStream.writeInt на джава