Menggunakan Java MappedByteBuffer

1. Gambaran keseluruhan

Dalam artikel ringkas ini, kita akan melihat MappedByteBuffer dalam pakej java.nio . Utiliti ini sangat berguna untuk pembacaan fail yang cekap.

2. Bagaimana MappedByteBuffer W Orks

Semasa kita memuatkan kawasan fail, kita dapat memuatnya ke kawasan memori tertentu yang dapat diakses kemudian.

Apabila kita tahu bahawa kita perlu membaca kandungan fail berkali-kali, ada baiknya kita mengoptimumkan proses yang mahal, misalnya dengan menyimpan kandungan tersebut dalam memori. Terima kasih untuk itu, pencarian bahagian fail berikutnya hanya akan masuk ke memori utama tanpa perlu memuatkan data dari cakera, mengurangkan latensi dengan ketara.

Satu perkara yang perlu kita berhati-hati ketika menggunakan MappedByteBuffer adalah ketika kita bekerja dengan fail yang sangat besar dari cakera - kita perlu memastikan fail itu sesuai dengan memori .

Jika tidak, kita dapat mengisi keseluruhan ingatan dan, sebagai akibatnya, mengalami OutOfMemoryException yang biasa . Kita dapat mengatasinya dengan memuat hanya sebahagian dari file - berdasarkan contohnya pada pola penggunaan.

3. Membaca Fail Menggunakan MappedByteBuffer

Katakan bahawa kita mempunyai fail bernama fileToRead.txt dengan kandungan berikut:

This is a content of the file

Fail terletak di direktori / sumber sehingga kita dapat memuatnya menggunakan fungsi berikut:

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

Untuk membuat MappedByteBuffer dari fail, pertama kita perlu membuat FileChannel darinya. Sebaik sahaja kami telah saluran kami dicipta, kita boleh ingat kepada peta () kaedah di atasnya lulus dalam MapMode, satu kedudukan dari mana kita mahu membaca, dan saiz parameter yang menentukan berapa banyak bait kita mahu:

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); } }

Sebaik sahaja kami memetakan fail kami ke dalam buffer pemetaan memori, kami dapat membaca data dari dalamnya ke CharBuffer. Penting untuk diperhatikan adalah bahawa walaupun kita membaca kandungan fail ketika kita memanggil kaedah decode () melewati MappedByteBuffer, kita membaca dari memori, bukan dari cakera. Oleh itu, membaca akan menjadi sangat pantas.

Kami dapat menegaskan bahawa kandungan yang kami baca dari fail kami adalah kandungan sebenar dari fileToRead.txt :

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

Setiap pembacaan berikutnya dari mappedByteBuffer akan sangat cepat kerana kandungan fail dipetakan dalam memori dan pembacaan dilakukan tanpa perlu mencari data dari cakera.

4. Menulis ke Fail Menggunakan MappedByteBuffer

Katakan bahawa kami ingin menulis beberapa kandungan ke dalam file fileToWriteTo.txt menggunakan API MappedByteBuffer . Untuk mencapainya kita perlu membuka FileChannel dan memanggil kaedah peta () di atasnya, melewati FileChannel.MapMode.READ_WRITE.

Seterusnya, kita dapat menyimpan kandungan CharBuffer ke dalam fail menggunakan kaedah put () dari 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)); } }

Kami dapat menegaskan bahawa kandungan charBuffer sebenarnya ditulis ke fail dengan membaca kandungannya:

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

5. Kesimpulan

Dalam tutorial ringkas ini, kami melihat konstruksi MappedByteBuffer dari pakej java.nio .

Ini adalah cara yang sangat cekap untuk membaca kandungan fail berkali-kali, kerana fail dipetakan ke dalam memori dan pembacaan berikutnya tidak perlu pergi ke cakera setiap masa.

Semua contoh dan coretan kod ini boleh didapati di GitHub - ini adalah projek Maven, jadi mudah diimport dan dijalankan sebagaimana adanya.