Útmutató a Java FileChannelhez
1. Áttekintés
Ebben a gyors bemutatóban megnézzük a FileChannel osztályban biztosított Java NIO könyvtár. Megbeszéljük hogyan lehet adatokat olvasni és írni FileChannel és ByteBuffer.
Megvizsgáljuk a használat előnyeit is FileChannel és néhány más fájlkezelési funkciója.
2. A. Előnyei FileChannel
A. Előnyei FileChannel tartalmazza:
- Olvasás és írás fájlban egy adott helyen
- A fájl egy szakaszának betöltése a memóriába, ami hatékonyabb lehet
- Gyorsabb sebességgel továbbíthatjuk a fájladatokat egyik csatornáról a másikra
- Zárolhatunk egy fájl egy részét, hogy korlátozzuk a hozzáférést más szálakhoz
- Az adatvesztés elkerülése érdekében kényszeríthetjük a fájl frissítéseinek azonnali tárolására
3. Olvasás vele FileChannel
FileChannel gyorsabban teljesít, mint a szokásos I / O, ha nagy fájlt olvasunk.
Meg kell jegyeznünk, hogy bár a Java NIO, FileChannel a műveletek blokkolják és nem rendelkezik nem blokkoló üzemmóddal.
3.1. Fájl olvasása a FileChannel
Értsük meg, hogyan kell egy fájlt elolvasni FileChannel fájlon, amely a következőket tartalmazza:
Helló Világ
Ez a teszt elolvassa a fájlt, és ellenőrzi, hogy rendben van-e:
@Test public void givenFile_whenReadWithFileChannelUsingRandomAccessFile_thenCorrect () dobja az IOException {próbálkozzon (RandomAccessFile olvasó = új RandomAccessFile ("src / test / erőforrások / test_read.in", "r"); FileChannel csatorna = olvasó )) {int bufferSize = 1024; if (bufferSize> channel.size ()) {bufferSize = (int) channel.size (); } ByteBuffer buff = ByteBuffer.allocate (bufferSize); while (csatorna.olvasott (buff)> 0) {out.write (buff.array (), 0, buff.position ()); buff.clear (); } String fileContent = új karakterlánc (out.toByteArray (), StandardCharsets.UTF_8); assertEquals ("Hello world", fileContent); }}
Itt bájtokat olvasunk a fájlból a FileChannel, RandomAccessFile, és ByteBuffer.
Azt is meg kell jegyeznünk több egyidejű szál használható FileChannels biztonságosan. Ugyanakkor egyszerre csak egy szál engedélyezett olyan művelet, amely magában foglalja a csatorna helyzetének frissítését vagy a fájlméret megváltoztatását. Ez megakadályozza, hogy más szálak hasonló műveletet kíséreljenek meg, amíg az előző művelet be nem fejeződik.
A kifejezett csatornapozíciókat biztosító műveletek azonban blokkolás nélkül egyidejűleg is futhatnak.
3.2. Nyitás a FileChannel
A fájl használatával a FileChannel, ki kell nyitnunk.
Nézzük meg, hogyan lehet megnyitni a FileChannel felhasználásával RandomAccessFile:
RandomAccessFile reader = új RandomAccessFile (fájl, "r"); FileChannel csatorna = reader.getChannel ();
Az „r” mód azt jelzi, hogy a csatorna „csak olvasásra van nyitva”. Meg kell jegyeznünk, hogy a záró a RandomAccessFile bezárja a társított csatornát is.
Ezután meglátjuk a FileChannel fájl használatával FileInputStream:
FileInputStream fin = új FileInputStream (fájl); FileChannel csatorna = fin.getChannel ();
Hasonlóképpen a FileInputStream bezárja a hozzá tartozó csatornát is.
3.3. Adatok olvasása a FileChannel
Az adatok kiolvasásához használhatjuk a olvas mód.
Lássuk, hogyan olvassuk el a bájtsort. Használjuk a ByteBuffer az adatok tárolásához:
ByteBuffer buff = ByteBuffer.allocate (1024); int noOfBytesRead = csatorna.olvasott (buff); String fileContent = új karakterlánc (buff.array (), StandardCharsets.UTF_8); assertEquals ("Hello world", fileContent);
Ezután meglátjuk, hogyan olvassuk el a bájtsorozatot, egy fájl helyzetétől kezdve:
ByteBuffer buff = ByteBuffer.allocate (1024); int noOfBytesRead = channel.read (buff, 5); String fileContent = új karakterlánc (buff.array (), StandardCharsets.UTF_8); assertEquals ("világ", fileContent);
Meg kell jegyeznünk a Charset hogy dekódoljon egy bájt tömböt Húr.
Megadjuk a Charset amellyel a bájtokat eredetileg kódolták. Nélküle, zűrzavaros szöveget eredményezhetünk. Különösen a többbájtos kódolások, mint a UTF-8 és UTF-16 lehet, hogy nem tudja dekódolni a fájl tetszőleges szakaszát, mivel a több bájtos karakterek egy része hiányos lehet.
4. Írás vele FileChannel
4.1. Írása fájlba a következővel: FileChannel
Fedezzük fel, hogyan kell írni FileChannel:
@Test public void, amikor aWriteWithFileChannelUsingRandomAccessFile_thenCorrect () dobja az IOException {String file = "src / test / resources / test_write_using_filechannel.txt" parancsot; próbáld (RandomAccessFile író = új RandomAccessFile (fájl, "rw"); FileChannel csatorna = író.getChannel ()) {ByteBuffer buff = ByteBuffer.wrap ("Hello world" .getBytes (StandardCharsets.UTF_8)); channel.write (buff); // RandomAccessFile olvasó ellenőrzése = new RandomAccessFile (fájl, "r"); assertEquals ("Hello world", reader.readLine ()); olvasó.zárja (); }}
4.2. Nyitás a FileChannel
A fájl használatával a FileChannel, ki kell nyitnunk.
Nézzük meg, hogyan lehet megnyitni a FileChannel felhasználásával RandomAccessFile:
RandomAccessFile író = új RandomAccessFile (fájl, "rw"); FileChannel csatorna = író.getChannel ();
Az „rw” mód azt jelzi, hogy a csatorna „nyitott olvasásra és írásra”.
Lássuk azt is, hogyan lehet megnyitni a FileChannel felhasználásával FileOutputStream:
FileOutputStream fout = új FileOutputStream (fájl); FileChannel csatorna = fout.getChannel ();
4.3. Adatok írása a következővel: FileChannel
Adatok írása a FileChannel, használhatjuk a ír mód.
Lássuk, hogyan írhatunk bájtsorozatot az a használatával ByteBuffer az adatok tárolásához:
ByteBuffer buff = ByteBuffer.wrap ("Hello world" .getBytes (StandardCharsets.UTF_8)); channel.write (buff);
Ezután meglátjuk, hogyan kell írni egy bájtsorozatot, egy fájl helyzetétől kezdve:
ByteBuffer buff = ByteBuffer.wrap ("Hello world" .getBytes (StandardCharsets.UTF_8)); channel.write (buff, 5);
5. Jelenlegi helyzet
FileChannel lehetővé teszi számunkra, hogy megszerezzük és megváltoztassuk azt a pozíciót, amelyen olvasunk vagy írunk.
Lássuk, hogyan kaphatjuk meg az aktuális pozíciót:
hosszú eredetiPosition = channel.position ();
Ezután nézzük meg, hogyan állítsuk be a pozíciót:
csatorna.helyzet (5); assertEquals (eredetiPozíció + 5, csatorna.pozíció ());
6. Szerezze meg a fájl méretét
Lássuk, hogyan kell használni a FileChannel.size módszer a fájl méretének bájtokban történő megszerzésére:
@Test public void, amikor a GETFileSize_thenCorrect () az IOException-t dobja {RandomAccessFile reader = new RandomAccessFile ("src / test / resources / test_read.in", "r"); FileChannel csatorna = reader.getChannel (); // az eredeti fájlméret 11 bájt. assertEquals (11, channel.size ()); csatorna.zár (); olvasó.zárja (); }
7. Csonkoljon meg egy fájlt
Értsük meg, hogyan kell használni a FileChannel.truncate módszer egy fájl bájtban megadott méretre csonkolásához:
@Test public void, amikor aTruncateFile_thenCorrect () IOException-t dob {String input = "ez egy tesztbevitel"; FileOutputStream fout = új FileOutputStream ("src / test / resources / test_truncate.txt"); FileChannel csatorna = fout.getChannel (); ByteBuffer buff = ByteBuffer.wrap (input.getBytes ()); channel.write (buff); buff.flip (); csatorna = channel.truncate (5); assertEquals (5, channel.size ()); fout.close (); csatorna.zár (); }
8. Kényszerítse a fájlfrissítést a tárolóba
Az operációs rendszer teljesítmény okokból gyorsítótárba helyezheti a fájlokat, és a rendszer összeomlása esetén elveszhetnek az adatok. A fájl tartalmának és metaadatainak folyamatos lemezre írására kényszerítésére használhatjuk a Kényszerítés módszer:
channel.force (true);
Ez a módszer csak akkor garantált, ha a fájl helyi eszközön található.
9. Töltse be a fájl egy részét a memóriába
Lássuk, hogyan tölthetünk be egy fájl egy részét a memóriába a segítségével FileChannel.map. Használunk FileChannel.MapMode.READ_ONLY a fájl írásvédett módban történő megnyitásához:
@Test public void givenFile_whenReadAFileSectionIntoMemoryWithFileChannel_thenCorrect () dobja az IOException {try (RandomAccessFile olvasó = új RandomAccessFile ("src / test / resources / test_read.in", "r"); FileChannel csatorna = olvasó )) {MappedByteBuffer buff = channel.map (FileChannel.MapMode.READ_ONLY, 6, 5); if (buff.hasRemaining ()) {byte [] data = új byte [buff.remaining ()]; buff.get (adatok); assertEquals ("világ", új String (adatok, StandardCharsets.UTF_8)); }}}
Hasonlóképpen használhatjuk FileChannel.MapMode.READ_WRITE a fájl olvasási és írási módba történő megnyitásához.
Használhatjuk isFileChannel.MapMode.PRIVATE mód, ahol a változtatások nem vonatkoznak az eredeti fájlra.
10. Zárolja le a fájl egy részét
Tisztázzuk, hogyan zárolhatunk egy fájl egy szakaszát, hogy megakadályozzuk a szakasz egyidejű hozzáférését a FileChannel.tryLock módszer:
@Test public void givenFile_whenWriteAFileUsingLockAFileSectionWithFileChannel_thenCorrect () dobja az IOException {try (RandomAccessFile olvasó = új RandomAccessFile ("src / teszt / erőforrások / test_read.in", "rw"); FileChannel csatorna.olvasó (6, 5, Boolean.FALSE)) {// egyéb műveletek végrehajtása ... assertNotNull (fileLock); }}
A tryLock metódus megpróbálja megszerezni a fájlrész zárját. Ha a kért fájlszakaszt már letiltotta egy másik szál, akkor egy ÁtfedőFileLockException kivétel. Ez a módszer a logikai paraméter egy megosztott zár vagy egy kizárólagos zár kérésére.
Meg kell jegyeznünk, hogy egyes operációs rendszerek nem engedélyezik a megosztott zárolást, ehelyett alapértelmezés szerint egy kizárólagos zárat használnak.
11. Zárás a FileChannel
Végül, ha elkészültünk az a használatával FileChannel, be kell zárnunk. Példáinkban használtuk erőforrásokkal próbálkozzon.
Ha szükséges, bezárhatjuk a FileChannel közvetlenül a Bezárás módszer:
csatorna.zár ();
12. Következtetés
Ebben az oktatóanyagban láttuk hogyan kell használni FileChannel fájlok olvasására és írására. Ezen felül megvizsgáltuk a fájlméret és annak jelenlegi olvasási / írási helyének olvasási és módosítási módját, valamint megvizsgáltuk a használat módját FileChannels egyidejű vagy adatkritikus alkalmazásokban.
Mint mindig, a példák forráskódja elérhető a GitHubon.