Эккель Брюс
Шрифт:
buffer flipO; // Подготовка к записи out.write(buffer):
buffer.clear; // Подготовка к чтению
}
}
} /// ~
В программе создаются два канала FileChannel: для чтения и для записи. Выделяется буфер ByteBuffer, а когда метод FileChannel.read возвращает -1, это значит, что мы достигли конца входных данных (без сомнения, пережиток UNIX и С). После каждого вызова метода read, помещающего данные в буфер, метод flip подготавливает буфер так, чтобы информация из него могла быть извлечена методом write. После вызова write информация все еще хранится в буфере, поэтому метод clear перемещает все его внутренние указатели, чтобы буфер снова был способен принимать данные в методе read.
Впрочем, рассмотренная программа не лучшим образом выполняет копирование файлов. Специальные методы, transferTo и transferFrom, позволяют напрямую присоединить один канал к другому:
// io/TransferTo java
// Использование метода transferToO для соединения каналов // {Параметры TransferTo java TransferTo txt} import java nio channels.*, import java io *.
public class TransferTo {
public static void main(String[] args) throws Exception { if(args length != 2) {
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 =