Эккель Брюс
Шрифт:
//• io/IntBufferDemo java // Работа с целыми числами в буфере ByteBuffer // посредством буфера IntBuffer import java nio *,
public class IntBufferDemo {
private static final int BSIZE = 1024, public static void main(String[] args) {
ByteBuffer bb = ByteBuffer.allocate(BSIZE); IntBuffer ib = bb.asIntBufferO; // Сохранение массива int:
ib put(new int[]{ 11, 42, 47, 99, 143, 811. 1016 }), // Чтение и запись по абсолютным позициям: System out.println(ib.get(3)), ib put(3, 1811):
// Назначение нового предела перед смещением буфера ib flipO.
whi 1 е(ib hasRemainingO) { int i = ib.getO; System.out.printin(i),
}
}
} /* Output 99 11 42 47
143 811 1016 *///:-
Перегруженный метод put первый раз вызывается для помещения в буфер массива целых чисел int. Последующие вызовы put и get обращаются к конкретному числу int из байтового буфера ByteBuffer. Заметьте, что такие обращения к простейшим типам по абсолютной позиции также можно осуществить напрямую через буфер ByteBuffer.
Как только байтовый буфер ByteBuffer будет заполнен целыми числами или другими примитивами через представление, его можно передать для непосредственной записи в канал. Настолько же просто считать данные из канала и использовать представление для преобразования данных к конкретному простейшему типу. Вот пример, который трактует одну и ту же последовательность байтов как числа short, int, float, long и double, создавая для одного байтового буфера ByteBuffer различные представления:
//: io/ViewBuffers.java import java.nio.*;
import static net.mindview.util.Print.*;
public class ViewBuffers {
public static void main(String[] args) { ByteBuffer bb = ByteBuffer.wrap(
new byte[]{ 0. 0. 0. 0. 0. 0. 0. 'a' }); bb.rewind; printnb("Буфер Byte "); while(bb.hasRemainingO)
printnb(bb.position+ " -> " + bb.getO + \ ");
printO; CharBuffer cb -
((ByteBuffer)bb.rewind).asCharBuffer; printnb("Буфер Char "); while(cb.hasRemainingO)
printnb(cb.position + " -> " + cb.getO + \ ");
printO;
FloatBuffer fb -
((ByteBuffer)bb.rewi nd).asFloatBuffer; printnb("Буфер Float "); while(fb.hasRemainingO)
printnb(fb.position+ " -> " + fb.getO + ");
printO; IntBuffer ib -
((ByteBuffer)bb.rewind).asIntBuffer; printnb("Буфер Int "); while(ib.hasRemainingO)
printnb(ib.position+ " -> " + ib.getO + ". ");
printO; LongBuffer lb =
((ByteBuffer)bb.rewind).asLongBuffer; printnbCБуфер Long "); while(lb.hasRemainingO)
printnb(1b.position+ " -> " + Ib.getO + ". ");
printO;
ShortBuffer sb =
((ByteBuffer)bb.rewind).asShortBuffer, pri ntnbCБуфер Short "), while(sb hasRemainingO)
printnb(sb position+ " -> " + sb.getO + ");
printO,
DoubleBuffer db =
((ByteBuffer)bb.rewi nd) asDoubleBuffer: printnb("Буфер Double "), while(db hasRemainingO)
printnb(db position+ " -> " + db getO + ", ");
}
} /* Output
Буфер Byte 0 -> 0. 1 -> 0, 2 -> 0. 3 -> 0. 4 -> 0, 5 -> 0. 6 -> 0. 7 -> 97,
Буфер Char 0 -> . 1 -> , 2 -> , 3 -> a,
Буфер Float 0 -> 0 0. 1 -> 1.36E-43,
Буфер Int 0 -> 0. 1 -> 97,
Буфер Long 0 -> 97,
Буфер Short 0 -> 0, 1 -> 0. 2 -> 0, 3 -> 97.
Буфер Double 0 -> 4 8E-322. *///.-
Байтовый буфер ByteBuffer создается как «обертка» для массива из восьми байтов, который затем и просматривается с помощью представлений для различных простейших типов.
О «порядке байтов
Различные компьютеры могут хранить данные с различным порядком следования байтов. Прямой порядок big_endian располагает старший байт по младшему адресу памяти, а для обратного порядка little_endian старший байт помещается по высшему адресу памяти. При хранении значения, занимающего более одного байта, такого как число int, float и т. п., вам, возможно, придется учитывать различные варианты следования байтов в памяти. Буфер ByteBuffer укладывает данные в порядке big_endian, такой же способ всегда используется для данных, пересылаемых по сети. Порядок следования байтов в буфере можно изменить методом order, передав ему аргумент ByteOrder.BIG_ENDIAN или ByteOrder. LITTLE_ENDIAN.
Рассмотрим двоичное представление байтового буфера, содержащего следующие два байта:
0
0
0
0
0
0
0
97
byte
а
char
0
0
0
97