מדריך ל- Java FileChannel

1. סקירה כללית

במדריך מהיר זה, נסתכל על FileChannel הכיתה הניתנת ב Java NIO סִפְרִיָה. נדון כיצד לקרוא ולכתוב נתונים באמצעות FileChannel ו ByteBuffer.

נבדוק גם את היתרונות של השימוש FileChannel וכמה מתכונות אחרות למניפולציית קבצים.

2. היתרונות של FileChannel

היתרונות של FileChannel לִכלוֹל:

  • קריאה וכתיבה במיקום ספציפי בקובץ
  • טעינת קטע מקובץ ישירות לזיכרון, שיכול להיות יעיל יותר
  • אנו יכולים להעביר נתוני קבצים מערוץ אחד לערוץ בקצב מהיר יותר
  • אנו יכולים לנעול חלק מקובץ כדי להגביל את הגישה על ידי שרשורים אחרים
  • כדי למנוע אובדן נתונים, אנו יכולים לאלץ כתיבת עדכונים לקובץ מיד לאחסון

3. קריאה עם FileChannel

FileChannel מבצע מהר יותר מאשר קלט / פלט רגיל כשאנחנו קוראים קובץ גדול.

עלינו לציין כי למרות שחלק מ Java NIO, FileChannel הפעולות חוסמות ואין לך מצב שאינו חוסם.

3.1. קריאת קובץ באמצעות FileChannel

בואו להבין איך לקרוא קובץ באמצעות FileChannel בקובץ המכיל:

שלום עולם

בדיקה זו קוראת את הקובץ ובודקת שהוא נקרא בסדר:

@Test ציבורי בטל givenFile_whenReadWithFileChannelUsingRandomAccessFile_thenCorrect () זורק IOException {try (RandomAccessFile reader = RandomAccessFile new ("src / test / resources / test_read.in", "r"); )) {int bufferSize = 1024; אם (bufferSize> channel.size ()) {bufferSize = (int) channel.size (); } Buff buff = ByteBuffer.allocate (bufferSize); בעוד (channel.read (buff)> 0) {out.write (buff.array (), 0, buff.position ()); buff.clear (); } מחרוזת fileContent = מחרוזת חדשה (out.toByteArray (), StandardCharsets.UTF_8); assertEquals ("שלום עולם", fileContent); }}

כאן קראנו בתים מהקובץ באמצעות FileChannel, RandomAccessFile, ו ByteBuffer.

עלינו לציין זאת גם ניתן להשתמש במספר נושאים בו זמנית ערוצי קבצים בצורה בטוחה. עם זאת, רק שרשור אחד בכל פעם מותר לפעולה הכוללת עדכון מיקום הערוץ או שינוי גודל הקובץ שלו. פעולה זו חוסמת שרשורים אחרים המנסים לבצע פעולה דומה עד להשלמת הפעולה הקודמת.

עם זאת, פעולות המספקות עמדות ערוץ מפורשות יכולות לפעול במקביל מבלי להיחסם.

3.2. פתיחת א FileChannel

על מנת לקרוא קובץ באמצעות FileChannel, עלינו לפתוח אותו.

בואו נראה איך לפתוח א FileChannel באמצעות RandomAccessFile:

קורא RandomAccessFile = RandomAccessFile חדש (קובץ, "r"); ערוץ FileChannel = reader.getChannel ();

מצב 'r' מציין שהערוץ 'פתוח לקריאה' בלבד. עלינו לציין כי סגירת א RandomAccessFile יסגור גם את הערוץ המשויך.

לאחר מכן נראה פתיחת א FileChannel לקרוא קובץ באמצעות FileInputStream:

FileInputStream סנפיר = FileInputStream חדש (קובץ); ערוץ FileChannel = fin.getChannel ();

באופן דומה, סגירת א FileInputStream סוגר גם את הערוץ המשויך אליו.

3.3. קריאת נתונים מא FileChannel

כדי לקרוא את הנתונים, נוכל להשתמש באחד מה- לקרוא שיטות.

בואו נראה איך לקרוא רצף של בתים. נשתמש ב- ByteBuffer להחזיק את הנתונים:

חובב ByteBuffer = ByteBuffer.allocate (1024); int noOfBytesRead = channel.read (buff); מחרוזת fileContent = מחרוזת חדשה (buff.array (), StandardCharsets.UTF_8); assertEquals ("שלום עולם", fileContent);

לאחר מכן נראה כיצד לקרוא רצף של בתים, החל ממיקום הקובץ:

חובב ByteBuffer = ByteBuffer.allocate (1024); int noOfBytesRead = channel.read (buff, 5); מחרוזת fileContent = מחרוזת חדשה (buff.array (), StandardCharsets.UTF_8); assertEquals ("עולם", fileContent);

עלינו לציין את הצורך ב- ערכת לפענח מערך בתים לתוך חוּט.

אנו מציינים את ערכת איתו המקודדים המקודדים במקור. בלי זה, אנו עשויים בסופו של דבר עם טקסט משובש. בפרט, קידודים מרובי בתים כמו UTF-8 ו UTF-16 יתכן שלא יוכלו לפענח קטע שרירותי בקובץ, מכיוון שחלק מהתווים המרובי בתים עשויים להיות לא שלמים.

4. כתיבה עם FileChannel

4.1. כתיבה לקובץ באמצעות FileChannel

בואו לחקור כיצד לכתוב באמצעות FileChannel:

@ מבחן ציבורי בטל כאשר WriteWithFileChannelUsingRandomAccessFile_thenCorrect () זורק IOException {String file = "src / test / resources / test_write_using_filechannel.txt"; נסה (כותב RandomAccessFile = RandomAccessFile חדש (קובץ, "rw"); ערוץ FileChannel = writer.getChannel ()) {ByteBuffer buff = ByteBuffer.wrap ("שלום עולם". getBytes (StandardCharsets.UTF_8)); channel.write (חובב); // אמת את הקורא RandomAccessFile = RandomAccessFile חדש (קובץ, "r"); assertEquals ("שלום עולם", reader.readLine ()); reader.close (); }}

4.2. פתיחת א FileChannel

על מנת לכתוב לקובץ באמצעות FileChannel, עלינו לפתוח אותו.

בואו נראה איך לפתוח א FileChannel באמצעות RandomAccessFile:

כותב RandomAccessFile = RandomAccessFile חדש (קובץ, "rw"); ערוץ FileChannel = author.getChannel ();

מצב 'rw' מציין שהערוץ 'פתוח לקריאה וכתיבה'.

בואו נראה גם איך לפתוח א FileChannel באמצעות FileOutputStream:

FileOutputStream fout = FileOutputStream חדש (קובץ); ערוץ FileChannel = fout.getChannel (); 

4.3. כתיבת נתונים עם FileChannel

לכתוב נתונים עם FileChannel, נוכל להשתמש באחד מה- לִכתוֹב שיטות.

בואו נראה איך לכתוב רצף של בתים, בעזרת a ByteBuffer לאחסון הנתונים:

ByteBuffer buff = ByteBuffer.wrap ("שלום עולם" .getBytes (StandardCharsets.UTF_8)); channel.write (חובב); 

לאחר מכן נראה כיצד לכתוב רצף של בתים, החל מיקום קובץ:

ByteBuffer buff = ByteBuffer.wrap ("שלום עולם" .getBytes (StandardCharsets.UTF_8)); channel.write (חובב, 5); 

5. מיקום נוכחי

FileChannel מאפשר לנו להשיג ולשנות את המיקום בו אנו קוראים או כותבים.

בואו נראה איך להשיג את המיקום הנוכחי:

OriginalPosition ארוך = channel.position ();

לאחר מכן, בואו נראה כיצד להגדיר את המיקום:

channel.position (5); assertEquals (OriginalPosition + 5, channel.position ());

6. קבל את גודל הקובץ

בואו נראה כיצד להשתמש ב- FileChannel.size שיטה לקבלת גודל הקובץ בתים:

@ מבחן ציבורי בטל כאשר GetFileSize_thenCorrect () זורק IOException {RandomAccessFile reader = חדש RandomAccessFile ("src / test / resources / test_read.in", "r"); ערוץ FileChannel = reader.getChannel (); // גודל הקובץ המקורי הוא 11 בתים. assertEquals (11, channel.size ()); channel.close (); reader.close (); }

7. חתוך קובץ

בואו נבין כיצד להשתמש ב- FileChannel.truncate שיטה לקטוע קובץ לגודל נתון בתים:

@Test הציבור בטל כאשרTruncateFile_thenCorrect () זורק IOException {String input = "זה קלט בדיקה"; FileOutputStream fout = FileOutputStream חדש ("src / test / resources / test_truncate.txt"); ערוץ FileChannel = fout.getChannel (); ByteBuffer buff = ByteBuffer.wrap (input.getBytes ()); channel.write (חובב); buff.flip (); channel = channel.truncate (5); assertEquals (5, channel.size ()); fout.close (); channel.close (); } 

8. כפה עדכון קובץ לאחסון

מערכת הפעלה עשויה לשמור במטמון שינויים בקובץ מטעמי ביצועים ונתונים עלולים לאבד אם המערכת קורסת. כדי לאלץ תוכן קבצים ומטא נתונים לכתוב לדיסק ברציפות אנו יכולים להשתמש ב- כּוֹחַ שיטה:

channel.force (נכון);

שיטה זו מובטחת רק כאשר הקובץ שוכן בהתקן מקומי.

9. טען חלק מקובץ בזיכרון

בואו נראה כיצד לטעון קטע מקובץ בזיכרון באמצעות FileChannel.map. אנו משתמשים FileChannel.MapMode.READ_ONLY כדי לפתוח את הקובץ במצב קריאה בלבד:

@Test ציבורי בטל givenFile_whenReadAFileSectionIntoMemoryWithFileChannel_thenCorrect () זורק IOException {נסה (RandomAccessFile reader = חדש RandomAccessFile ("src / test / resources / test_read.in", "r"); FileChannel channel = reader.getStreamarray); )) {MappedByteBuffer buff = channel.map (FileChannel.MapMode.READ_ONLY, 6, 5); אם (buff.hasRemaining ()) {בייט [] נתונים = בתים חדשים [buff.remaining ()]; buff.get (נתונים); assertEquals ("עולם", מחרוזת חדשה (נתונים, StandardCharsets.UTF_8)); }}}

באופן דומה, אנו יכולים להשתמש FileChannel.MapMode.READ_WRITE כדי לפתוח את הקובץ למצב קריאה וכתיבה.

אנחנו יכולים גם להשתמשFileChannel.MapMode.PRIVATE במצב, שבו השינויים אינם חלים על הקובץ המקורי.

10. נועל קטע מקובץ

בואו ונבין כיצד לנעול קטע מקובץ כדי למנוע גישה מקבילה לקטע באמצעות ה- FileChannel.tryLock שיטה:

@Test ציבורי בטל givenFile_whenWriteAFileUsingLockAFileSectionWithFileChannel_thenCorrect () זורק IOException {try (RandomAccessFile reader = new RandomAccessFile ("src / test / resources / test_read.in", "rw"); FileChannel channel = reader.get; (6, 5, Boolean.FALSE)) {// מבצעים פעולות אחרות ... assertNotNull (fileLock); }}

ה tryLock השיטה מנסה לרכוש נעילה במקטע הקבצים. אם קטע הקובץ המבוקש כבר חסום על ידי שרשור אחר, הוא משליך OverlappingFileLockException יוצא מן הכלל. שיטה זו לוקחת גם א בוליאני פרמטר לבקש נעילה משותפת או נעילה בלעדית.

עלינו לשים לב כי ייתכן שמערכות הפעלה מסוימות אינן מאפשרות נעילה משותפת, אך ברירת מחדל נעילה בלעדית.

11. סגירה א FileChannel

לבסוף, כשסיימנו להשתמש ב- FileChannelאנחנו חייבים לסגור את זה. בדוגמאות שלנו השתמשנו נסה עם משאבים.

במידת הצורך נוכל לסגור את FileChannel ישירות עם סגור שיטה:

channel.close ();

12. מסקנה

במדריך זה ראינו איך להישתמש FileChannel לקרוא ולכתוב קבצים. בנוסף, בדקנו כיצד לקרוא ולשנות את גודל הקובץ ואת מיקום הקריאה / כתיבה הנוכחי שלו ובדקנו כיצד להשתמש בו ערוצי קבצים ביישומים בו זמנית או נתונים קריטיים.

כמו תמיד, קוד המקור לדוגמאות זמין ב- GitHub.


$config[zx-auto] not found$config[zx-overlay] not found