Fájl zárolása a Java-ban

1. Áttekintés

Fájlok olvasásakor vagy írásakor meg kell győződnünk arról, hogy megfelelő fájlzárolási mechanizmusok vannak-e érvényben. Ez biztosítja az adatok integritását egyidejű I / O alapú alkalmazásokban.

Ebben az oktatóanyagban különböző megközelítéseket veszünk szemügyre ennek elérése érdekében a Java NIO könyvtár segítségével.

2. Bevezetés a fájlzárakba

Általában kétféle zár létezik:

    • Exkluzív zárak - más néven írási zárak
    • Megosztott zárak - olvasható záraknak is nevezik

Leegyszerűsítve: az exkluzív zár megakadályozza az összes többi műveletet - beleértve az olvasást is -, miközben az írási művelet befejeződik.

Ezzel szemben a megosztott zár lehetővé teszi több folyamat egyidejű olvasását. Az olvasási zár lényege, hogy megakadályozza az írási zár megszerzését egy másik folyamat által. A következetes állapotú fájloknak általában bármilyen folyamatnak olvashatónak kell lennie.

A következő részben megnézzük, hogyan kezeli a Java az ilyen típusú zárakat.

3. Fájlzárak a Java-ban

A Java NIO könyvtár lehetővé teszi a fájlok zárolását az operációs rendszer szintjén. A zár() és tryLock () módszerek a FileChannel arra a célra szolgálnak.

Hozhatunk létre a FileChannel akár a FileInputStream, a FileOutputStream, vagy a RandomAccessFile. Mindháromnak van egy getChannel () metódus, amely a FileChannel.

Alternatív megoldásként létrehozhatunk egy FileChannel közvetlenül a statikuson keresztül nyisd ki módszer:

próbáld meg (FileChannel channel = FileChannel.open (elérési út, openOptions)) {// írj a csatornára}

Ezután megvizsgáljuk a különféle lehetőségeket az exkluzív és megosztott zárak megszerzésére a Java-ban. Ha többet szeretne megtudni a fájlcsatornákról, olvassa el a Java FileChannel bemutató útmutatónkat.

4. Exkluzív zárak

Mint már megtudtuk, egy fájlba való írás közben exkluzív zár használatával megakadályozhatjuk más folyamatok beolvasását vagy írását.

Exkluzív zárakat kapunk hívással zár() vagy tryLock () a FileChannel osztály. Használhatjuk a túlterhelt módszereiket is:

  • zár (hosszú helyzet, hosszú méret, logikai megosztott)
  • tryLock (hosszú pozíció, hosszú méret, logikai megosztott)

Ezekben az esetekben a megosztva paramétert állítani kell hamis.

Egy exkluzív zár megszerzéséhez írhatót kell használnunk FileChannel. A getChannel () módszerek a FileOutputStream vagy a RandomAccessFile. Alternatív megoldásként, amint azt korábban említettük, használhatjuk a statikát nyisd ki módszere FileChannel osztály. Csak a második érvre van szükségünk StandardOpenOption.APPEND:

próbáld meg (FileChannel channel = FileChannel.open (elérési út, StandardOpenOption.APPEND)) {// írj a csatornára}

4.1. Exkluzív zárak a FileOutputStream

A FileChannel alapján létrehozott FileOutputStream írható. Ezért megszerezhetünk egy exkluzív zárat:

próbáld meg (FileOutputStream fileOutputStream = new FileOutputStream ("/ tmp / testfile.txt"); FileChannel channel = fileOutputStream.getChannel (); FileLock lock = channel.lock ()) {// írj a csatornára}

Itt, channel.lock () vagy blokkol, amíg nem kap zárat, vagy kivételt vet. Például, ha a megadott régió már zárolva van, akkor egy ÁtfedőFileLockException dobják. A lehetséges kivételek teljes listáját lásd a Javadoc-ban.

Nem blokkoló zárat is használhatunk channel.tryLock (). Ha nem sikerül zárat kapnia, mert egy másik program átfedést tart, akkor visszatér nulla. Ha ezt más okból elmulasztja, akkor megfelelő kivételt vetnek be.

4.2. Exkluzív zárak a RandomAccessFile

Val,-vel RandomAccessFile, meg kell adnunk a flageket a konstruktor második paraméterén.

Itt meg fogjuk nyitni a fájlt olvasási és írási engedéllyel:

próbálkozzon (RandomAccessFile fájl = új RandomAccessFile ("/ tmp / testfile.txt", "rw"); FileChannel csatorna = file.getChannel (); FileLock lock = channel.lock ()) {// írjon a csatornára} 

Ha csak olvasható módban nyitjuk meg a fájlt, és megpróbálunk a csatornájára írni, akkor a NonWritableChannelException.

4.3. Az exkluzív zárak írhatót igényelnek FileChannel

Mint korábban említettük, az exkluzív záraknak írható csatornára van szükségük. Ezért nem kaphatunk exkluzív zárat a FileChannel alapján létrehozott FileInputStream:

Elérési útvonal = Files.createTempFile ("foo", "txt"); Naplózó napló = LoggerFactory.getLogger (this.getClass ()); próbáld meg (FileInputStream fis = új FileInputStream (elérési út.File ()); FileLock-zár = fis.getChannel (). lock ()) {// elérhetetlen kód} catch (NonWritableChannelException e) {// kezelési kivétel}

A fenti példában a zár() módszer dobja a NonWritableChannelException. Valóban, ez azért van, mert mi hivatkozunk getChannel rajta FileInputStream, amely csak olvasható csatornát hoz létre.

Ez a példa csak annak bemutatására szolgál, hogy nem írhatunk nem írható csatornára. Valódi forgatókönyv szerint nem foghatnánk fel és nem ismételhetnénk meg a kivételt.

5. Közös zárak

Ne feledje, hogy megosztott zárakat is hívnak olvas zárak. Ezért az olvasási zár megszerzéséhez olvashatót kell használnunk FileChannel.

Ilyen FileChannel hívható a getChannel () módszer a FileInputStream vagy a RandomAccessFile. Ismét egy másik lehetőség a statikus használat nyisd ki módszere FileChannel osztály. Ebben az esetben a második argumentumot állítottuk be StandardOpenOption.READ:

próbáld meg (FileChannel channel = FileChannel.open (elérési út, StandardOpenOption.READ); FileLock lock = channel.lock (0, Long.MAX_VALUE, true)) {// a csatornáról olvasva}

Egy dolgot érdemes megjegyezni, hogy úgy döntöttünk, hogy a teljes fájlt lezárjuk hívással zár (0, Hosszú.MAX_VALUE, igaz). A fájlnak csak egy meghatározott régióját is lezárhattuk volna, ha az első két paramétert különböző értékekre változtattuk. A harmadik paramétert állítani kell igaz megosztott zár esetén.

A dolgok egyszerűbbé tétele érdekében az egész fájlt lezárjuk az összes alábbi példában, de ne felejtsük el, hogy a fájl egy adott területét mindig lezárhatjuk.

5.1. Megosztott zárak a FileInputStream

A FileChannel nyert a FileInputStream olvasható. Ezért közös zárat kaphatunk:

próbáld meg (FileInputStream fileInputStream = new FileInputStream ("/ tmp / testfile.txt"); FileChannel channel = fileInputStream.getChannel (); FileLock lock = channel.lock (0, Long.MAX_VALUE, true)) {// a csatornáról olvasva }

A fenti részletben a hívás zár() a csatornán sikerülni fog. Ennek oka, hogy a megosztott zároláshoz csak a csatorna olvashatóságára van szükség. Ez a helyzet itt, mivel a FileInputStream.

5.2. Megosztott zárak a RandomAccessFile

Ezúttal a just fájlmal nyithatjuk meg a fájlt olvas engedélyek:

próbálkozzon (RandomAccessFile fájl = új RandomAccessFile ("/ tmp / testfile.txt", "r"); FileChannel csatorna = file.getChannel (); FileLock lock = channel.lock (0, Long.MAX_VALUE, true)) {// olvasás a csatornáról}

Ebben a példában létrehoztuk a RandomAccessFile olvasási engedéllyel. Létrehozhatunk belőle olvasható csatornát, és így létrehozhatunk egy megosztott zárat.

5.3. A megosztott zárakhoz olvasmány szükséges FileChannel

Ezért nem szerezhetünk megosztott zárat a FileChannel alapján létrehozott FileOutputStream:

Elérési útvonal = Files.createTempFile ("foo", "txt"); próbáld meg (FileOutputStream fis = new FileOutputStream (path.toFile ()); FileLock lock = fis.getChannel (). lock (0, Long.MAX_VALUE, true)) {// elérhetetlen kód} catch (NonWritableChannelException e) {// fogantyú kivétel} 

Ebben a példában a zár() megpróbál megosztott zárolást szerezni az a-ból létrehozott csatornán FileOutputStream. Egy ilyen csatorna csak írható. Nem teljesíti azt az igényt, hogy a csatornának olvashatónak kell lennie. Ez kiváltja a NonWritableChannelException.

Ez a részlet is csak annak bemutatására szolgál, hogy nem olvashatunk nem olvasható csatornáról.

6. Fontos dolgok

A gyakorlatban a fájlzárak használata nehéz; a reteszelő mechanizmusok nem hordozhatóak. Ezt szem előtt tartva kell kialakítanunk a zárolási logikánkat.

A POSIX rendszerekben a zárak tanácsosak. Egy adott fájlba olvasás vagy írás során különböző folyamatoknak meg kell egyezniük a zárolási protokollban. Ez biztosítja a fájl integritását. Maga az operációs rendszer nem hajt végre semmilyen zárolást.

Windows rendszeren a zárak csak akkor lesznek kizárólagosak, ha a megosztás engedélyezett. Az operációs rendszer-specifikus mechanizmusok előnyeinek vagy hátrányainak megvitatása nem tartozik e cikk hatálya alá. A reteszelő mechanizmus megvalósításakor mégis fontos ismerni ezeket az árnyalatokat.

7. Következtetés

Ebben az oktatóanyagban több különböző lehetőséget is megvizsgáltunk a fájlzárak megszerzéséhez a Java-ban.

Először a két fő zárolási mechanizmus megértésével kezdtük, és hogy a Java NIO könyvtár hogyan segíti elő a fájlok zárolását. Ezután áttekintettünk egy sor egyszerű példát, amelyek bemutatják, hogy exkluzív és megosztott zárakat szerezhetünk be alkalmazásainkban. Megvizsgáltuk azokat a tipikus kivételeket is, amelyekkel a fájlzárakkal való munka során találkozhatunk.

Mint mindig, a példák forráskódja elérhető a GitHubon.