JavaRush /จาวาบล็อก /Random-TH /ไฟล์ Java, พาธ

ไฟล์ Java, พาธ

เผยแพร่ในกลุ่ม
สวัสดี! วันนี้เราจะพูดถึงการทำงานกับไฟล์และไดเร็กทอรี คุณรู้วิธีจัดการเนื้อหาของไฟล์อยู่แล้ว: เรามีคลาสมากมายสำหรับสิ่งนี้ :) ฉันคิดว่าคุณสามารถจำคลาสต่างๆ ที่จำเป็นสำหรับวัตถุประสงค์เหล่านี้ได้อย่างง่ายดาย ในการบรรยายวันนี้ เราจะพูดเฉพาะเกี่ยวกับการจัดการไฟล์ - การสร้าง การเปลี่ยนชื่อ ฯลฯ ก่อน Java 7 การดำเนินการดังกล่าวทั้งหมดดำเนินการโดยใช้ส่วนขยายFile. คุณสามารถอ่านเกี่ยวกับงานของเขาได้ที่นี่ แต่ใน Java 7 ผู้สร้างภาษาได้ตัดสินใจเปลี่ยนวิธีการทำงานกับไฟล์และไดเร็กทอรี นี่เป็นเพราะความจริงที่ว่าชั้นเรียนFileมีข้อเสียหลายประการ ตัวอย่างเช่น ไม่มีวิธีการcopy()ที่จะช่วยให้คุณสามารถคัดลอกไฟล์จากที่หนึ่งไปยังอีกที่หนึ่งได้ (คุณลักษณะที่ดูเหมือนจำเป็นอย่างชัดเจน) นอกจากนี้ คลาสFileยังมีเมธอดจำนวนมากที่คืนbooleanค่า -value หากเกิดข้อผิดพลาด วิธีการดังกล่าวจะส่งกลับค่าเท็จแทนที่จะส่งข้อยกเว้น ซึ่งทำให้การวินิจฉัยข้อผิดพลาดและการระบุสาเหตุทำได้ยากมาก แทนที่จะเป็นคลาสเดียวFileมีมากถึง 3 คลาสปรากฏขึ้น: Paths, PathและFiles. ถ้าให้พูดให้ชัดเจนPathนี่คืออินเทอร์เฟซ ไม่ใช่คลาส เรามาดูกันว่าพวกเขาแตกต่างกันอย่างไรและเหตุใดจึงจำเป็นต้องมีแต่ละอัน เริ่มจากสิ่งที่ง่ายที่สุดกันดีกว่า - Paths.

เส้นทาง

Pathsเป็นคลาสที่เรียบง่ายมากโดยใช้วิธีคงที่เพียงวิธีget()เดียว มันถูกสร้างขึ้นเพื่อรับวัตถุประเภทจากสตริงที่ส่งผ่านหรือ URI Pathเท่านั้น มันไม่มีฟังก์ชั่นอื่น ๆ นี่คือตัวอย่างผลงานของเขา:
import java.nio.file.Path;
import java.nio.file.Paths;

public class Main {

   public static void main(String[] args) {

       Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt");
   }
}
ไม่ใช่วิชาที่ยากที่สุดใช่ไหม? :) เนื่องจากเรามี object ประเภทPathเรามาดูกันว่ามันคืออะไรPathและทำไมจึงจำเป็น :)

เส้นทาง

Pathโดยทั่วไปแล้ว เป็นอะนาล็อกที่ออกแบบใหม่ของFile. มันง่ายกว่ามากในการทำงานมากกว่าFileด้วย ประการ แรกวิธีการอรรถประโยชน์ (คงที่) จำนวนมากถูกลบออกจากมันและย้ายไปที่ชั้นเรียน ประการที่สองมีการเรียงลำดับค่าส่งคืนของวิธีการ ในชั้นเรียนวิธีการต่างๆ ส่งคืนสิ่งนี้, นั่น, นั่น- มันไม่ง่ายเลยที่จะเข้าใจ ตัวอย่างเช่น มีวิธีการที่ส่งคืนพาธพาเรนต์สำหรับไฟล์ปัจจุบันเป็นสตริง แต่ในขณะเดียวกันก็มีวิธีที่คืนสิ่งเดียวกัน แต่อยู่ในรูปของวัตถุ! นี่เป็นสิ่งที่ซ้ำซ้อนอย่างชัดเจน ดังนั้นในอินเทอร์เฟซวิธีการและวิธีการอื่นในการทำงานกับไฟล์เพียงแค่ส่งคืนวัตถุ ไม่มีตัวเลือกมากมาย - ทุกอย่างง่ายและเรียบง่าย มันมีวิธีการที่มีประโยชน์อะไรบ้าง? นี่คือบางส่วนและตัวอย่างงานของพวกเขา: FilesPathFileStringbooleanFilegetParent()getParentFile()FilePathgetParent()PathPath
  • getFileName()— ส่งคืนชื่อไฟล์จากเส้นทาง;

  • getParent()— ส่งคืนไดเร็กทอรี "พาเรนต์" ที่สัมพันธ์กับพาธปัจจุบัน (นั่นคือ ไดเร็กทอรีที่อยู่สูงกว่าในแผนผังไดเร็กทอรี)

  • getRoot()— ส่งคืนไดเร็กทอรี "root"; นั่นคืออันที่อยู่ด้านบนสุดของแผนผังไดเร็กทอรี

  • startsWith(), endsWith()— ตรวจสอบว่าเส้นทางเริ่มต้น/สิ้นสุดด้วยเส้นทางที่ผ่านหรือไม่:

    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class Main {
    
       public static void main(String[] args) {
    
           Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt");
    
           Path fileName = testFilePath.getFileName();
           System.out.println(fileName);
    
           Path parent = testFilePath.getParent();
           System.out.println(parent);
    
           Path root = testFilePath.getRoot();
           System.out.println(root);
    
           boolean endWithTxt = testFilePath.endsWith("Desktop\\testFile.txt");
           System.out.println(endWithTxt);
    
           boolean startsWithLalala = testFilePath.startsWith("lalalala");
           System.out.println(startsWithLalala);
       }
    }

    เอาต์พุตคอนโซล:

    testFile.txt
    C:\Users\ชื่อผู้ใช้\Desktop
    C:\
    true
    เท็จ

    ให้ความสนใจกับวิธีการendsWith()ทำงาน จะตรวจสอบว่าเส้นทางปัจจุบันสิ้นสุดด้วยเส้นทาง ที่ผ่านไป หรือไม่ มันอยู่บนเส้นทางและไม่ใช่ชุดของตัวละคร

    เปรียบเทียบผลลัพธ์ของการโทรทั้งสองนี้:

    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class Main {
    
       public static void main(String[] args) {
    
           Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt");
    
           System.out.println(testFilePath.endsWith("estFile.txt"));
           System.out.println(testFilePath.endsWith("Desktop\\testFile.txt"));
       }
    }

    เอาต์พุตคอนโซล:

    ผิด
    ถูก

    คุณต้องส่งเส้นทางแบบเต็ม ไปยังเมธอดendsWith()ไม่ใช่เพียงชุดอักขระ: ไม่เช่นนั้นผลลัพธ์จะเป็นเท็จ เสมอ แม้ว่าเส้นทางปัจจุบันจะลงท้ายด้วยลำดับอักขระดังกล่าวก็ตาม (เช่นในกรณีของ “estFile.txt ” ในตัวอย่างข้างต้น)

    นอกจากนี้ยังมีPathกลุ่มวิธีการที่ทำให้การทำงานกับเส้นทางสัมบูรณ์ (เต็ม) และเส้นทางสัมพัทธ์ง่ายขึ้น

ลองดูวิธีการเหล่านี้:
  • boolean isAbsolute()— คืนค่าเป็นจริงหากเส้นทางปัจจุบันเป็นแบบสัมบูรณ์:

    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class Main {
    
       public static void main(String[] args) {
    
           Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt");
    
           System.out.println(testFilePath.isAbsolute());
       }
    }

    เอาต์พุตคอนโซล:

    จริง

  • Path normalize()— “ทำให้ปกติ” เส้นทางปัจจุบัน โดยลบองค์ประกอบที่ไม่จำเป็นออกไป คุณอาจรู้ว่าระบบปฏิบัติการยอดนิยมมักใช้อักขระ “.” เมื่อแสดงถึงเส้นทาง (“ไดเรกทอรีปัจจุบัน”) และ “..” (ไดเรกทอรีหลัก) ตัวอย่างเช่น: “ ./Pictures/dog.jpg ” หมายความว่าในไดเร็กทอรีที่เราอยู่ในตอนนี้มีโฟลเดอร์ Pictures และในนั้นมีไฟล์ “dog.jpg”

    ดังนั้นนี่คือ หากโปรแกรมของคุณมีเส้นทางที่ใช้ “” หรือ “..” วิธีการnormalize()จะลบออกและรับเส้นทางที่ไม่มี:

    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class Main {
    
       public static void main(String[] args) {
    
    
           Path path5 = Paths.get("C:\\Users\\Java\\.\\examples");
    
           System.out.println(path5.normalize());
    
           Path path6 = Paths.get("C:\\Users\\Java\\..\\examples");
           System.out.println(path6.normalize());
       }
    }

    เอาต์พุตคอนโซล:

    C:\Users\Java\examples
    C:\Users\examples

  • Path relativize()— คำนวณเส้นทางสัมพัทธ์ระหว่างเส้นทางปัจจุบันและเส้นทางที่ผ่านไป

    ตัวอย่างเช่น:

    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class Main {
    
       public static void main(String[] args) {
    
           Path testFilePath1 = Paths.get("C:\\Users\\Users\\Users\\Users");
           Path testFilePath2 = Paths.get("C:\\Users\\Users\\Users\\Users\\Username\\Desktop\\testFile.txt");
    
           System.out.println(testFilePath1.relativize(testFilePath2));
       }
    }

    เอาต์พุตคอนโซล:

    ชื่อผู้ใช้\เดสก์ท็อป\testFile.txt

รายการวิธีการทั้งหมดPathมีขนาดค่อนข้างใหญ่ คุณสามารถค้นหาทั้งหมดได้ในเอกสารของ Oracle เราจะดำเนินการตรวจสอบต่อFilesไป

ไฟล์

FilesFile- นี่คือคลาสยูทิลิตี้ซึ่งมีการย้ายวิธีการแบบคงที่จากคลาส Files- สิ่งนี้ประมาณเหมือนกับArraysหรือCollectionsใช้งานได้กับไฟล์เท่านั้นไม่ใช่กับอาร์เรย์และคอลเลกชัน :) มุ่งเน้นไปที่การจัดการไฟล์และไดเร็กทอรี โดยใช้วิธีการคงที่Filesเราสามารถสร้าง ลบ และย้ายไฟล์และไดเร็กทอรีได้ สำหรับการดำเนินการเหล่า นี้จะใช้วิธีการcreateFile()(สำหรับไดเร็กทอรี - createDirectory()) move()และ delete()ต่อไปนี้เป็นวิธีการใช้งาน:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

public class Main {

   public static void main(String[] args) throws IOException {

       //file creation
       Path testFile1 = Files.createFile(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt"));
       System.out.println("Was the file created successfully?");
       System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));

       // create directory
       Path testDirectory = Files.createDirectory(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory"));
       System.out.println("Was the directory successfully created?");
       System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory")));

       //move file from desktop to testDirectory. You need to move with the name of the file in the folder!
       testFile1 = Files.move(testFile1, Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt"), REPLACE_EXISTING);

       System.out.println("Is our file left on the desktop?");
       System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));

       System.out.println("Has our file been moved to testDirectory?");
       System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt")));

       //remove file
       Files.delete(testFile1);
       System.out.println("Does the file still exist?");
       System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt")));
   }
}
ที่นี่เราสร้างไฟล์ (method Files.createFile()) บนเดสก์ท็อปก่อน จากนั้นจึงสร้างโฟลเดอร์ที่นั่น (method Files.createDirectory()) หลังจากนั้นเราจะย้ายไฟล์ (method Files.move()) จากเดสก์ท็อปไปยังโฟลเดอร์ใหม่นี้ และในตอนท้ายเราจะลบไฟล์ (method Files.delete()) เอาต์พุตคอนโซล: สร้างไฟล์สำเร็จหรือไม่ true สร้างไดเร็กทอรีสำเร็จหรือไม่? จริง ไฟล์ของเรายังอยู่บนเดสก์ท็อปหรือไม่? false ไฟล์ของเราถูกย้ายไปยัง testDirectory หรือไม่? จริง ไฟล์ยังคงอยู่หรือไม่? เท็จ ใส่ใจ:เช่นเดียวกับวิธีการอินเทอร์เฟซหลายPathวิธีส่งFilesคืนอ็อบเจ็กต์ Pathวิธีการเรียนส่วนใหญ่FilesยังยอมรับPath. วิธีการจะกลายเป็นผู้ช่วยที่ซื่อสัตย์ของคุณPaths.get()- ใช้มันอย่างแข็งขัน มีอะไรน่าสนใจอีกบ้างFiles? สิ่งที่คลาสเก่าขาดจริงๆ คือ ! Fileวิธีการ copy()เราคุยกันถึงเขาตั้งแต่เริ่มบรรยายแล้ว ถึงเวลาพบเขาแล้ว!
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

public class Main {

   public static void main(String[] args) throws IOException {

       //file creation
       Path testFile1 = Files.createFile(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt"));
       System.out.println("Was the file created successfully?");
       System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));

       // create directory
       Path testDirectory2 = Files.createDirectory(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2"));
       System.out.println("Was the directory successfully created?");
       System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2")));

       //copy the file from the desktop to the directory testDirectory2.
       testFile1 = Files.copy(testFile1, Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2\\testFile111.txt"), REPLACE_EXISTING);

       System.out.println("Is our file left on the desktop?");
       System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));

       System.out.println("Has our file been copied to testDirectory?");
       System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2\\testFile111.txt")));
   }
}
เอาต์พุตคอนโซล: สร้างไฟล์สำเร็จหรือไม่ true สร้างไดเร็กทอรีสำเร็จหรือไม่? จริง ไฟล์ของเรายังอยู่บนเดสก์ท็อปหรือไม่? จริง ไฟล์ของเราถูกคัดลอกไปยัง testDirectory หรือไม่ จริง ตอนนี้คุณสามารถคัดลอกไฟล์โดยทางโปรแกรมได้แล้ว! :) แต่ชั้นเรียนFilesช่วยให้คุณไม่เพียง แต่จัดการไฟล์ด้วยตนเอง แต่ยังทำงานกับเนื้อหาด้วย ในการเขียนข้อมูลลงไฟล์ก็มีวิธีการwrite()และสำหรับการอ่าน - มากถึง 3: read()และreadAllBytes()เราreadAllLines() จะดูรายละเอียดหลังกัน ทำไมมัน? เพราะมีประเภทคืนที่น่าสนใจมาก - List<String>! นั่นคือมันจะส่งคืนรายการบรรทัดในไฟล์ให้เราทราบ แน่นอนว่าสิ่งนี้ทำให้การทำงานกับเนื้อหาสะดวกมาก เนื่องจากไฟล์ทั้งหมดทีละบรรทัดสามารถส่งออกไปยังคอนโซลในลูปปกติได้for:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

import static java.nio.charset.StandardCharsets.UTF_8;

public class Main {

   public static void main(String[] args) throws IOException {

       List<String> lines = Files.readAllLines(Paths.get("C:\\Users\\Username\\Desktop\\pushkin.txt"), UTF_8);

       for (String s: lines) {
           System.out.println(s);
       }
   }
}
ผลลัพธ์ของคอนโซล: ฉันจำช่วงเวลาที่ยอดเยี่ยมได้: คุณปรากฏตัวต่อหน้าฉัน ราวกับนิมิตที่หายวับไป ราวกับอัจฉริยะแห่งความงามอันบริสุทธิ์ สบายมาก! :) คุณลักษณะนี้ปรากฏใน Java 7 ใน Java 8 Stream API ปรากฏขึ้น ซึ่งเพิ่มองค์ประกอบบางส่วนของการเขียนโปรแกรมเชิงฟังก์ชันให้กับ Java รวมถึงความสามารถในการจัดการไฟล์ที่สมบูรณ์ยิ่งขึ้น ลองนึกภาพว่าเรามีงาน: ค้นหาบรรทัดทั้งหมดในไฟล์ที่ขึ้นต้นด้วยคำว่า "อย่างไร" แปลงเป็น UPPER CASE และส่งออกไปยังคอนโซล โซลูชันที่ใช้คลาสFilesใน Java 7 จะมีลักษณะ อย่างไร บางสิ่งเช่นนี้:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import static java.nio.charset.StandardCharsets.UTF_8;

public class Main {

   public static void main(String[] args) throws IOException {

       List<String> lines = Files.readAllLines(Paths.get("C:\\Users\\Username\\Desktop\\pushkin.txt"), UTF_8);

       List<String> result = new ArrayList<>();

       for (String s: lines) {
           if (s.startsWith("How")) {
               String upper = s.toUpperCase();
               result.add(upper);
           }
       }

       for (String s: result) {
           System.out.println(s);
       }
   }
}
เอาต์พุตคอนโซล: เหมือนวิสัยทัศน์ที่รวดเร็ว เหมือนอัจฉริยะแห่งความงามอันบริสุทธิ์ ดูเหมือนเราจะทำมันสำเร็จแล้ว แต่คุณไม่คิดเหรอว่าสำหรับงานง่ายๆ เช่นนี้ โค้ดของเราจะกลายเป็น... รายละเอียดเล็กๆ น้อยๆ ใช่ไหม? การใช้ Java 8 Stream API โซลูชันดูหรูหรากว่ามาก:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {

   public static void main(String[] args) throws IOException {

       Stream<String> stream = Files.lines(Paths.get("C:\\Users\\Username\\Desktop\\pushkin.txt"));

       List<String> result  = stream
               .filter(line -> line.startsWith("How"))
               .map(String::toUpperCase)
               .collect(Collectors.toList());
       result.forEach(System.out::println);
   }
}
เราได้รับผลลัพธ์เดียวกัน แต่มีโค้ดน้อยกว่ามาก! ยิ่งไปกว่านั้น ไม่สามารถพูดได้ว่าเราสูญเสีย "ความสามารถในการอ่าน" ไป ฉันคิดว่าคุณสามารถแสดงความคิดเห็นได้อย่างง่ายดายว่าโค้ดนี้ทำอะไรได้บ้าง แม้ว่าคุณจะไม่คุ้นเคยกับ Stream API ก็ตาม แต่โดยสรุปสตรีมคือลำดับขององค์ประกอบที่คุณสามารถทำหน้าที่ต่างๆ ได้ เราได้รับออบเจ็กต์ Stream จากเมธอดFiles.lines()จากนั้นจึงใช้ 3 ฟังก์ชันกับมัน:
  1. โดยใช้วิธีการนี้filter()เราเลือกเฉพาะบรรทัดจากไฟล์ที่ขึ้นต้นด้วย "How"

  2. เราผ่านบรรทัดที่เลือกทั้งหมดโดยใช้วิธีการmap()และนำแต่ละบรรทัดไปที่ UPPER CASE

  3. เรารวมบรรทัดผลลัพธ์ทั้งหมดเข้ากับListการใช้collect().

ที่ทางออกเราได้รับผลลัพธ์เดียวกัน: เหมือนการมองเห็นที่รวดเร็ว เหมือนอัจฉริยะแห่งความงามอันบริสุทธิ์ หากคุณสนใจที่จะเรียนรู้เพิ่มเติมเกี่ยวกับความสามารถของไลบรารีนี้ เราขอแนะนำให้อ่านบทความนี้ เราจะกลับไปที่แกะของเรานั่นคือไฟล์ :) ความเป็นไปได้สุดท้ายที่เราจะพิจารณาในวันนี้คือการเดินผ่านแผนผังไฟล์ . โครงสร้างไฟล์ในระบบปฏิบัติการสมัยใหม่ส่วนใหญ่มักจะอยู่ในรูปแบบของแผนผัง: มีรูทและมีกิ่งก้านที่สามารถแยกกิ่งอื่นได้ ฯลฯ ไดเร็กทอรีมีบทบาทเป็นรูทและสาขา ตัวอย่างเช่น ไดเรกทอรี “ C:// ” สามารถทำหน้าที่เป็นรูทได้ สองสาขาแยกออกจากกัน: “ C://Downloads ” และ “ C://Users ” จากแต่ละสาขาเหล่านี้จะมีอีก 2 สาขา: “ C://Downloads/Pictures ”, “ C://Downloads/Video ”, “ C://Users/JohnSmith ”, “ C://Users/Pudge2005 ” . สาขาอื่นๆ แยกออกจากสาขาเหล่านี้ เป็นต้น - นี่คือลักษณะของต้นไม้ ใน Linux มีลักษณะเหมือนกัน มีเพียงไดเร็กทอรีเท่านั้นที่ทำหน้าที่เป็นรูท/ ไฟล์, พาธ - 2ทีนี้ลองจินตนาการว่าเรามีงาน: เมื่อรู้ไดเร็กทอรีรูทแล้วเราต้องผ่านมันไป ดูในโฟลเดอร์ของทุกระดับและค้นหาไฟล์ในนั้นพร้อมเนื้อหา พวกเราต้องการ. เราจะค้นหาไฟล์ที่มีบรรทัด “นี่คือไฟล์ที่เราต้องการ!” ไดเร็กทอรีรากของเราจะเป็นโฟลเดอร์ "testFolder" ซึ่งอยู่บนเดสก์ท็อป ข้างในมีเนื้อหาดังต่อไปนี้: ไฟล์, พาธ - 3ภายในโฟลเดอร์ระดับ 1-a และระดับ 1-b ยังมีโฟลเดอร์: ไฟล์, พาธ - 4ไฟล์, พาธ - 5ภายใน "โฟลเดอร์ระดับที่สอง" เหล่านี้ไม่มีโฟลเดอร์อีกต่อไป มีเพียงไฟล์แต่ละไฟล์เท่านั้น: ไฟล์, พาธ - 6ไฟล์, พาธ - 7เราจะกำหนดไฟล์ 3 ไฟล์เป็นพิเศษด้วยเนื้อหาที่เรา ต้องการชื่อที่ชัดเจน - FileWeNeed1.txt , FileWeNeed2.txt, FileWeNeed3.txt นี่คือสิ่งที่เราจำเป็นต้องค้นหาด้วยเนื้อหาโดยใช้ Java เราจะทำเช่นนี้ได้อย่างไร? วิธีการที่มีประสิทธิภาพมากในการสำรวจแผนผังไฟล์สามารถช่วยได้ - Files.walkFileTree(). นี่คือสิ่งที่เราต้องทำ ก่อนอื่นเราFileVisitorต้อง FileVisitorเป็นอินเทอร์เฟซพิเศษที่อธิบายวิธีการทั้งหมดในการสำรวจแผนผังไฟล์ โดยเฉพาะเราจะใส่ตรรกะเพื่ออ่านเนื้อหาของไฟล์และตรวจสอบว่ามีข้อความที่เราต้องการหรือไม่ หน้าตาของเราจะเป็นดังนี้FileVisitor:
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;

public class MyFileVisitor extends SimpleFileVisitor<Path> {

   @Override
   public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {

       List<String> lines = Files.readAllLines(file);
       for (String s: lines) {
           if (s.contains("This is the file we need")) {
               System.out.println("Required file found!");
               System.out.println(file.toAbsolutePath());
               break;
           }
       }

       return FileVisitResult.CONTINUE;
   }
}
ในกรณีนี้ คลาสของเราสืบทอดมาจากSimpleFileVisitor. นี่คือคลาสที่นำไปใช้FileVisitorซึ่งคุณต้องแทนที่เพียงวิธีเดียวเท่านั้นvisitFile(): ที่นี่เราจะอธิบายสิ่งที่ต้องทำกับแต่ละไฟล์ในแต่ละไดเร็กทอรี หากคุณต้องการตรรกะการแวะผ่านที่ซับซ้อนมากขึ้น คุณควรเขียนการใช้งานของคุณFileVisitorเอง ที่นั่นคุณจะต้องใช้อีก 3 วิธี:
  • preVisitDirectory()— ตรรกะที่ต้องดำเนินการก่อนเข้าสู่โฟลเดอร์

  • visitFileFailed()— จะทำอย่างไรถ้าไม่สามารถเข้าไฟล์ได้ (ไม่สามารถเข้าถึงหรือเหตุผลอื่น ๆ )

  • postVisitDirectory()— ตรรกะที่ต้องดำเนินการหลังจากเข้าสู่โฟลเดอร์

เราไม่มีเหตุผลเช่นนั้น ดังนั้นก็เพียงพอแล้วสำหรับSimpleFileVisitorเรา ตรรกะภายในวิธีการนี้visitFile()ค่อนข้างง่าย: อ่านบรรทัดทั้งหมดจากไฟล์ ตรวจสอบว่ามีเนื้อหาที่เราต้องการหรือไม่ และหากเป็นเช่นนั้น ให้พิมพ์เส้นทางที่แน่นอนไปยังคอนโซล บรรทัดเดียวที่อาจทำให้คุณมีปัญหาคือบรรทัดนี้:
return FileVisitResult.CONTINUE;
ในความเป็นจริงทุกอย่างเป็นเรื่องง่าย ที่นี่เราเพียงแต่อธิบายว่าโปรแกรมควรทำอะไรหลังจากป้อนไฟล์และการดำเนินการที่จำเป็นทั้งหมดเสร็จสิ้นแล้ว ในกรณีของเรา เราจำเป็นต้องสำรวจต้นไม้ต่อไป ดังนั้นเราจึงเลือกตัวCONTINUEเลือก แต่ตัวอย่างเช่นเราอาจมีหน้าที่อื่น: ค้นหาไฟล์ทั้งหมดที่มี "นี่คือไฟล์ที่เราต้องการ" แต่มีไฟล์ดังกล่าวเพียงไฟล์เดียวเท่านั้น หลังจากนี้จะต้องยุติโปรแกรม ในกรณีนี้ โค้ดของเราจะมีลักษณะเหมือนกันทุกประการ แต่แทนที่จะพัง จะ:
return FileVisitResult.TERMINATE;
เรามารันโค้ดของเราแล้วดูว่ามันใช้งานได้หรือไม่
import java.io.IOException;
import java.nio.file.*;

public class Main {

   public static void main(String[] args) throws IOException {

       Files.walkFileTree(Paths.get("C:\\Users\\Username\\Desktop\\testFolder"), new MyFileVisitor());
   }
}
เอาต์พุตคอนโซล: พบไฟล์ที่ต้องการแล้ว! C:\Users\Username\Desktop\testFolder\FileWeNeed1.txt พบไฟล์ที่ต้องการแล้ว! C:\Users\Username\Desktop\testFolder\level1-a\level2-aa\FileWeNeed2.txt พบไฟล์ที่ต้องการแล้ว! C:\Users\Username\Desktop\testFolder\level1-b\level2-bb\FileWeNeed3.txt เยี่ยมมาก เราทำได้! :) หากคุณต้องการทราบข้อมูลเพิ่มเติมฉันwalkFileTree()ขอแนะนำบทความนี้ คุณยังสามารถทำงานเล็ก ๆ ให้สำเร็จได้ - แทนที่SimpleFileVisitorด้วยงานปกติFileVisitorใช้ทั้ง 4 วิธีและสร้างวัตถุประสงค์สำหรับโปรแกรมนี้ ตัวอย่างเช่น คุณสามารถเขียนโปรแกรมที่จะบันทึกการกระทำทั้งหมดของคุณ: แสดงชื่อไฟล์หรือโฟลเดอร์ในคอนโซลก่อน/หลังป้อน นั่นคือทั้งหมด - แล้วพบกันใหม่! :)
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION