February 21, 2012

Directory And File

ပြီးခဲ့သော အခန်းဆက်ဖြင့် Java 7 NIO2 ၏ FileSystem နှင့် Path အင်တာဖေစ် အကြောင်းကို ဖော်ပြခဲ့၏။FileSystemကို အသုံးပြု၍ Default File System နှင့် Zip ဒါမှမဟုတ် Jar ကဲ့သို့သော ဒြပ်မဲ့ဖိုင်စစ္စတမ် (Virtual File System) များကို အသုံးပြုနိုင်ကြောင်းနှင့်၊ Path အင်တာဖေစ်ကို အသုံးပြု၍ ဖိုင်များကို အသုံးပြုပုံတို့ကို ဖော်ပြခဲ့၏။ ယနေ့ဆက်လက်၍ NIO2 ၏  ဒိုင်အတ္တရီ (Directory)  နှင့် ဖိုင် များကို ဆက်သွယ်ပြီး Input/Output ပြုလုပ်ပုံနှင့်၊ ယခင်ရှိခဲ့ပြီးဖြစ်သော File IO နှင့် ဆက်သွယ်ပြီး အသုံးပြုပုံတို့ကို လေ့လာသွားပါမည်။


Directory

NIO2 တွင် ဒိုင်အတ္တရီ (Directory)  များကိုအသုံးပြုနိုင်ရန် DirectorySystem ကို ပံ့ပုံပေးလာခဲ့ပါသည်။ ယခင်တစ်ခေါက်က လေ့လာခဲ့သော Path အင်တာဖေစ် ဖြင့်လည်း ဒိုင်အတ္တရီ (Directory) များကို ကိုယ်စားပြု အသုံးပြုနိုင်ပါသည်။ သို့ရာတွင် Path အင်တာဖေစ်သည် ဖိုင်နှင့် ဒိုင်အတ္တရီ (Directory) တို့၏ တူညီသော အချက်အလက်များနှင့် အသုံးပြုပုံတို့ကိုသာ အသုံးပြုနိုင်ခဲ့၏။ ဒိုင်အတ္တရီ (Directory) အတွင်းရှိ ဖိုင်များနှင့် ထပ်ဆင့် ဒိုင်အတ္တရီများကိုမူ ခေါ်ယူအသုံးပြုနိုင်ခြင်း မရှိခဲ့ပါ။ အဆိုပါအချက်အလက်များကို အသုံးပြုနိုင်ရန်မှာ DirectorySystem အင်တာဖေစ်ကို ပံ့ပိုးထားသော အော့ဘဂျက် (Object) များကို အသုံးပြုရန် လိုအပ်ပါသည်။

DirectorySystem အော့ဘဂျက် (Object) အား Files အသုံးပြုကလပ်စ် (Utility Class) ၏ newDirectorySystem လုပ်ဆောင်ချက်ကို အသုံးပြုပြီး ခေါ်ယူ အသုံးပြု နိုင်ပါသည်။ လက်တွေ့ ဒိုင်အတ္တရီအတွင်းရှိ ဖိုင်များကို ရေးသားဖော်ပြနိုင်သော showChildren မက်သတ်ကို ပိုင်ဆိုင်သော ကလပ်စ်တစ်ခုကို ရေးသားကြည့်ပါမည်။ ပြီးလျှင် ပြီးခဲ့သောအပါတ်က ရေးသားခဲ့သော Zip File System နမှုနာ၏ Tomcat 7 ၏ catalina.jar အတွင်းရှိ ဖိုင်များကို ရေးသားကြည့်စေပါမည်။ အကုန်လျှောက်ရေးလျှင် ရှည်ကုန်မှာစိုးပါသဖြင့် org.apache.namming အောက်ရှိ ဖိုင်များကို ရေးခိုင်းကြည့်ပါမည်။
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;

public class ShowChildren {
 
 private static final String BIAS = "    ";
 
 public void showChildren(Path path, String bias) throws IOException {
  
  System.out.println(bias + path.getFileName());
  
  if(Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) {
   DirectoryStream<Path> directory = Files.newDirectoryStream(path);
   
   for(Path p : directory)
    this.showChildren(p, bias + BIAS);
  }
 }
 
 public static void main(String[] args) {

  ShowChildren sc = new ShowChildren();
  Path zip = Paths.get("A:","var","tomcat-7","lib","catalina.jar");
  
  try (FileSystem fs = FileSystems.newFileSystem(zip,
    ClassLoader.getSystemClassLoader())) {
   sc.showChildren(fs.getPath("org","apache","naming"), BIAS);
  } catch (IOException e) {
   System.out.println(e.getMessage());
  }
 }

}
Files#newDirectorySystem ဖြင့်အသုံးပြုရန် Path အော့ဘဂျက်မှာ ဒိုင်အတ္တရီ (Directory) ဖြစ်ရန် လိုအပ်ပါသည်။ ထို့အတွက် Files#isDirectory ဖြင့် ဒိုင်အတ္တရီ ဖြစ်ကြောင်း စမ်းစစ်နေပါသည်။ isDirectory ၏ ပဋ္ဌမ ပါရာမီတာမှာ Path အော့ဘဂျက်ဖြစ်ပြီး၊ ဒုတိယပါရာမီတာမှာ Varargs ပုံစံ LinkOption Enum ဖြစ်ပါသည်။ ဤနေရာတွင် လင့်ခ်ဖြစ်ပါက လိုက်မရှာရန် NOFOLLOW_LINKS ကို အသုံးပြုထားပါသည်။

တဖန် စာကြောင်း ၁၉တွင် DirectorySystem အင်တာဖေစ်၏ အော့ဘဂျက်ကို Files#newDirectorySystem ကို သုံး၍ ခေါ်ယူပါသည်။ DirectorySystem သည် java.lang.Iterable ၏ Sub Interface ဖြစ်သောကြောင့် For ဝါကျကို သုံး၍ ပါဝင်သော Path အော့ဘဂျက် တစ်ခုချင်းကို ရယူပြီး showChildren လုပ်ဆောင်ချက်ကို ပြန်လည် လုပ်ဆောင် စေနိုင်ပါသည်။

တဖန် Zip ဖိုင်စစ္စတမ်ကို အသုံးပြု၍ catalina.jar အတွင်းရှိ org.apache.naming အတွင်းရှိ ဖိုင်များကို showChildren ကို သုံး၍ ရေးသားစေပါသည်။ အထက်ပါ ပရိုဂရမ်ကို အလုပ်ခိုင်ကြည့်သောအခါ အောက်ဖော်ပြပါအတိုင်း ကွန်ဆိုးတွင် ထွက်ပေါ်လာမည် ဖြစ်သည်။
    naming
        TransactionRef.class
        StringManager.class
        ServiceRef.class
        SelectorContext.class
        ResourceRef.class
        ResourceLinkRef.class
        ResourceEnvRef.class
        NamingEntry.class
        NamingContextEnumeration.class
        NamingContextBindingsEnumeration.class
        NamingContext.class
        NameParserImpl.class
        LocalStrings.properties
        JndiPermission.class
        HandlerRef.class
        EjbRef.class
        ContextBindings.class
        ContextAccessController.class
        Constants.class
        resources/
            WARDirContext.class
            WARDirContext$WARResource.class
            WARDirContext$Entry.class
            VirtualDirContext.class
            ResourceCache.class
            ResourceAttributes.class
            Resource.class
            RecyclableNamingEnumeration.class
            ProxyDirContext.class
            LocalStrings.properties
            ImmutableNameNotFoundException.class
            FileDirContext.class
            FileDirContext$FileResourceAttributes.class
            FileDirContext$FileResource.class
            DirContextURLStreamHandlerFactory.class
            DirContextURLStreamHandler.class
            DirContextURLConnection.class
            Constants.class
            CacheEntry.class
            BaseDirContext.class
            BaseDirContext$AliasResult.class
            BaseDirContext$1.class
            jndi/
                Handler.class
        java/
            javaURLContextFactory.class
        factory/
            TransactionFactory.class
            SendMailFactory.class
            SendMailFactory$1.class
            ResourceLinkFactory.class
            ResourceFactory.class
            ResourceEnvFactory.class
            OpenEjbFactory.class
            MailSessionFactory.class
            MailSessionFactory$1.class
            MailSessionFactory$1$1.class
            EjbFactory.class
            DataSourceLinkFactory.class
            DataSourceLinkFactory$DataSourceHandler.class
            Constants.class
            BeanFactory.class

ယခင် File များနှင့် ဆက်သွယ်အသုံးပြုပုံ


Java ကဲ့သို့ အသုံးများသော ဘာသာရပ်များတွင် API အသစ်တစ်ခုတွင် အသစ်ပါဝင်သော အင်တာဖေစ်များကို လေ့လာရုံနှင့် လိုလောက်မည် မဟုတ်သေးပါ။ လက်ရှိအသုံးပြုနေသော API အဟောင်းများလည်း နေရာအနှံ့တွင် ရှိသောကြောင့် ရှိပြီးသား စစ္စတမ်နှင့် အပြန်အလှန် အသုံးပြုနိုင်မှု့သည် လွန်စွာမှအရေးပါလှပါသည်။

Path အော့ဘဂျက်မှ File အော့ဘဂျက်ကို ရယူရာတွင် Path အင်တာဖေစ်၏ toFile မက်သတ်ကို ပြင်ဆင်ထားပြီး၊ File မှ Path ကို ခေါ်ယူရန်အတွက် toPath မက်သတ်ကို ပြင်ဆင်ထားပါသည်။ သတိပြုရန်အချက်မှာ File ကလပ်စ်တွင် getPath လုပ်ဆောင်ချက်ကို ပံ့ပိုးထားပြီး၊ အထက်ပါ လုပ်ဆောင်ချက်မှာ File အော့ဘဂျက်၏ တည်နေရာကို စာကြောင်း အဖြစ် ပြန်လည် ဖော်ပြပေးနိုင်သော လုပ်ဆောင်ချက်ဖြစ်ပြီး Path အော့ဘဂျက်ကို မရရှိနိုင်ပါ။

ကျွှန်တော်တို့ လက်တွေ့ရေးကြည့်ပါမည်။
 public static void main(String[] args) {
  Path path = Paths.get("A:","var","tomcat-7","lib","catalina.jar");
  File file = new File("A:\\var\\tomcat-7");
  
  System.out.println("path" + "\t" + path);
  System.out.println("file" + "\t" + path.toFile());
  System.out.println("file" + "\t" + file);
  System.out.println("path" + "\t" + file.toPath());
  
 }
အထက်ပါပရိုဂရမ်၏ ရလဒ်မှာ အောက်ပါအတိုင်းဖြစ်ပါသည်။
path A:\var\tomcat-7\lib\catalina.jar
file A:\var\tomcat-7\lib\catalina.jar
file A:\var\tomcat-7
path A:\var\tomcat-7
 
ဖော်ပြပါအတိုင်း ဖိုင်အဟောင်းနှင့် Path ကို လွယ်ကူစွာ အပြန်အလှန် ခေါ်ယူ အသုံးပြုနိုင်သော်လည်း တစ်ခု သတိထားရန် အချက်မှာ ဤကဲ့သို့ ဖိုင်မှ Path နှင့် Path မှ ဖိုင် ပြောင်းလည်းခြင်းသည် DefaultFileSystem ကို အသုံးပြုသည့်အခါတွင်သာ အသုံးပြုနိုင်မည်ဖြစ်ပြီး ZIP/JAR ဖိုင်စစ္စတမ်ကို အသုံးပြုရာမှာ အသုံးပြုနိုင်မည် မဟုတ်ပေ။

Input / Output ပြုလုပ်ပုံများ

Java တွင် ဖိုင်များကို ဖတ်ယူရာတွင်၎င်း ရေးသားရာတွင်၎င်း၊ Stream များ၊ Reader Writer များနှင့် Channel များကို အသုံးပြုနိုင်ပါသည်။ Path အင်တာဖေစ်တွင်လည်း ထိုနည်းတူပင်ဖြစ်၏။ NIO2 ၌ java.io.FileInputStream နှင့် java.io.FileReader အစရှိသည့် ကလပ်စ်များနှင့် အဆင့်တူ ကလပ်စ်များကို ပြင်ဆင်ထားခြင်းမရှိပါ။ သို့ရာတွင် Files ကလပ်စ်ကို အသုံးပြု၍ FileInputStream များ FileReader များကို ခေါ်ယူနိုင်ပါသည်။


StandardOpenOption

NIO2 တွင် Files Utility ကလပ်စ်ကိုအသုံးပြု၍ Path အော့ဘဂျက် ဖိုင်များကို အလွယ်တကူ ဆက်သွယ်အသုံးပြုနိုင်ပါသည်။ ဖိုင်အော့ဘဂျက် များကို Input Output ပြုလုပ်ရာတွင် ရှိရင်းစွဲ Streams များ၊ Readers များ အပြင် Channels များကို အသုံးပြု၍၎င်း၊ Files ကလပ်စ်မှ တိုက်ရိုက် In Out ပြုလုပ်နိုင်ပါသည်။ Files မှ ဖိုင်များကို ဆက်သွယ်ရာတွင် မည်သည့်ပုံစံဖြင့် ဆက်သွယ်မည်ဆိုသည်ကို သတ်မှတ်ရန် လိုအပ်ပါသည်။ ဤသို့သက်မှာရာတွင် OpenOption Enum ကို အသုံးပြု၍ နှစ်သက်သလို အသုံးပြုနိုင်ပါသည်။

ပြင်ဆင်ထားသော StandardOpenOption Enum မှာ အောက်ပါအတိုင်းဖြစ်၏။

  • APPEND
  • CREATE
  • CREATE_NEW
  • DELETE_ON_CLOSE
  • DSYNC
  • READ
  • SPARSE
  • SYNC
  • TRUNCATE_EXISTING
  • WRITE


Stream များ

ဦးစွာ Stream များကို အသုံးပြုကြည့်ပါမည်။
 public static void doStreamSample(Path path) {

  try (InputStream input = Files.newInputStream(path);
    OutputStream out1 = Files.newOutputStream(path,
      StandardOpenOption.APPEND)) {
   // INPUT OUTPUT Process

  } catch (IOException e) {
   e.printStackTrace();
  }
 }
Files ကလပ်စ်၏ newInputStream နှင့် newOutputStream တို့တွင် ပါရာမီတာအနေဖြင့် Path အော့ဘုဂျက်နှင့် OpenOption Enum ၏ Varargs ကို အသုံးပြုရန်လိုအပ်ပါသည်။ Path မှာ Input Output လုပ်မည့် Path အော့ဘဂျက်ဖြစ်ပြီး၊ OpenOption မှာ File အား ဖွင့်ရာတွင် အသုံးပြုလိုသည့် Option များ ဖြစ်ပါသည်။ Varargs ပုံစံဖြစ်ပါသဖြင့် လိုအပ်သလို သတ်မှတ် အသုံးပြုနိုင်ပါသည်။


Reader နှင့် Writer များ

တဖန် Reader အော့ဘဂျက်များကိုလည်း Stream များကဲ့သို့ပင် Files Utility ကလပ်စ်မှ တိုက်ရိုက်ခေါ်ယူ အသုံးပြုနိုင်ပါသည်။
 public static void doReaderSample(Path path) {

  try (BufferedReader input = Files.newBufferedReader(path, 
      Charset.forName("utf-8"));
    BufferedWriter out1 = Files.newBufferedWriter(path,
      Charset.forName("utf-8"),
      StandardOpenOption.APPEND)) {
   // INPUT OUTPUT Process

  } catch (IOException e) {
   e.printStackTrace();
  }
 }
BufferedReader နှင့် BufferedWriter များကိုလည်း၊ Input Output Stream များကဲ့သို့ပင် Files Utility ကလပ်စ်မှ တိုက်ရိုက်ခေါ်ယူနိုင်ပါသည်။ BufferedReader နှင့် BufferedWriter တို့ကို တစ်ကြောင်းတည်းနှင့် ခေါ်ယူနိုင်ခြင်းသည် လွန်စွာမှ အစဉ်ပြေပါသည်။ ယခင်ကဆိုလျှင် FileInputStream အစရှိသည်တို့ကို ပါရာမီတာအဖြစ် ပေးရန် လိုအပ်ခဲ့သည်။ ဖိုင်လေးတစ်ခုရေးဖို့၊ ဖတ်ဖို့အတွက် မသုံးတဲ့ အော့ဘဂျက်တွေကို ရေးစရာလိုခဲ့ပေသည်။ သို့ရာတွင် Java 7 အရောက်တွင် အသုံးလိုသည့် BufferedReader ကို တိုက်ရိုက်ခေါ်ယူနိုင်သဖြင့် လွန်စွာမှ အစဉ်ပြေလှပါသည်။ မေ့စရာလည်း မရှိတော့ပေ။ သို့ရာတွင် BufferedReader နှင့် BufferedWriter တို့သည် Character Set ကို အသုံးပြုရန်လိုအပ်သဖြင့် ဒုတီယ ပါရာမီတာတွင် CharSet ၏ အော့ဘဂျက်ကို သတ်မှတ်ပေးရန် လိုအပ်ပါသည်။ တတိယပါရာမီတာမှာမူ၊ OpenOption Enum ၏ Verags ပင်ဖြစ်၏။


Chanel များ

 public static void doSeekChennelSample(Path path) {
  try (SeekableByteChannel chennel = Files.newByteChannel(path);
    SeekableByteChannel writeChannel = Files.newByteChannel(path, 
      StandardOpenOption.WRITE, 
      StandardOpenOption.APPEND)) {
   // INPUT OUTPUT Process

  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 public static void doFileChannelSample(Path path) {
  try (FileChannel channel = FileChannel.open(path);
    FileChannel wtChannel = FileChannel.open(path, StandardOpenOption.WRITE)) {
   // INPUT OUTPUT Process

  } catch (IOException e) {
   e.printStackTrace();
  }
 }

Channel များကိုလည်း Files#newByteChannel ကို အသုံးပြု၍ ခေါ်ယူနိုင်ပါသည်။ Channel များသည်၊ ဖတ်နိုင်ရေးနိုင်သော အော့ဘဂျက်များ ဖြစ်ကြပါသည်။ သို့ရာတွင် Default မှာ ReadOnly ဖြစ်ပါသဖြင့် ရေးသားနိုင်ရန် StandardOpenOption.WRITE ကို သက်မှတ်ရန်လိုအပ်ပါသည်။

တဖန် ယခင်ကကဲ့သို့ FileChannel#open ဖြင့်လည်း FileChannel အော့ဘဂျက်ကို ခေါ်ယူအသုံးပြုနိုင်ပါသည်။ Java 7 မတိုင်ခင်က Stream ကို ကြားခံ၍ အသုံးပြုရန်လိုအပ်ခဲ့သော်လည်း Java 7 အရောက်တွင် Path အင်တာဖေစ်မှ တိုက်ရိုက်ခေါ်ယူလာနိုင်ခဲ့ပါသည်။


ပေါ့ပါးသော ဖိုင်များဆိုပါက

 public static void easyReadSample(Path path) throws IOException {
  
  // Read Bytes
  byte [] bytes = Files.readAllBytes(path);
  
  // Read Lines
  List<String> lines = Files.readAllLines(path, Charset.defaultCharset());
  
  // Write bytes
  Files.write(path, bytes, StandardOpenOption.APPEND);
  
  // Write Text Lines
  Files.write(path, lines, Charset.forName("utf-8"), StandardOpenOption.APPEND);
 }
နောက်ဆုံးတွင် အသုံးပြုလိုသောဖိုင်မှာ သေးငယ်ပေါ့ပါးပါက၊ Stream, Reader/Writer, Channel သုံးစရာမလိုပဲ Files Utility ကလပ်စ်မှ တိုက်ရိုက် အသုံးပြုနိုင်သည်ကို တွေ့ရပါသည်။



နောက်ဆုံးတွင်


ကျွှန်တော်တို့သည် ဒိတစ်ခေါက်တွင် Directory ၏ လုပ်ဆောင်ချက်များကို အပြည့်အဝအသုံးပြုနိုင်ရန် DirectorySystem ကလပ်စ်ကို အသုံးပြုရန်လိုအပ်ကြောင်း၊ မှုလ ဖိုင်စစ္စတမ်များနှင့်လည်း အလွယ်တကူ အပြန်အလှန် ဆက်သွယ်အသုံးပြုနိုင်ကြောင်းနှင့် Input Output ပြုလုပ်ရာတွင်လည်း ရင်းနှီးပြီးသား ကလပ်စ်များမှအစ၊ Channel များကိုပါ Path အင်တာဖေစ်ကို အသုံးပြု၍ လွယ်ကူစွာ ခေါ်ယူအသုံးပြုနိုင်ကြောင်း လေ့လာခဲ့ပါသည်။ ပြန်လည်သုံးသပ်ရမည် ဆိုလျှင် အသစ်များကိုလည်း အသုံးပြုနိုင်၏၊ ယခင်ကအရာများကိုလည်း အသုံးပြုနိုင်၏၊ ထိုထက်မက ပိုမိုလွယ်ကူစွာခေါ်ယူအသုံးပြုနိုင်၏။ ကျွှန်တော်သည် ဤဘလောဂ်အား ရေးရင်းနဲ့ ဖိုင်အင်တာဖေစ် အသစ်များကို လက်တွေ့အသုံးပြုလိုစိတ်များ တစ်ဖွားဖွား ပေါ်ပေါက်လာပတ်တော့သည်။ နောက်တစ်ခေါက်ရေးရန် Happy Hacking တွင် Nio2 ကိုသုံး၍ ဖိုင်ကိုခေါ်ဖတ်ပုံကို ထည့်သွင်းရေးသားကြည့်ပါဦးမည်။


ကိုးကား
http://itpro.nikkeibp.co.jp/article/COLUMN/20110725/362803/?ST=develop&mkjt&P=6


လေးစားစွာဖြင့်
မင်းလွင်

No comments:

Post a Comment