February 9, 2012

FileSystem & Path Interface

ပြီးခဲ့သော NIO2 ဆိုသည်မှာ ဘလောဂ်ဖြင့် Java 7 ၏ ဖိုင်စစ္စတမ်အသစ်တစ်ခုဖြစ်သော NIO2 အကြောင်းကို အကျဉ်းချုံး ဖော်ပြခဲ့၏။ ယခင်အသုံးပြုခဲ့သော java.io.File ၏ အားနည်းချက်များဖြစ်ကြသော၊ Metadata များကိုအသုံးမပြုနိုင်ခြင်း၊ Symbolic Link များကို အသုံးမပြုနိုင်ခြင်းနှင့် ဖိုင်စစ္စတမ်ကို စောင့်ကြည့်မနေနိုင်ခြင်း အစရှိသည်တို့ကို ပြုပြင်ရန် ဖိုင်စစ္စတမ်အသစ်တစ်ခုကို အသစ်ရေသားလာခဲ့ခြင်း ဖြစ်၏။ ယခု တစ်ခေါက်တွင် NIO2 ၏ အဓိက ဇာတ်ကောင်များဖြစ်ကြသော FileSystem နှင့် Path Interface တို့၏ အသုံးပြုပုံတို့ကို လေ့လာသွားပါမည်။

FileSystem

FileSystem ကလပ်စ်သည် အမည်ပါအတိုင်း ဖိုင်စစ္စတမ်ကို ကိုယ်စားပြုသော ကလပ်စ်တစ်ခုဖြစ်ပါသည်။ FileSystem သည် လက်ရှိ OS အတွင်းရှိ ဖိုင်စစ္စတမ်များသာမက၊ jar သို့မဟုတ် zip ဖိုင်များကိုလည်း ဒြပ်မဲ့ ဖိုင်စစ္စတမ် (Virtual File System)  အနေဖြင့် အသုံးပြုနိုင်ပါသည်။

တဖန် FileSystem Object ကို အသစ်မွေးဖွားစေရာတွင် အသုံးပြုနိုင်သည်မှာ FileSystems Factory Class ပင်ဖြစ်၏။ Default FileSystem Object ကို မွေးဖွားစေရာတွင် အောက်ပါအတိုင်း အသုံးပြု ရေးသား နိုင်ပါသည်။
FileSystem fileSystem = FileSystems.getDefault();

FileSystem Class သည် AutoCloseable Interface ကို ပံ့ပိုးထားပါသဖြင့် Java 7 တွင် စတင်ခဲ့သော try-with-resource ရေးသားပုံကို အသုံးပြုနိုင်ပါသည်။ သို့ရာတွင် သတိထားရန် တစ်ခုမှာ FileSystems#getDefault မက်သတ်ဖြင့် ခေါ်ယူထားသော Default FileSystem အား try-with-resource ပုံစံဖြင့် ရေးသားပါက အလုပ်လုပ်ချိန်တွင် UnsupportedOperationException ကို ဖြစ်ပေါ်စေမည် ဖြစ်သည်။
package com.mmjug.java7.ep4;

import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;

public class FileSystemSample {

 public static void main(String[] args) {
  try (FileSystem fileSystem = FileSystems.getDefault()) {
   System.out.println(fileSystem.provider().getClass().getName());
  } catch (IOException e) {
   System.err.println(e.getMessage());
  }
 }
}
အထက်ပါ ကုဒ်များကို အလုပ်ခိုင်းကြည့်ပါက အောက်ပါအတိုင်း Exception ကို ဖြစ်ပေါ်စေမည် ဖြစ်သည်။
Exception in thread "main" sun.nio.fs.WindowsFileSystemProvider
java.lang.UnsupportedOperationException
 at sun.nio.fs.WindowsFileSystem.close(WindowsFileSystem.java:117)
 at com.mmjug.java7.ep4.FileSystemSample.main(FileSystemSample.java:12)

Open JDK အဖွဲ့မှ ပြသထားသော WindowsFileSystem ကလပ်စ်၏ close လုပ်ဆောင်ချက်ကို ကြည့်ကြည့်ရာတွင် အောက်ပါအတိုင်း UnsupportedOperationException ကို throw လုပ်နေသည်ကို တွေ့ရပါသည်။ ထို့ကြောင့် Exception ကို ဖြစ်ပေါ်စေခြင်းဖြစ်သည်။ Source ကုဒ်ကို ကြည့်ခြင်းအားဖြင့် လက်ရှိအချိန်တွင် WindowsFileSystem သည် AutoCloseable ကို အပြည့်အဝ ပံ့ပိုးနိုင်ပုံမရသေးပေ။
       @Override
       public void close() throws IOException {
           throw new UnsupportedOperationException();
       }
တမင်ပဲ Exception ကို throw လုပ်နေသလား၊ Bug လားတော့မသိပါ၊ Linux နှင့် Solaries OS များတွင် အသုံးပြုသော UnixFileSystem ၌လည်း အထက်ပါအတိုင်း ရေးသားထားသည်ကို တွေ့ရ၏။ OS အဆင့် ဖိုင်စစ္စတမ်ကို AutoCloseable မလုပ်စေချင်သည့်သဘောလား မသိပါ။ Bug Report ကို စောင့်ကြည့်ရပါဦးမည်။ လက်ရှိ FileSystem Object ကို ခေါ်ယူနိုင်ကြောင်းကို သိရသည့်အတွက် ရှေ့ကို ဆက်ပါဦးမည်။


Path Interface

Path Interface သည် လက်ရှိ ဖိုင်စစ္စတမ် အတွင်းရှိ ဖိုင်နှင့် ဒိုင်အက်တရီများကို ကိုယ်စားပြုပါသည်။ Path ၏ instance များကို မွေးဖွားစေရာတွင် FileSystem#getPath လုပ်ဆောင်ချက်ကို၎င်း Paths#get လုပ်ဆောင်ချက်ကို၎င်း အသုံးပြုနိုင်ပါသည်။
  // Path with only one parameter
  Path path1 = fs.getPath("c:\\tmp\\fpone.txt");
  System.out.println(path1);
  
  // Path with varargs
  Path path2 = fs.getPath("c:", "tmp","sample","ftwo.txt");
  System.out.println(path2);
  
  // Path made by Paths
  Path path3 = Paths.get("c:\\tmp\\fthree.txt");
  System.out.println(path3);

FileSystem#getPath လုပ်ဆောင်ချက်သည် ပါရာမီတာအား၊ Varargs အနေဖြင့် အသုံးပြုနိုင်ပါသည်။ ပါရာမီတာ တစ်ခုတည်းသာ ပါဝင်ခဲ့မည်ဆိုလျှင် စာကြောင်း ၂ ကဲ့သို့ ဖိုင်၊ ဒါမှမဟုတ်  ဒိုင်အတ္တရီ တစ်ခုအနေဖြင့် အသုံးပြုနိုင်မည် ဖြစ်သည်။ ရေးသားရာတွင်လည်း လမ်းကြောင်း အတိအကျ (Absolute Path) အနေဖြင့်၎င်း၊ နှိုင်းယှဉ် လမ်းကြောင်း (Relative Path) အနေဖြင့်၎င်း ရေးသားနိုင်ပါသည်။

စာကြောင်း နံပါတ်၆ကဲ့သို့ ပါရာမီတာအများ(Varargs) ကို အသုံးပြုထားပါက၊ နောက်ဆုံး ပါရာမီတာသည် ဖိုင်ဒါမှ မဟုတ် ဒိုင်အတ္တရီ၏ အမည် အဖြစ်အသုံးပြုမည်ဖြစ်ပြီး၊ ကျန်ရစ်သော ပါရာမီတာများကိုမူ Sub Directory အဖြစ်အသုံးပြုနိုင်မည် ဖြစ်သည်။ ဤနမှုနာ၌ စာကြောင်း ၇ ဖြင့် "c:\tmp\sample\ftwo.txt" ကို ဖော်ပြပေးနိုင်မည် ဖြစ်သည်။

NIO2 တွင် FileSystem အပြင် အလွယ်တကူ Path အင်စတန့်စ်များကို မွေးဖွားစေနိုင်ရန် Paths ကလပ်စ်ကို ပြင်ဆင်ထားပါသည်။ အထက်ပါ နမှုနာ၏ စာကြောင်း ၁၀ကဲ့သို့ Paths#get လုပ်ဆောင်ချက်ကို အသုံးပြုပါက၊ အတိအကျလမ်းကြောင်းဖြစ်ဖြစ်၊ နှိုင်းယှဉ်လမ်းကြောင်းများကိုပါ Path Object များကို မွေးဖွားအသုံးပြုနိုင်ပါသည်။ သို့ရာတွင် Paths ကလပ်စ်ဖြင့် အသုံးပြုနိုင်သည်မှာ Default FileSystem များသာဖြစ်သည်ကို သတိပြုစေလိုပါသည်။

အထက်ပါ နမှုနာကို Run လုပ်ကြည့်သောအခါ အောက်ပါအတိုင်း ဖော်ပြနိုင်မည်ဖြစ်သည်။
c:\tmp\fpone.txt
c:\tmp\sample\ftwo.txt
c:\tmp\fthree.txt

FileSystemProvider

FileSystem ကလပ်စ်များအား ပံ့ပိုးပေးနေသည်မှာ ServiceProvider များပင်ဖြစ်၏။ Java ၏ ServiceProvider သည် java.nio.file.spi.FileSystemProvider ဖြစ်၏။ လက်ရှိ အသုံးပြုနိုင်သော ServiceProvider များအား  FileSystemProvider #installedProviders ဖြင့် သိရှိနိုင်ပါသည်။
 public static void main(String[] args) {
  List list = FileSystemProvider.installedProviders();
  
  for(FileSystemProvider p : list) {
   System.out.println(p.getScheme() + " : " + p.getClass());
  }
 }
အထက်ပါ နမှုနာ၏ စာကြောင်း ၂ တွင် installedProviders လုပ်ဆောင်ချက်ဖြင့် အသုံးပြုနိုင်သော FileSystemProvider များကို ရယူပါသည်။ တဖန် for ဝါကျကိုအသုံးပြု၍ list အတွင်းရှိ FileSystemProvider Object များ၏ စကီးမားနှင့် ကလပ်စ် များကို ရေးသားနေစေပါသည်။ လက်ရှိ အလုပ်လုပ်ကြည့်စေသောအခါ အောက်ပါအတိုင်းတွေ့ရမည် ဖြစ်သည်။
file : class sun.nio.fs.WindowsFileSystemProvider
jar : class com.sun.nio.zipfs.ZipFileSystemProvider
File များအား ပံ့ပိုးပေးရန်အတွက် WindowsFileSystemProvider နှင့် jar ဒါမှမဟုတ် zip ဖိုင်တွေကို ပံ့ပိုးပေးဖို့အတွက် ZipFileSystemProvider တို့က တာဝန်ယူထားသည်ကို သိရှိနိုင်ပါသည်။ FileSystems#getDefault ဖြင့် ခေါ်ယူပါက WindowsFileSystemProvider မှ Windows ၏ FileSystem ကို ပြန်လည်ပေးပို့ပေးမည် ဖြစ်၏။ Default File System မှာ အသုံးပြုနေသော OS အပေါ်မှုတည်၍ အမျိုးမျိုး ပြောင်းလည်းနိုင်ပါသည်။

Jar နှင့် Zip ဖိုင်များအား File System အနေဖြင့် အသုံးပြုနိုင်သော ZipFileSystemProvider ကို အသုံးပြုပြီး လက်တွေ့ နမှုနာတစ်ခုကို ရေးကြည့်ပါမည်။ ဤနေရာတွင် getDefault ဖြင့်ခေါ်ယူ၍မရပဲ FileSystems#newFileSystem လုပ်ဆောင်ချက်ကို အသုံးပြုသွားမည် ဖြစ်ပါသည်။
package com.mmjug.java7.ep4;

import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;

public class ZipFileSystem {

 public static void main(String[] args) {
  
  Path zip = Paths.get("A:","var","tomcat-7","lib","catalina.jar");

  try (FileSystem fs = FileSystems.newFileSystem(zip,
    ClassLoader.getSystemClassLoader())) {
   System.out.println("FileSystem : " + fs);
   System.out.println("Class : " + fs.getClass());
  } catch (IOException e) {
   System.out.println(e.getMessage());
  }
 }

}
အထက်ပါ နမှုနာအထဲတွင် catalina.jar ဖိုင်အား  ဒြပ်မယ့်ဖိုင်စစ္စတမ် တစ်ခုအနေဖြင့် အသုံးပြုရန် ZipFileSystemProvider ကိုအသုံးပြု၍ ZipFileSystem ကို ခေါ်ယူနေခြင်းဖြစ်ပါသည်။  ဦးစွာ catalina.jar ဖိုင်၏ နေရာအတိအကျကိုဖော်ပြ၍ Path အင်တာဖေစ်ကို မွေးဖွားစေပါသည်။ တဖန် အထက်ပါ Path အင်းစတန့်စ်အား ပါရာမီတာအဖြစ်သုံးပြီး FileSystems ကလပ်၏ newFileSystem လုပ်ဆောင်ချက်ကို အသုံးပြုကာ catalina.jar အား ဒြပ်မဲ့ဖိုင်စစ္စတမ် အဖြစ်အသုံးပြုနိုင်သော Object တစ်ခုကို ရယူနေပါသည်။

ကျွှန်တော်တို့ ဤဘလောဂ်ဖြင့် FileSystem ကလပ်စ်နှင့် Path အင်တာဖေစ်တို့ကို မွေးဖွားစေပုံနှင့် jar နှင့် zip ဖိုင်တို့ကို ဒြပ်မဲ့ဖိုင် စစ္စတမ်အဖြစ် အသုံးပြုနိုင်ရန် ZipFileSystemProvider တို့က ပံ့ပိုးပေးနေကြောင်းကို လေ့လာခဲ့ပါသည်။

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

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


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

No comments:

Post a Comment