Използване на Java MappedByteBuffer

1. Общ преглед

В тази бърза статия ще разгледаме MappedByteBuffer в пакета java.nio . Тази помощна програма може да бъде доста полезна за ефективно четене на файлове.

2. Как работи MappedByteBuffer

Когато зареждаме регион на файла, можем да го заредим в конкретния регион на паметта, който може да бъде достъпен по-късно.

Когато знаем, че ще трябва да прочетем съдържанието на даден файл няколко пъти, е добра идея да оптимизираме скъпия процес, например като запазим това съдържание в паметта. Благодарение на това последващото търсене на тази част от файла ще отиде само в основната памет, без да е необходимо да се зареждат данните от диска, което значително намалява латентността.

Едно нещо, с което трябва да внимаваме, когато използваме MappedByteBuffer, е когато работим с много големи файлове от диск - трябва да се уверим, че файлът ще се побере в паметта .

В противен случай можем да запълним цялата памет и като следствие да се сблъскаме с общия OutOfMemoryException. Можем да го преодолеем, като заредим само част от файла - базиран например на модели на използване.

3. Четене на файла с помощта на MappedByteBuffer

Да кажем, че имаме файл, наречен fileToRead.txt със следното съдържание:

This is a content of the file

Файлът се намира в директорията / resource, за да можем да го заредим, като използваме следната функция:

Path getFileURIFromResources(String fileName) throws Exception { ClassLoader classLoader = getClass().getClassLoader(); return Paths.get(classLoader.getResource(fileName).getPath()); }

За да създадем MappedByteBuffer от файл, първо трябва да създадем FileChannel от него. След като сме създали нашия канал, ние можем да се позове на карта () метода върху него преминава в MapMode, на позиция , от която искаме да се чете, както и размера на параметър, който определя колко байта, които искаме:

CharBuffer charBuffer = null; Path pathToRead = getFileURIFromResources("fileToRead.txt"); try (FileChannel fileChannel (FileChannel) Files.newByteChannel( pathToRead, EnumSet.of(StandardOpenOption.READ))) { MappedByteBuffer mappedByteBuffer = fileChannel .map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size()); if (mappedByteBuffer != null) { charBuffer = Charset.forName("UTF-8").decode(mappedByteBuffer); } }

След като картографираме нашия файл в картографирания буфер, можем да прочетем данните от него в CharBuffer. Важно е да се отбележи, че въпреки че четем съдържанието на файла, когато извикаме метода decode () , преминавайки MappedByteBuffer, ние четем от паметта, а не от диска. Следователно четенето ще бъде много бързо.

Можем да твърдим, че съдържанието, което четем от нашия файл, е действителното съдържание на файла fileToRead.txt :

assertNotNull(charBuffer); assertEquals( charBuffer.toString(), "This is a content of the file");

Всяко следващо четене от mappedByteBuffer ще бъде много бързо, защото съдържанието на файла се картографира в паметта и четенето се извършва, без да е необходимо да се търсят данни от диска.

4. Записване във файла с помощта на MappedByteBuffer

Да кажем, че искаме да напишем малко съдържание във файла fileToWriteTo.txt с помощта на API MappedByteBuffer . За да постигнем това, трябва да отворим FileChannel и да извикаме метода map () върху него, като предадем FileChannel.MapMode.READ_WRITE.

След това можем да запишем съдържанието на CharBuffer във файла, използвайки метода put () от MappedByteBuffer:

CharBuffer charBuffer = CharBuffer .wrap("This will be written to the file"); Path pathToWrite = getFileURIFromResources("fileToWriteTo.txt"); try (FileChannel fileChannel = (FileChannel) Files .newByteChannel(pathToWrite, EnumSet.of( StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING))) { MappedByteBuffer mappedByteBuffer = fileChannel .map(FileChannel.MapMode.READ_WRITE, 0, charBuffer.length()); if (mappedByteBuffer != null) { mappedByteBuffer.put( Charset.forName("utf-8").encode(charBuffer)); } }

Можем да твърдим, че действителното съдържание на charBuffer е записано във файла, като четем съдържанието на него:

List fileContent = Files.readAllLines(pathToWrite); assertEquals(fileContent.get(0), "This will be written to the file");

5. Заключение

В този бърз урок разглеждахме конструкцията MappedByteBuffer от пакета java.nio .

Това е много ефективен начин за многократно четене на съдържанието на файла, тъй като файлът се картографира в паметта и следващите четения не трябва да отиват на диск всеки път.

Всички тези примери и кодови фрагменти могат да бъдат намерени в GitHub - това е проект на Maven, така че трябва да е лесно да се импортира и да се изпълнява както е.