Чтение онлайн

ЖАНРЫ

Философия Java3

Эккель Брюс

Шрифт:

cap |

>

г

>

г

и

S

i

п

g

в

U

f

f

е

г

s

k

к

k

к

lim

pos I

Процесс

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

г

и

S

i

п

g

в

U

f

f

е

г

S

i

к

k

к

posl

lim

При следующем вызове symmetricScramble процесс повторяется, и буфер CharBuffer возвращается к своему изначальному состоянию.

Отображаемые в память файлы

Механизм отображения файлов в память позволяет создавать и изменять файлы, размер которых слишком велик для прямого размещения в памяти. В таком случае вы считаете, что файл целиком находится в памяти, и работаете с ним как с очень большим массивом. Такой подход значительно упрощает код изменения файла. Небольшой пример:

//. io/LargeMappedFiles.java

// Создание очень большого файла, отображаемого в память

// {RunByHand}

import java.nio.*;

import java nio.channels.*;

import java.io.*;

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

public class LargeMappedFiles {

static int length = 0x8FFFFFF, // 128 MB public static void main(String[] args) throws Exception { MappedByteBuffer out =

new RandomAccessFileC'test.dat". "rw").getChannel .map(Fi1eChannel.MapMode.READ_WRITE. 0. length); for(int i = 0; i < length; i++)

out.put((byte)'x'); print("Запись завершена"); for(int i = length/2; i < length/2 +6; i++) printnb((char)out.get(i));

}

} ///:-

Чтобы одновременно выполнять чтение и запись, мы начинаем с создания объекта RandomAccessFile, получаем для этого файла канал, а затем вызываем метод тар, чтобы получить буфер MappedByteBuffer, который представляет собой разновидность буфера прямого

доступа. Заметьте, что необходимо указать начальную точку и длину участка, который будет проецироваться, то есть у вас есть возможность отображать маленькие участки больших файлов.

Класс MappedByteBuffer унаследован от буфера ByteBuffer, поэтому он содержит все методы последнего. Здесь представлены только простейшие вызовы методов put и get, но вы также можете использовать такие возможности, как метод asCharBuffer и т. п.

Программа напрямую создает файл размером 128 Мбайт; скорее всего, это превышает ограничения вашей операционной системы на размер блока данных, находящегося в памяти. Однако создается впечатление, что весь файл доступен сразу, поскольку только часть его подгружается в память, в то время как остальные части выгружены. Таким образом можно работать с очень большими (размером до 2 Гбайт) файлами. Заметьте, что для достижения максимальной производительности используются низкоуровневые механизмы отображения файлов используемой операционной системы.

Производительность

Хотя быстродействие «старого» ввода/вывода было улучшено за счет переписывания его с учетом новых библиотек nio, техника отображения файлов качественно эффективнее. Следующая программа выполняет простое сравнение производительности:

//. io/MappedIO.java import java.nio.*. import java.nio.channels *; import java io.*,

public class MappedIO {

private static int numOflnts = 4000000, private static int numOfUbufflnts = 200000; private abstract static class Tester { private String name,

public Tester(String name) { this name = name. } public void runTestO {

System.out.print(name + ": "). try {

long start = System nanoTimeO; test;

double duration = System.nanoTimeO - start; System.out.formates 2f\n", duration/1.0e9); } catch(IOException e) {

throw new RuntimeException(e).

}

}

public abstract void testO throws IOException;

}

private static Tester[] tests = {

new Tester("Stream Write") {

public void testO throws IOException {

DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(

new FileOutputStream(new

FileC temp, tmp"))));

for(int i = 0; i < numOflnts; i++) dos writelnt(i); dos.closeO;

}

}.

new Tester("Mapped Write") {

public void testO throws IOException { FileChannel fc =

new RandomAccessFile("temp.tmp". "rw") getChannel; IntBuffer ib = fc map(

FileChannel .MapMode READ_WRITE, 0. fc sizeO) .asIntBufferO; for(int i = 0; i < numOflnts; i++)

ib.putCi); fc.closeO;

}

}.

new Tester("Stream Read") {

public void testO throws IOException {

DatalnputStream dis = new DatalnputStreamC new BufferedlnputStreamC

new F i1eInputSt rearn("temp.tmp"))); for(int i = 0; i < numOflnts; i++)

dis.readlntO; dis.closeO;

}

}.

new Tester("Mapped Read") {

public void testO throws IOException {

FileChannel fc = new FileInputStream(

new File("temp.tmp")).getChannelО; IntBuffer ib = fc.map(

Поделиться с друзьями: