May 19, 2012

FileVisitor

ပြီးခဲ့သောအခန်းများတွင် ဖိုင်နှင့် ဒိုင်အတ္တရီများအား ကော်ပီကူပုံအကြောင်းကို ရေးသားခဲ့ဘူးပါသည်။ သို့ရာတွင် ဒိုင်အတ္တရီများအား ကော်ပီကူးရာ၌ အတွင်းတွင် ဖိုင်နှင့် ဒိုင်အတ္တရီများ ပါရှိပါက တိုက်ရိုက် ကော်ပီကူး၍မရပဲ၊ ဒိုင်အတ္တရီများအတွင်း တဆင့်ချင်းဝင်ကာ ဖိုင်တစ်ခုချင်း ကော်ပီကူးရန် လိုအပ်ခဲ့၏။

ယနေ့အထိအသုံးပြုခဲ့သော File IO အဟောင်းကို အသုံးပြုစဉ်အခါက ဒိုင်အတ္တရီ အတွင်း တစ်ခုချင်းဝင်ကာ ဖိုင်များအားရှာဖွေရသည်မှာ အတော်လေးကို လက်ပေါက်ကတ်ခဲ့ပါသည်။ သို့ရာတွင် ယနေ့ NIIO 2 အရောက်တွင် Java Design Pattern တစ်ခုဖြစ်သော Visitor Pattern ကို အသုံးပြုထားသည့် အင်တာဖေစ် တစ်ခုကို ပြင်ဆင်လာခဲ့ပါသည်။ FileVisitor အင်တာဖေစ် ဖြစ်ပါသည်။


FileVisitor အင်တာဖေစ်


FileVisitor အင်တာဖေစ်တွင် ဖိုင်စစ္စတမ်အတွင်းရှိ ဖိုင်များ ဒိုင်အတ္တရီများအား ဝင်ရောက်ရှာဖွေရ လွယ်ကူစေရန် လုပ်ဆောင်ချက် ၄ မျိုးကို ပြင်ဆင်ထားပါသည်။

  1. preVisitDirectory ဒိုင်အတ္တရီ အတွင်းသို့ မဝင်ရောက်ခင် ခေါ်ဆိုမည့် လုပ်ဆောင်ချက်ဖြစ်၏။
  2. postVisitDirecotry ဒိုင်အတ္တရီ အတွင်းမှ မထွက်ခွာခင် ခေါ်ဆိုမည့် လုပ်ဆောင်ချက်ဖြစ်၏။
  3. visitFile ဖိုင်နေရာသို့ ရောက်ရှိသည့် အခါတွင် ခေါ်ဆိုမည့် လုပ်ဆောင်ချက် ဖြစ်၏။
  4. visitFileFailed ဖိုင်နေရာသို့ ဝင်ရောက်ရာတွင် မှားယွင်းမှု့များ ဖြစ်ပေါ်ခဲ့ပါက ခေါ်ဆိုမည့် လုပ်ဆောင်ချက် ဖြစ်၏။
အရင်ဦးဆုံး FileVisitor Pattern ကို စမ်းသပ်ကြည့်လိုပါသဖြင့် အောက်ပါအတိုင်း linux အပေါ်တွင် ဒိုင်အတ္တရီ (Directory) နှင့် ဖိုင်များကို တည်ဆောက်ပါမည်။


import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;

public class FileVisitorTest {

    public static void main(String[] args) {

        FileVisitor<Path> visitor = new FileVisitor<Path>() {

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc)
                    throws IOException {
                System.out.println("postVisitDirectory : " + dir);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult preVisitDirectory(Path dir,
                    BasicFileAttributes attrs) throws IOException {
                System.out.println("preVisitDirectory : " + dir);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path file,
                    BasicFileAttributes attrs) throws IOException {
                System.out.println("visitFile : " + file);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc)
                    throws IOException {
                System.out.println("visitFileFailed : " + file);
                return FileVisitResult.CONTINUE;
            }
        };

        try {
            Files.walkFileTree(FileSystems.getDefault().getPath("alpha"),
                    visitor);
        } catch (IOException e) {
            System.err.println("There is no File.");
        }
    }
}
အထက်ပါ အတိုင်း FileVistor အင်တာဖေစ်၏ Object အား instance လုပ်ပါမည်။ ဖြည့်စွက်ရန် လိုအပ်သော လုပ်ဆောင်ချက်များအား override လုပ်ရေးပါမည်။ ဤနေရာတွင် FileVisitor အားမည်သို့ အသုံးချမည်ကို သိလိုပါသဖြင့် အတွင်းပိုင်းတွင် လုပ်ဆောင်ချက်၏ အမည်နှင့် ပါရာမီတာအဖြစ် အသုံးပြုမည့် Path ၏ Object အားကွန်ဆိုးပေါ်တွင် ရေးသားစေပါမည်။

FileVisitor ကို အသုံးပြုရန်မှာ Files#walkFileTree မှ တဆင့် အသုံးပြုရပါမည်။ ပဋ္ဌမပါရာမီတာ အဖြစ် ရှာဖွေလိုသည့် Path Object နှင့် ဒုတိယ ပါရာမီတာ အဖြစ် ထို Path အတွင်းတွင် အလုပ်လုပ်စေမည့် FileVisitor Object ကို အသုံးပြုရန်လိုအပ်ပါသည်။

Files#walkFileTree အတွင်းတွင် FileVisitor အား မည်သို့အသုံးချသွားသည်ကို သိရှိရန် အထက်ပါ ကုဒ်များအား ကွန်ပိုင်းလုပ်၍ စမ်းသပ်ကြည့်ပါမည်။



အထက်ပါ ရလဒ်ကို ကြည့်ခြင်းအားဖြင့် Files#fwalkFileTree အတွင်းတွင် ဦးစွာ preVisitDirectory ဖြင့် alpha အားသွားပြီး bravo မှတဆင့် visitFile ဖြင့် bar.txt ကို သွားနေသည်ကို တွေ့ရပါသည်။ ဒိုင်အတ္တရီအတွင်းရှိ ဖိုင်နှင့် ဒိုင်အတ္တရီ များအား အောက်ပါအတိုင်း သွားရောက်ခဲ့သည်ကို တွေ့ရပါလိမ့်မည်။



ဒိုင်အတ္တရီ ကော်ပီအားရေးသားကြည့်ခြင်း


ကျွှန်တော်တို့တွေ ဒိုင်အတ္တရီတွေအတွင်းမှာ ထပ်ဆင့် ဒိုင်အတ္တရီနှင့် ဖိုင်များရှိပါက ကော်ပီကူး၍ မရခဲ့သည်ကို FileVisitor ကို သုံး၍ ရေးသားကြည့်ပါမည်။

CpyDir.java
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;

public class CpyDir {

    public static void main(String[] args) {

        if (args.length != 2) {
            System.out
                    .println("Please set the parameter as Copy from and Copy to.");
            return;
        }

        try {
            Cpy cp = new Cpy();
            cp.copyDir(Paths.get(args[0]), Paths.get(args[1]));
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }

    static class Cpy {

        public void copyDir(Path from, final Path to) throws IOException {
            FileVisitor<Path> visitor = new FileVisitor<Path>() {

                @Override
                public FileVisitResult postVisitDirectory(Path dir,
                        IOException exc) throws IOException {
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult preVisitDirectory(Path dir,
                        BasicFileAttributes attrs) throws IOException {
                    Files.copy(dir, to.resolve(dir),
                            StandardCopyOption.COPY_ATTRIBUTES);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFile(Path file,
                        BasicFileAttributes attrs) throws IOException {
                    Files.copy(file, to.resolve(file),
                            StandardCopyOption.COPY_ATTRIBUTES);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFileFailed(Path file,
                        IOException exc) throws IOException {
                    return FileVisitResult.CONTINUE;
                }
            };

            Files.walkFileTree(from, visitor);
        }
    }

}

အဓိကအားဖြင့် preVisitDirectory နှင့် visitFile တွင် ဖိုင်နှင့် ဒိုင်အတ္တရီကို ကော်ပီကူးသည့် ကုဒ်များကို ဖြည့်စွက်ရေးသားရုံသာ ဖြစ်၏။ from သည် ကော်ပီကူးမည့် နဂိုနေရာဖြစ်ပြီး၊ to သည် ကော်ပီကူးမည့် နေရာသစ်ဖြစ်ပါသည်။

 preVisitDirectory နှင့် visitFile တွင် ကော်ပီကူးသည့်ကုဒ်များကို ရေးထားခြင်းအားဖြင့် FileVisitor က from ၏ ဖိုင်များအား သွားရောက်သည့်အခါတွင် to နေရာတွင် တစ်ခုချင်း ကူးသွားမည်ဖြစ်ပါသည်။ လက်တွေ့ စမ်းသပ်ကြည့်ပါမည်။


alpha အား beta ၏ အောက်တွင် ကော်ပီကူးသွားနိုင်သည်ကို တွေ့ရပါလိမ့်မည်။ တစ်ခုသတိထားမိမည် ဖြစ်သည်။ beta မရှိပါက၊ အကယ်၍ beta ၏ အောက်တွင် alpha ရှိနှင့်ပြီး ဖြစ်ပါက ကောင်းစွာ အလုပ်လုပ်နိုင်မည် မဟုတ်ပေ။

အိမ်စာအနေဖြင့် အောက်ပါလော့ဂျစ်များအား ဖြည့်စွက်ရေးသားကြည့်ပါ။
  1. beta မရှိခဲ့ပါက alpha အား beta အမည်ဖြင့် ကူးယူနိုင်ရန်
  2. beta သည် ဒိုင်အတ္တရီအနေဖြင့် ရှိခဲ့ပြီး ၎င်း၏ အောက်တွင် alpha သည် ရှိနှင့်ပြီး ဖြစ်ပါက alpha အပေါ်တွင် ထပ်ပြီး ကူးရန်
အဖြေအား နောက်အခန်းများတွင် ဆက်လက်ဖော်ပြသွားပါမည်။

ဆက်ပါဦးမည်။ လေးစားစွာဖြင့်။
မင်းလွင်

No comments:

Post a Comment