ג'אווה - כתוב לקובץ

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

במדריך זה, נחקור דרכים שונות לכתוב לקובץ באמצעות Java. נשתמש BufferedWriter, PrintWriter, FileOutputStream, DataOutputStream, RandomAccessFile, FileChannel, ו- Java 7 קבצים מחלקת שירות.

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

מדריך זה הוא חלק מסדרת Java "Back to Basics" כאן על Baeldung.

2. כתוב עם BufferedWriter

נתחיל בפשטות ולהשתמש BufferedWriter לכתוב א חוּט לקובץ חדש:

חלל ציבורי כאשר WritingStringUsingBufferedWritter_thenCorrect () זורק IOException {String str = "שלום"; כותב BufferedWriter = BufferedWriter חדש (FileWriter חדש (fileName)); author.write (str); author.close (); }

הפלט בקובץ יהיה:

שלום

אנחנו יכולים אז לצרף א חוּט לקובץ הקיים:

@ מבחן ציבורי בטל כאשר AppendStringUsingBufferedWritter_thenOldContentShouldExistToo () זורק IOException {String str = "World"; כותב BufferedWriter = BufferedWriter חדש (FileWriter חדש (fileName, נכון)); author.append (''); כותב. append (str); author.close (); }

הקובץ יהיה אז:

שלום עולם

3. כתוב עם PrintWriter

לאחר מכן, בואו נראה איך אנחנו יכולים להשתמש PrintWriter כדי לכתוב טקסט מעוצב לקובץ:

@Test הציבור בטל givenWritingStringToFile_whenUsingPrintWriter_thenCorrect () זורק IOException {FileWriter fileWriter = FileWriter חדש (fileName); PrintWriter printWriter = PrintWriter חדש (fileWriter); printWriter.print ("איזה מחרוזת"); printWriter.printf ("שם המוצר הוא% s ומחירו% d $", "iPhone", 1000); printWriter.close (); }

הקובץ שהתקבל יכיל:

שם מוצר מחרוזת כלשהו הוא iPhone ומחירו 1000 $

שימו לב איך אנחנו לא רק כותבים גלם חוּט לקובץ, אך גם טקסט מעוצב עם ה- printf שיטה.

אנו יכולים ליצור את הכותב באמצעות FileWriter, BufferedWriter, או אפילו System.out.

4. כתוב עם FileOutputStream

בואו נראה עכשיו כיצד נוכל להשתמש FileOutputStream ל לכתוב נתונים בינאריים לקובץ.

הקוד הבא ממיר א חוּט לתוך בתים וכותב את הבתים לקובץ באמצעות FileOutputStream:

@Test ציבורי בטל givenWritingStringToFile_whenUsingFileOutputStream_thenCorrect () זורק IOException {String str = "שלום"; FileOutputStream outputStream = FileOutputStream חדש (fileName); בתים [] strToBytes = str.getBytes (); outputStream.write (strToBytes); outputStream.close (); }

הפלט בקובץ יהיה כמובן:

שלום

5. כתוב עם DataOutputStream

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

@Test ציבורי בטל givenWritingToFile_whenUsingDataOutputStream_thenCorrect () זורק IOException {String value = "שלום"; FileOutputStream fos = FileOutputStream חדש (fileName); DataOutputStream outStream = DataOutputStream חדש (BufferedOutputStream חדש (fos)); outStream.writeUTF (ערך); outStream.close (); // אמת את התוצאות מחרוזת תוצאה; FileInputStream fis = FileInputStream חדש (fileName); קורא DataInputStream = DataInputStream חדש (fis); תוצאה = reader.readUTF (); reader.close (); assertEquals (ערך, תוצאה); }

6. כתוב עם RandomAccessFile

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

RandomAccessFile מאפשר לנו לכתוב במיקום ספציפי בקובץ בהתחשב בקיזוז - מתחילת הקובץ - בתים.

קוד זה כותב ערך שלם עם קיזוז שניתן מראשית הקובץ:

חלל פרטי writeToPosition (שם קובץ מחרוזת, נתוני int, מיקום ארוך) זורק IOException {RandomAccessFile כותב = RandomAccessFile חדש (שם קובץ, "rw"); writer.seek (תפקיד); writer.writeInt (נתונים); author.close (); }

אם אנחנו רוצים קרא את ה int מאוחסן במקום ספציפיאנו יכולים להשתמש בשיטה זו:

פרטי int readFromPosition (שם קובץ מחרוזת, מיקום ארוך) זורק IOException {int result = 0; קורא RandomAccessFile = RandomAccessFile חדש (שם קובץ, "r"); reader.seek (עמדה); תוצאה = reader.readInt (); reader.close (); תוצאת החזרה; }

כדי לבדוק את הפונקציות שלנו, בואו לכתוב מספר שלם, לערוך אותו ולבסוף לקרוא אותו בחזרה:

@Test הציבור בטל כאשר WritingToSpecificPositionInFile_thenCorrect () זורק IOException {int data1 = 2014; int data2 = 1500; writeToPosition (fileName, data1, 4); assertEquals (data1, readFromPosition (fileName, 4)); writeToPosition (fileName2, data2, 4); assertEquals (data2, readFromPosition (fileName, 4)); }

7. כתוב עם FileChannel

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

@Test ציבורי בטל givenWritingToFile_whenUsingFileChannel_thenCorrect () זורק IOException {זרם RandomAccessFile = חדש RandomAccessFile (fileName, "rw"); ערוץ FileChannel = stream.getChannel (); ערך מחרוזת = "שלום"; בתים [] strBytes = value.getBytes (); חיץ ByteBuffer = ByteBuffer.allocate (strBytes.length); buffer.put (strBytes); buffer.flip (); channel.write (חיץ); stream.close (); channel.close (); // אמת אמת קורא RandomAccessFile = RandomAccessFile חדש (fileName, "r"); assertEquals (value, reader.readLine ()); reader.close (); }

8. כתוב עם קבצים מעמד

Java 7 מציגה דרך חדשה לעבודה עם מערכת הקבצים, יחד עם מחלקת כלי עזר חדשה: קבצים.

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

@Test ציבורי בטל givenUsingJava7_whenWritingToFile_thenCorrect () זורק IOException {String str = "שלום"; נתיב נתיב = Paths.get (fileName); בתים [] strToBytes = str.getBytes (); Files.write (נתיב, strToBytes); מחרוזת קריאה = Files.readAllLines (נתיב) .get (0); assertEquals (str, read); }

9. כתוב לקובץ זמני

עכשיו בואו ננסה לכתוב לקובץ זמני. הקוד הבא יוצר קובץ זמני וכותב a חוּט לזה:

@Test הציבור בטל כאשר WriteToTmpFile_thenCorrect () זורק IOException {String toWrite = "שלום"; קובץ tmpFile = File.createTempFile ("מבחן", ". Tmp"); כותב FileWriter = FileWriter חדש (tmpFile); author.write (toWrite); author.close (); BufferedReader reader = BufferedReader חדש (FileReader חדש (tmpFile)); assertEquals (toWrite, reader.readLine ()); reader.close (); }

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

10. נעילת קובץ לפני כתיבה

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

בואו נעשה שימוש FileChannel כדי לנסות לנעול את הקובץ לפני שאתה כותב אליו:

@ מבחן ציבורי בטל כאשר TryToLockFile_thenItShouldBeLocked () זורק IOException {זרם RandomAccessFile = חדש RandomAccessFile (fileName, "rw"); ערוץ FileChannel = stream.getChannel (); נעילת FileLock = null; נסה {lock = channel.tryLock (); } לתפוס (OverlappingFileLockException סופית e) {stream.close (); channel.close (); } stream.writeChars ("נעילת בדיקה"); lock.release (); stream.close (); channel.close (); }

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

11. הערות

לאחר שבדקנו כל כך הרבה שיטות כתיבה לקובץ, בואו נדון בכמה הערות חשובות:

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

אם נסתכל על שיטות השימוש הנפוצות, נוכל לראות, למשל PrintWriter משמש לכתיבת טקסט מעוצב, FileOutputStream לכתוב נתונים בינאריים, DataOutputStream לכתוב סוגי נתונים פרימיטיביים, RandomAccessFile לכתוב לתפקיד מסוים, ו FileChannel לכתוב מהר יותר בקבצים גדולים יותר. חלק מממשקי ה- API של שיעורים אלה מאפשרים יותר, אך זהו מקום טוב להתחיל בו.

12. מסקנה

מאמר זה המחיש את האפשרויות הרבות של כתיבת נתונים לקובץ באמצעות Java.

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