מחק ספריה רקורסיבית בג'אווה
1. הקדמה
במאמר זה נמחיש כיצד למחוק ספרייה באופן רקורסיבי ב- Java רגיל. אנו נבחן גם כמה חלופות למחיקת ספריות באמצעות ספריות חיצוניות.
2. מחיקת מדריך רקורסיבי
ל- Java אפשרות למחוק ספריה. עם זאת, הדבר מחייב שהספריה תהיה ריקה. לכן, עלינו להשתמש ברקורסיה כדי למחוק ספרייה מסוימת שאינה ריקה:
- קבל את כל תוכן הספרייה למחיקה
- מחק את כל הילדים שאינם ספריה (יציאה מ- recursion)
- עבור כל ספריה משנה של הספריה הנוכחית, התחל משלב 1 (שלב רקורסיבי)
- מחק את הספרייה
בואו נשתמש באלגוריתם הפשוט הזה:
deleteDirectory בוליאני (directoryToBeDeleted File) {File [] allContents = directoryToBeDeleted.listFiles (); אם (allContents! = null) {עבור (קובץ קובץ: allContents) {deleteDirectory (קובץ); }} להחזיר directoryToBeDeleted.delete (); }
ניתן לבדוק שיטה זו באמצעות מקרה מבחן פשוט:
@Test הציבור בטל givenDirectory_whenDeletedWithRecursion_thenIsGone () זורק IOException {נתיב pathToBeDeleted = TEMP_DIRECTORY.resolve (DIRECTORY_NAME); תוצאה בוליאנית = deleteDirectory (pathToBeDeleted.toFile ()); assertTrue (תוצאה); assertFalse ("הספריה עדיין קיימת", Files.exists (pathToBeDeleted)); }
ה @לפני שיטת מחלקת הבדיקה שלנו יוצרת עץ ספריות עם ספריות משנה וקבצים ב pathToBeDeleted מיקום ו @לאחר השיטה מנקה את הספרייה במידת הצורך.
לאחר מכן, בואו נסתכל כיצד נוכל להשיג מחיקה באמצעות שתיים מהספריות הנפוצות ביותר - אפאצ'י commons-io ומסגרות האביב ליבת קפיץ. שתי הספריות הללו מאפשרות לנו למחוק את הספריות באמצעות שורת קוד אחת בלבד.
3. שימוש FileUtils מ commons-io
ראשית, עלינו להוסיף את commons-io תלות בפרויקט Maven:
commons-io commons-io 2.5
הגרסה האחרונה של התלות נמצאת כאן.
עכשיו, אנחנו יכולים להשתמש FileUtils לביצוע פעולות מבוססות קבצים כולל deleteDirectory () עם הצהרה אחת בלבד:
FileUtils.deleteDirectory (קובץ);
4. שימוש FileSystemUtils מאביב
לחלופין, אנו יכולים להוסיף את ה- sפרינג-ליבה תלות בפרויקט Maven:
org.springframework spring-core 4.3.10.RELEASE
הגרסה האחרונה של התלות נמצאת כאן.
אנחנו יכולים להשתמש ב- deleteRecursively () שיטה ב FileSystemUtils לביצוע המחיקה:
תוצאה בוליאנית = FileSystemUtils.deleteRecursively (קובץ);
המהדורות האחרונות של Java מציעות דרכים חדשות יותר לבצע פעולות IO כאלה המתוארות בסעיפים הבאים.
5. שימוש ב- NIO2 עם Java 7
Java 7 הציגה דרך חדשה לגמרי לביצוע פעולות קבצים באמצעות קבצים. זה מאפשר לנו לחצות עץ מדריך ולהשתמש בקריאות חוזרות לצורך פעולות שיבוצעו.
חלל ציבורי כאשרDeletedWithNIO2WalkFileTree_thenIsGone () זורק IOException {Path pathToBeDeleted = TEMP_DIRECTORY.resolve (DIRECTORY_NAME); Files.walkFileTree (pathToBeDeleted, חדש SimpleFileVisitor () {@Override פומבי FileVisitResult postVisitDirectory (נתיב dir, IOException exc) זורק IOException {Files.delete (dir); להחזיר FileVisitResult.CONTINUE;} @Override תוצאות קובץ FileFit ) זורק את IOException {Files.delete (file); להחזיר FileVisitResult.CONTINUE;}}); assertFalse ("הספריה עדיין קיימת", Files.exists (pathToBeDeleted)); }
ה Files.walkFileTree () השיטה חוצה עץ קבצים ופולטת אירועים. עלינו לציין התקשרות חוזרות לאירועים אלה. אז, במקרה זה, נגדיר SimpleFileVisitor לנקוט בפעולות הבאות לאירועים שנוצרו:
- ביקור בקובץ - מחק אותו
- ביקור בספריה לפני עיבוד הערכים שלה - אל תעשה כלום
- ביקור בספריה לאחר עיבוד הערכים שלה - מחק את הספרייה, מכיוון שכל הערכים בספריה זו היו מעובדים (או נמחקים) עד עכשיו
- לא ניתן לבקר בקובץ - לסדר מחדש IOException שגרם לכישלון
עיין במבוא ל- API של Java NIO2 File לקבלת פרטים נוספים על NIO2 APIs על טיפול בפעולות קבצים.
6. שימוש NIO2 עם Java 8
מאז Java 8, Stream API מציע דרך טובה עוד יותר למחיקת ספריה:
@Test הציבור בטל כאשרDeletedWithFilesWalk_thenIsGone () זורק IOException {Path pathToBeDeleted = TEMP_DIRECTORY.resolve (DIRECTORY_NAME); Files.walk (pathToBeDeleted) .sorted (Comparator.reverseOrder ()) .map (Path :: toFile) .forEach (File :: delete); assertFalse ("הספריה עדיין קיימת", Files.exists (pathToBeDeleted)); }
פה, Files.walk () מחזירה א זרם שֶׁל נָתִיב שאנחנו ממיינים בסדר הפוך. זה מציב את הנתיבים המציינים את תוכן הספריות לפני ספריות עצמן. לאחר מכן הוא ממפה נָתִיב ל קוֹבֶץ ומוחק כל אחד קוֹבֶץ.
7. מסקנה
במדריך מהיר זה בדקנו דרכים שונות למחיקת ספריה. בעוד שראינו כיצד להשתמש ברקורסיה למחיקה, בדקנו גם כמה ספריות, NIO2 ממנף אירועים ו- Java 8 Path Stream תוך שימוש בפרדיגמת תכנות פונקציונלית.
כל קוד המקור ומקרי הבדיקה עבור מאמר זה זמינים באתר GitHub.