Рейтинговые книги
Читем онлайн Философия Java3 - Брюс Эккель

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 102 103 104 105 106 107 108 109 110 ... 132

System out printin("параметры источник приемник"), System exit(l).

}

FileChannel

in = new FileInputStream(args[0]) getChannel(). out = new FileOutputStream(args[l]) getChannelО; in.transferTo(0, in.sizeO. out); // Или-

// out transferFrom(in, 0. in.sizeO),

}

} ///;-

Часто такую операцию выполнять вам не придется, но знать о ней полезно.

Преобразование данных

Если вы вспомните программу GetChannel.java, то увидите, что для вывода информации из файла нам приходилось считывать из буфера по одному байту и преобразовывать его от типа byte к типу char. Такой подход явно примитивен — если вы посмотрите на класс java.nio.CharBuffer, то увидите, что в нем есть метод toString(), который возвращает строку из символов, находящихся в данном буфере. Байтовый буфер ByteBuffer можно рассматривать как символьный буфер CharBuffer, как это делается в методе asCharBuffer(), почему бы так и не поступить? Как вы увидите уже из первого предложения expect(), это не сработает:

//; io/BufferToText java

// Получение текста из буфера ByteBuffers и обратно

import java.nio *.

import java nio channels.*;

import java nio charset *;

import java.io.*,

public class BufferToText {

private static final int BSIZE = 1024, public static void main(String[] args) throws Exception { FileChannel fc =

new Fi1eOutputStream("data2.txt").getChannel(); fc write (ByteBuffer. wrap ("Some text" .getBytesO)); fc closeO;

fc = new FileInputStream("data2.txt").getChannelО; ByteBuffer buff = ByteBuffer allocate(BSIZE); fc read(buff); buff .flipO; // He работает-

System out prmtln(buff.asCharBufferO); продолжение &

// Декодирование с использованием кодировки по умолчанию: buff.rewindO;

String encoding = System.getProperty("file.encoding"); System.out.println("Декодировано в " + encoding + ": "

+ Charset.forName(encoding).decode(buff)); // Кодирование в печатной форме: fc = new Fi1e0utputStreamCdata2.txt").getChannel О; fc.wri te(ByteBuffer.wrap(

"Some text".getBytes("UTF-16BE"))): fc.closeO:

// Повторная попытка чтения:

fc = new FileInputStreamCdata2.txt").getChannelO;

buff.clearO:

fc.read(buff);

buff.flipO:

System.out.pri nt1n(buff.asCharBuffer());

// Использование CharBuffer для записи:

fc = new FileOutputSt reamCdata2.txt"). getChannelO;

buff = ByteBuffer.a11ocate(24); // Больше, чем необходимо

buff.asCharBuffer().put("Some text");

fc.write(buff);

fc.closeO;

// Чтение и вывод:

fc = new FileInputStreamCdata2.txt").getChannelO;

buff.clearO;

fc.read(buff):

buff.flipO;

System.out.pri nt1n(buff.asCha rBuffer());

}

} /* Output: ????

Декодировано в Cpl252: Some text Some text Some text *///:-

Буфер содержит обычные байты, следовательно, для превращения их в символы мы должны либо кодировать их по мере помещения в буфер, либо декодировать их при извлечении из буфера. Это можно сделать с помощью класса java.nio.charset.Charset, который предоставляет инструменты для преобразования многих различных типов в наборы символов:

//: io/Avai1ableCharSets.java

// Перечисление кодировок и их символических имен

import java.nio.charset.*;

import java.util.*;

import static net.mindview.util.Print.*;

public class AvailableCharSets {

public static void main(String[] args) {

SortedMap<String.Charset> charSets = Charset.avai1ableCharsets(); Iterator<String> it = charSets.keySetО.iteratorO: whileCit.hasNextO) {

String csName = it.nextO; printnb(csName); Iterator aliases =

charSets get(csName) .aliasesO .iteratorO; if(aliases.hasNextO)

pnntnbC': "); while(aliases hasNextO) {

printnb(aliases.nextO); if(aliases. hasNextO) printnbC'. "),

}

printO;

}

}

} /* Output: Big5. csBig5

Big5-HKSCS: big5-hkscs, big5hk, big5-hkscs:unicode3 0. big5hkscs. Big5_HKSCS

EUC-JP eucjis, x-eucjp, csEUCPkdFmtJapanese, eucjp,

Extended_UNIX_Code_Packed_Format_for_Japanese. x-euc-jp, euc_jp

EUC-KR: ksc5601, 5601, ksc5601_1987, ksc_5601, ksc5601-

1987, euc_kr, ks_c_5601-1987, euckr, csEUCKR

GB18030• gbl8030-2000

GB2312: gb2312-1980, gb2312, EUC_CN, gb2312-80, euc-cn,

euccn, x-EUC-CN

GBK. windows-936, CP936

*///;-

Вернемся к программе BufferToText.java. Если вы вызовете для буфера метод rewind() (чтобы вернуться к его началу), а затем используете кодировку по умолчанию в методе decode(), данные буфера CharBuffer будут правильно выведены на консоль. Чтобы узнать кодировку по умолчанию вызовите метод System. getProperty("fiLe.encoding"), который возвращает строку с названием кодировки. Передавая эту строку методу Charset.forName(), вы получите объект Charset, с помощью которого и декодируете строку.

Другой подход — кодировать данные методом encode() так, чтобы при чтении файла выводились данные, пригодные для вывода на печать (пример представлен в программе BufferToText.java). Здесь для записи текста в файл используется кодировка UTF-16BE, и при последующем чтении вам остается лишь преобразовать данные в буфер CharBuffer и вывести его содержимое.

Наконец, мы видим, что происходит, когда вы записываете в буфер ByteBuffer через CharBuffer (мы узнаем об этом чуть позже). Заметьте, что для байтового буфера выделяется 24 байта. На каждый символ (char) отводится два байта, соответственно, буфер вместит 12 символов, а у нас в строке Some Text их только девять. Оставшиеся нулевые байты все равно отображаются в строке, образуемой методом toStringO класса CharBuffer, что и показывают результаты.

Извлечение примитивов

Несмотря на то что в буфере ByteBuffer хранятся только байты, он поддерживает методы для выборки любых значений примитивных типов из этих байтов. Следующий пример демонстрирует вставку и выборку из буфера разнообразных значений примитивных типов:

//. io/GetData java

11 Получение различных данных из буфера ByteBuffer import java nio *.

import static net.mindview util Print *;

public class GetData {

private static final int BSIZE = 1024. public static void main(String[] args) {

ByteBuffer bb = ByteBuffer allocate(BSIZE). // При выделении буфер заполняется нулями int i = 0;

while(i++ < bb limitO)

if(bb.get() != 0)

print("nonzero");

printC'i = " + i); bb rewindO:

// Сохраняем и считываем символьный массив bb asCharBufferO put("Howdy!"); char c,

while((c = bb.getCharO) != 0) printnb(c + " ");

printO. bb rewindO:

// Сохраняем и считываем число типа short: bb.asShortBuffer().put((short >471142): print(bb.getShortO), bb. rewindO;

// Сохраняем и считываем число типа int: bb.asIntBufferO put(99471142): print(bb getlntO), bb. rewindO,

// Сохраняем и считываем число типа long-bb.asLongBufferO put(99471142): print(bb.getLongO); bb. rewindO,

// Сохраняем и считываем число типа float. bb.asFloatBufferO put(99471142): print(bb getFloatO); bb. rewindO.

// Сохраняем и считываем число типа double: bb asDoubleBufferO put(99471142): print(bb getDoubleO). bb. rewindO;

}

} /* Output-i = 1025 Howdy ! 12390 99471142 99471142 9 9471144E7

9.9471142E7 *///.-

После выделения байтового буфера мы убеждаемся в том, что его содержимое действительно заполнено нулями. Проверяются все 1024 значения, хранимые в буфере (вплоть до последнего, индекс которого (размер буфера) возвращается методом limit()), и все они оказываются нулями.

Простейший способ вставить примитив в ByteBuffer основан на получении подходящего «представления» этого буфера методами asCharBuffer(), asShort-Buffer() и т. п., и последующем занесении в это представление значения методом put(). В примере мы так поступаем для каждого из простейших типов. Единственным исключением из этого ряда является использование буфера ShortBuffer, требующего приведения типов (которое усекает и изменяет результирующее значение). Все остальные представления не нуждаются в преобразовании типов.

Представления буферов

«Представления буферов» дают вам возможность взглянуть на соответствующий байтовый буфер «через призму» некоторого примитивного типа. Байтовый буфер все так же хранит действительные данные и одновременно поддерживает представление, поэтому все изменения, которые вы сделаете в представлении, отразятся на содержимом байтового буфера. Как было показано в предыдущем' примере, это удобно для вставки значений примитивов в байтовый буфер. Представления также позволяют читать значения примитивов из буфера, по одному (раз он «байтовый» буфер) или пакетами (в массивы). Следующий пример манипулирует целыми числами (int) в буфере ByteBuffer с помощью класса IntBuffer:

//• 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)

1 ... 102 103 104 105 106 107 108 109 110 ... 132
На этой странице вы можете бесплатно читать книгу Философия Java3 - Брюс Эккель бесплатно.
Похожие на Философия Java3 - Брюс Эккель книги

Оставить комментарий