afrag  
          記錄學習和成長的歷程
          日歷
          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567
          統(tǒng)計
          • 隨筆 - 9
          • 文章 - 5
          • 評論 - 2
          • 引用 - 0

          導航

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          文章檔案

          搜索

          •  

          積分與排名

          • 積分 - 10117
          • 排名 - 2383

          最新評論

          閱讀排行榜

          評論排行榜

           

          2010年4月5日

          轉(zhuǎn)自 開發(fā)者的天空

          本文中我們來討論在NIO2中怎樣創(chuàng)建文件、讀取文件和寫文件。NIO2提供了多種創(chuàng)建 文件的方法,使得我們在創(chuàng)建文件的時候就可以指定文件的某些初始屬性。例如在支持POSIX的文件系統(tǒng)上指定文件的所有者,訪問權(quán)限等。關于文件的屬性, 請看上一篇文章Java SE 7新特性之文件操作(5) - 管理元數(shù)據(jù)
          創(chuàng)建文件
          可以調(diào)用createFile(FileAttribute<?>)方法創(chuàng)建一個空文件。該方法的參數(shù)就是文件的初始屬性。下面的例子是怎樣 在創(chuàng)建文件的時候賦予該文件某些權(quán)限的屬性:
          Path sourceFile = ;
          Path newFile 
          = ;
          PosixFileAttributes attrs 
          = Attributes.readPosixFileAttributes(sourceFile);
          FileAttribute
          <Set<PosixFilePermission>> attr =
                    PosixFilePermissions.asFileAttribute(attrs.permissions());
          try {
              file.createFile(attr);
          catch (IOException x) {
              
          //unable to create the file
          }
          如 果在調(diào)用該方法的時候沒有傳入任何參數(shù),那么創(chuàng)建的文件將具有缺省的文件屬性。下面的代碼創(chuàng)建了一個具有缺省文件屬性的文件:
          Path file = ;
          try {
              file.createFile();   
          //Create the empty file with default permissions, etc.
          catch (FileAlreadyExists x) {
              System.err.format(
          "file named %s already exists%n", file);
          catch (IOException x) {
              
          //Some other sort of failure, such as permissions.
              System.err.format("createFile error: %s%n", x);
          }
          如 果要創(chuàng)建的文件已經(jīng)存在,該方法會拋出異常。
          注意在調(diào)用createFile方法時,檢查文件是否存在和創(chuàng)建具有特定的屬性的文件是在同一個原子操作中。
          還可以使用newOutputSteam方法來創(chuàng)建文件,在本文的后面我們會講到怎樣使用newOutputStream方法來創(chuàng)建文件。
          通過Stream I/O讀文件
          我們可以通過newInputStream(OpenOption...)方法打開和讀取文件。這個方法返回一個unbuffered輸入流(input stream),我們可以用它來從文件中讀取字節(jié)內(nèi)容。
          Path file = ;
          InputStream in 
          = null;
          try {
              in 
          = file.newInputStream();
              BufferedReader reader 
          = new BufferedReader(new InputStreamReader(in));
              String line 
          = null;
              
          while ((line = reader.readLine()) != null) {
                  System.out.println(line);
              }
          catch (IOException x) {
              System.err.println(x);
          finally {
              
          if (in != null) in.close();
          }
          注 意該方法接受可變個數(shù)的參數(shù),參數(shù)類型為OpenOption,指定了文件怎樣打開。如果不傳入?yún)?shù),則使用默認的READ方式打開。READ方式是所有 的實現(xiàn)都支持的方式。有一些實現(xiàn)也支持其他的打開方式。
          如果傳入的OpenOption或其組合不正確,會拋出異常。如果程序沒有讀權(quán)限或I/O錯誤,也會拋出異常。
          Creating and Writing a File by Using Stream I/O
          使用Stream I/O來創(chuàng)建和寫文件
          我們可以使用newOutputStream方法來創(chuàng)建文件、擴展文件或覆蓋已有文件。這個方法為了寫文件而打開或創(chuàng)建文件,該方法返回一個 unbuffered的輸出流(output stream)。newOutputStream方法有兩種形式:

          • newOutputStream(OpenOption...)
          • newOutputStream(Set<? extends OpenOption>, FileAttribute<?>...)

          這兩種形式都接受一組OpenOption作為參數(shù),第二種形式還允許指定初始的文件屬性。這個方法支持的StandardOpenOption有:

          • WRITE –為了寫訪問而打開該文件.
          • APPEND – 將新數(shù)據(jù)擴展在文件的末尾。該選項和WRITE或CREATE選項一起使用。
          • TRUNCATE_EXISTING – 將文件截斷為0字節(jié)長. 該選項和WRITE選項一起使用來覆蓋原有文件。
          • CREATE_NEW – 創(chuàng)建一個新的文件。如果原來的文件存在這拋出異常。
          • CREATE – 如果原文件存在這打開它,否則創(chuàng)建新的文件。
          • DELETE_ON_CLOSE – 當Stream關閉時刪除該文件。這個選項對臨時文件比較有用。
          • SPARSE – 表明新創(chuàng)建的文件是Sparse文件. 關于Sparse文件的具體信息請看http://space.itpub.net/8242091/viewspace-619756
          • SYNC – 保持該文件(包括內(nèi)容和元數(shù)據(jù))與底層存儲設備同步。
          • DSYNC – 保持文件內(nèi)容與底層存儲設備同步。

          如果沒有指定OpenOption,該方法的行為是:如果文件不存在,則創(chuàng)建新文件;如果文件存在,那么截斷它。也就是說缺省的選擇是CREATE和 TRUNCATE_EXISTING選項的組合。
          下面的代碼打開一個日志文件,如果文件不存在,則創(chuàng)建一個新文件。如果文件 存在,這將新的內(nèi)容擴展到文件尾部。
          import static java.nio.file.StandardOpenOption.*;

          Path logfile 
          = ;

          //Convert the string to a byte array.
          String s = ;
          byte data[] = s.getBytes();

          OutputStream out 
          = null;
          try {
              out 
          = new BufferedOutputStream(logfile.newOutputStream(CREATE, APPEND));
              
              out.write(data, 
          0, data.length);
          catch (IOException x) {
              System.err.println(x);
          finally {
              
          if (out != null) {
                  out.flush();
                  out.close();
              }
          }

          使用Channel I/O來讀寫文件
          Stream I/O每次讀取一個字符,Channel I/O每次讀取一個緩沖塊的數(shù)據(jù)。ByteChannel接口提供了基本的讀寫功能。SeekableByteChannel擴展了 ByteChannel并提供了維護一個channel中的位置并改變該位置的能力。SeekableByteChannel還支持截斷文件和查詢文件大 小的功能。
          移動到文件中不同的位置,從該位置開始讀或?qū)懙哪芰κ刮覀兛梢?span onclick="tagshow(event)" class="t_tag">隨機訪問文件。有兩種形式的 newByteChannel方法可以用來讀或?qū)懳募@兩種形式和newOutputStream方法一樣。

          • newByteChannel(OpenOption...)
          • newByteChannel(Set<? extends OpenOption>, FileAttribute<?>...)

          這兩個方法都允許指定OpenOption,newOutputStream所支持的選擇這里也支持,而且這里還支持另外一個選項READ,因為 SeekableByteChannel既支持讀也支持寫。
          如果選項是READ,那么該channel就是為了讀訪問打開。如果選項是WRITE或APPEND,則該channel就是為了寫訪問打開。如果沒有指 定,該channel默認是為了讀打開。
          下面的代碼從文件中讀取內(nèi)容并輸出到控制臺上:
          SeekableByteChannel sbc = null;
          try {
              sbc 
          = file.newByteChannel();  //Defaults to READ
              ByteBuffer buf = ByteBuffer.allocate(10);

              
          //Read the bytes with the proper encoding for this platform.
              
          //If you skip this step, you might see something that looks like Chinese
              
          //characters when you expect Latin-style characters.
              String encoding = System.getProperty("file.encoding");
              
          while (sbc.read(buf) > 0) {
                  buf.rewind();
                  System.out.print(Charset.forName(encoding).decode(buf));
                  buf.flip();
              }
          catch (IOException x) {
              System.out.println(
          "caught exception: " + x);
          finally {
              
          if (sbc != null) sbc.close();
          }
          下 面的代碼是為了UNIX或其他支持POSIX的文件系統(tǒng)編寫的。這段代碼創(chuàng)建一個新的日志文件或者擴展原有的日志文件,該日志文件創(chuàng)建時指定了訪問權(quán)限 (所有者有讀寫權(quán)限,同組用戶只有讀權(quán)限,其他用戶沒有讀權(quán)限)。
          import static java.nio.file.StandardCopyOption.*;

          //Create the set of options for appending to the file.
          Set<OpenOptions> options = new HashSet<OpenOption>();
          options.add(APPEND);
          options.add(CREATE);

          //Create the custom permissions attribute.
          Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-r------");
          FileAttribute
          <Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);

          //Convert the string to a ByetBuffer.
          String s = ;
          byte data[] = s.getBytes();
          ByteBuffer bb 
          = ByteBuffer.wrap(data);

          SeekableByteChannel sbc 
          = null;
          try {
              sbc 
          = file.newByteChannel(options, attr);
              sbc.write(bb);
          catch (IOException x) {
              System.out.println(
          "exception thrown: " + x);
          finally {
              
          if (sbc != null) sbc.close();
          }
          posted @ 2010-04-05 17:30 afrag 閱讀(493) | 評論 (0)編輯 收藏

          2010年4月1日

          轉(zhuǎn)自 開發(fā)者的天空

          管理元數(shù)據(jù)(文件屬性和文件存儲屬性)
          在文件系統(tǒng)中,文件或者目錄的元數(shù)據(jù)是和文件或者目錄本身存儲在一起的,而且元數(shù)據(jù)保存了很多的信息,例如:對象是文件還是目錄,抑或是符號鏈接。文件的大小、創(chuàng)建 時間、最后修改時間、文件的所有者、組、訪問權(quán)限等。
          java.nio.file.attribute包提供了訪問和管理文件系統(tǒng)元數(shù)據(jù)(通常叫做文件屬性)的功能。不同的文件系統(tǒng)提供的文件屬性是不一樣 的,所以我們按照這個將文件的屬性劃分成了不同的視圖(View)。每個View對應一個文件系統(tǒng)的實現(xiàn),如POSIX(Unix使用的文件系統(tǒng))或 DOS;或者是所有文件系統(tǒng)共有的屬性,如文件的所有權(quán)。當我們讀取文件的屬性的時候,是一次讀取整個視圖的屬性的。Java所支持的視圖有:
          BasicFileAttributeView – 所有的文件系統(tǒng)實現(xiàn)都必須提供的屬性的視圖。
          DosFileAttributeView – 擴展了BasicFileAttributeView,添加了DOS文件系統(tǒng)能夠支持的幾種屬性。
          PosixFileAttributeView – 擴展了BasicFileAttributeView,添加了POSIX文件系統(tǒng)能夠支持的幾種屬性。
          FileOwnerAttributeView – 任何文件系統(tǒng)實現(xiàn)都會支持文件所有者的屬性。這個View就包含這個屬性。
          AclFileAttributeView – 支持讀取和更新文件的訪問控制列表。支持NFSv4訪問控制列表模型。所有定義了到NFSv4的映射的訪問控制列表模型也同樣支持,如Windows的訪 問控制列表模型。
          UserDefinedFileAttributeView – 支持用戶自定義的元數(shù)據(jù)。這個View可以被映射到文件系統(tǒng)提供的擴展機制。例如在Solaris操作系統(tǒng)上,可以將這個View存儲MIMEtype。
          不同的文件系統(tǒng)可能支持不同的一個或幾個view,也有可能含有上面所有的View都沒有包含的文件屬性。
          Attributes類
          大多數(shù)情況下,我們不需要直接使用FileAttributeView接口,Attributes類提供了轉(zhuǎn)換的方法來讀取和設置文件屬性。
          下面是Attributes類提供的一些方法:
          讀取或設置基本的文件屬性:
          readBasicFileAttributes(FileRef, LinkOption...)
          setLastAccessTime(FileRef, FileTime)
          setLastModifiedTime(FileRef, FileTime)

          讀取或設置POSIX文件屬性
          readPosixFileAttributes(FileRef, LinkOption...)
          setPosixFilePermissions(FileRef, Set<PosixFilePermission>)

          讀取或設置文件的所有者
          getOwner(FileRef)
          setOwner(FileRef, UserPrincipal)

          一次讀取所有的文件屬性
          readAttributes(FileRef, String, LinkOption...)

          讀取或設定特定的文件屬性
          getAttribute(FileRef, String, LinkOption...)
          setAttribute(FileRef, String, Object)

          讀取DOS文件屬性
          readDosFileAttributes(FileRef, LinkOption...)

          讀取或設置文件的訪問控制列表。
          getAcl(FileRef)
          setAcl(FileRef, List<AclEntry>)

          讀取文件存儲空間的屬性,如總空間、有效空間、未分配空間等。
          readFileStoreSpaceAttributes(FileStore)

          每個read方法都返回一個對象,該對象會提供訪問方法,我們通過這些訪問方法能夠很方便的獲得特定的文件屬性的值。
          要想讀取基本的文件信息,那么可以調(diào)用readBasicFileAttributes(FileRef, LinkOption...)方法。這個方法支持的LinkOption就只有NOFOLLOW_LINKS。這個方法會一次性的讀取所有的基本的文件屬 性并返回一個BasicFileAttributes對象,我們可以訪問該對象獲取具體的文件屬性。如果程序?qū)ξ募]有訪問權(quán)限,該方法會拋出 SecurityException異常。要注意的是,并不是所有文件系統(tǒng)的實現(xiàn)都支持創(chuàng)建時間、最后修改時間和最后訪問時間這三個屬性。如果某個屬性不 被支持,則調(diào)用該屬性的get方法時會返回null。下面就是一個讀取文件的基本屬性的例子:
          Path file = ;
          BasicFileAttributes attr 
          = Attributes.readBasicFileAttributes(file);

          if (attr.creationTime() != null) {
              System.out.println(
          "creationTime: " + attr.creationTime());
          }
          if (attr.lastAccessTime() != null) {
              System.out.println(
          "lastAccessTime: " + attr.lastAccessTime());
          }
          if (attr.lastModifiedTime() != null) {
              System.out.println(
          "lastModifiedTime: " + attr.lastModifiedTime());
          }

          System.out.println(
          "isDirectory: " + attr.isDirectory());
          System.out.println(
          "isOther: " + attr.isOther());
          System.out.println(
          "isRegularFile: " + attr.isRegularFile());
          System.out.println(
          "isSymbolicLink: " + attr.isSymbolicLink());
          System.out.println(
          "size: " + attr.size());
          下面的例子中,我們檢查了對一個文件的訪問權(quán)限,判斷 該文件是常規(guī)的文件還是目錄:
             import static java.nio.file.AccessMode.*;
            

             Path file 
          = ;
             
          boolean error=false;
            

             
          try {
                 file.checkAccess(READ, EXECUTE);
                 
          if (!Attributes.readBasicFileAttributes(file).isRegularFile()) {
                     error 
          = true;
                 }
             } 
          catch (IOException x) {
                 
          //Logic for error condition
                 error = true;
             }
             
          if (error) {
                 
          //Logic for failure
                 return;
             }
             
          //Logic for executable file

          設置 時間戳

          前面的文件基本屬性的代碼中演示了怎樣獲取文件的時間戳,Attributes類還提供了兩個方法來設置時間戳:setLastAccessTime和 setLastModifiedTime,下面是這兩個方法的示例:
          Path file = ;
          BasicFileAttributes attr 
          = Attributes.readBasicFileAttributes(file);
          long currentTime = System.currentTimeMillis();
          if (attr.lastModifiedTime() != null) {
              FileTime ft 
          = FileTime.fromMillis(currentTime);
              Attributes.setLastModifiedTime(file, ft);
          else {
              System.err.println(
          "lastModifiedTime time stamp not supported");
          }

          DOS的文件屬性
          要獲取一個文件的DOS的文件屬性,需要調(diào)用readDosFileAttributes方法。這個方法會返回一個DosFileAttributes對 象,該對象提供了獲取DOS文件屬性的方法,例如:
          Path file = ;
          try {
              DosFileAttributes attr 
          = Attributes.readDosFileAttributes(file);
              System.out.println(
          "isReadOnly is " + attr.isReadOnly());
              System.out.println(
          "isHidden is " + attr.isHidden());
              System.out.println(
          "isArchive is " + attr.isArchive());
              System.out.println(
          "isSystem is " + attr.isSystem());
          catch (IOException x) {
              System.err.println(
          "DOS file attributes not supported:" + x);
          }


          我 們可以使用setAttribute方法來設置DOS文件屬性,如:
          Path file = ;
          Attributes.setAttribute(file, 
          "dos:hidden"true);

          要注意的是,不是只有DOS操作系統(tǒng)才支持DOS文 件屬性,有些操作系統(tǒng)如Samba也支持DOS文件屬性。
          POSIX的文件屬性
          POSIX是Portable Operation System Interface for UNIX的縮寫,而且IEEE和ISO定義很多標準來保證不同的UNIX之間的戶操作性,因此對于開發(fā)人員來說,針對POSIX編寫的程序能夠很容易的運 行在不同的兼容POSIX的文件系統(tǒng)上。
          要讀取POSIX文件屬性,需要調(diào)用readPosixFileAttributes方法。除了文件所有者和所屬組,POSIX還支持9種文件權(quán)限許可組 合:讀、寫、執(zhí)行三種權(quán)限和文件所有者、同組的用戶和其他用戶三種角色的組合(3 × 3 = 9)。下面就是讀取POSIX文件屬性的簡單的例子:
          Path file = ;
          PosixFileAttributes attr 
          = Attributes.readPosixFileAttributes(file);
          System.out.format(
          "%s %s %s%n", attr.owner().getName, attr.group().getName(),
                            PosixFilePermissions.toString(attr.permissions()));

          下面的代碼讀取了一個文件的屬性,然后創(chuàng)建了一個新的 文件,將原有的文件的權(quán)限屬性賦予新創(chuàng)建的文件:

          Path sourceFile = ;
          Path newFile 
          = ;
          PosixFileAttributes attrs 
          = Attributes.readPosixFileAttributes(sourceFile);
          FileAttribute
          <Set<PosixFilePermission>> attr =
                    PosixFilePermissions.asFileAttribute(attrs.permissions());
          try {
              file.createFile(attr);
          catch (IOException x) {
              
          //unable to create the file
          }
          上 面的代碼中我們使用了PosixFilePermission類,該類是一個幫助類,提供了一些方法來讀取和生成文件權(quán)限,這里就不詳細解釋了。
          如果想指定創(chuàng)建的文件的權(quán)限,可以使用下面的代碼:
          Path file = ;
          Set
          <PosixFilePermission> perms = PosixFilePermissions.fromString("rw-------");
          FileAttribute
          <Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);
          try {
              Attributes.setPosixFilePermissions(file, perms);
          catch (IOException x) {
              System.err.println(x);
          }
          文 件有所有者的屬性和所屬組的屬性,在設置這些屬性的時候,我們需要傳入一個UserPrincipal對象作為參數(shù),我們可以使用 UserPrincipalLookupService來根據(jù)用戶名或組名來創(chuàng)建該對象。UserPrincipalLookupService實例可以 通過FileSystem.getUserPrincipalLookupService方法獲得。下面就是設置所有者屬性的例子:
          Path file = ;
          try {
              UserPrincipal owner 
          = file.GetFileSystem().getUserPrincipalLookupService()
                                    .lookupPrincipalByName(
          "sally");
              Attributes.setOwner(file, owner);
          catch (IOException x) {
              System.err.println(x);
          }
          Attributes 類沒有提供設置所屬組的方法,如果要設置所屬組,需要調(diào)用POSIX文件屬性視圖來進行,下面是示例代碼:
          Path file = ;
          try {
              GroupPrincipal group 
          = file.getFileSystem().getUserPrincipalLookupService()
                                    .lookupPrincipalByGroupName(
          "green");
              file.getFileAttributeView(PosixFileAttributeView.
          class).setGroup(group);
          catch (IOException x) {
              System.err.println(x);
          }

          用戶定義的文件屬性
          如果文件系統(tǒng)支持的屬性對你來說還不夠用,你可以通過UserDefinedAttributeView來創(chuàng)建和跟蹤自己的文件屬性。
          下面的例子中,我們將MIME類型作為一個用戶自定義的屬性:
          Path file = ;
          UserDefinedFileAttributeView view 
          = file
              .getFileAttributeView(UserDefinedFileAttributeView.
          class);
          view.write(
          "user.mimetype", Charset.defaultCharset().encode("text/html");
          要讀取MIME類型屬性,要使用以下的代碼:
          Path file = ;
          UserDefinedFileAttributeView view 
          = file
              .getFileAttributeView(UserDefinedFileAttributeView.
          class);
          String name 
          = "user.mimetype";
          ByteBuffer buf 
          = ByteBuffer.allocate(view.size(name));
          view.read(name, buf);
          buf.flip();
          String value 
          = Charset.defaultCharset().decode(buf).toString();
          如果文件系統(tǒng)不支持擴展屬性,那么會拋出一個 UnsupportedOperationException異常,你可以咨詢系統(tǒng)管理員來確認系統(tǒng)是否支持文件的擴展屬性并進行相應的配置。

          文件存儲屬性
          文件存儲屬性其實我們應該非常熟悉的屬性,我們查看硬盤屬性的時候,經(jīng)常看到硬盤總的存儲空間,使用了的存儲空間,空閑的存儲空間等就是文件存儲屬性。下 面是獲取文件存儲屬性的代碼:
          Path file = ;
          FileStore store 
          = file.getFileStore();
          FileStoreSpaceAttributes attr 
          = Attributes.readFileStoreSpaceAttributes(store);

          System.out.println(
          "total: " + attr.totalSpace() );
          System.out.println(
          "used:  " + (attr.totalSpace() - attr.unallocatedSpace()) );
          System.out.println(
          "avail: " + attr.usableSpace() );

          posted @ 2010-04-01 10:49 afrag 閱讀(375) | 評論 (0)編輯 收藏

          2010年3月30日

          轉(zhuǎn)自開發(fā)者的天空

          刪除操作

          通過Path類,我們可以刪除文件、目錄或符號鏈接。要注意的是當我們刪除符號鏈接時,其指向的目的目錄或文件不會被刪除。當要刪除一個目錄時,該目錄必須為空,否則會失敗。

          Path類提供了兩個刪除方法。第一個是delete方法。Delete方法會直接刪除文件或目錄,如果刪除失敗則會拋出異常。例如如果要刪除的文件不存在,則會拋出NoSuchFileException。程序員可以catch這些異常并進行相應的處理。

          try {
              path.delete();
          catch (NoSuchFileException x) {
              System.err.format(
          "%s: no such file or directory%n", path);
          catch (DirectoryNotEmptyException x) {
              System.err.format(
          "%s not empty%n", path);
          catch (IOException x) {
              //File permission problems are caught here.
              System.err.println(x);
          }


          另外一個方法是deleteIfExists。這個方法同樣會刪除文件或目錄,和delete方法唯一不同的是如果文件不存在,這個方法不會拋出異常。


          拷貝操作

          Path類提供了拷貝文件或目錄的方法,就是copyTo方法。(以前要copy文件只能夠自己寫程序完成哦!)。在進行拷貝的時候,我們可以指定如果目標文件或目錄已經(jīng)存在時怎么處理;如果設置了REPLACE_EXISTING,則會覆蓋已有的文件或目錄;如果沒有設置 REPLACE_EXISTING,那么拷貝操作會失敗。

          要注意的是拷貝目錄時,目錄中的內(nèi)容并沒有被拷貝過去,新生成的目錄會是一個空目錄。要想將目錄中的內(nèi)容一起拷貝過去,只有自己編程了。

          在拷貝符號鏈接時,默認的行為是拷貝符號鏈接指向的目的文件或目錄。如果需要拷貝符號鏈接本身,需要指定NOFOLLOW_LINKS REPLACE_EXISTING選項。

          CopyTo方法接受CopyOption類型的varargsCopyOption是一個接口,目前有兩個實現(xiàn)類:StandardCopyOptionLinkOptionCopyTo方法能夠支持的選項有:

          * REPLACE_EXISTING – 當要拷貝的是文件是,如果目標文件已經(jīng)存在,則覆蓋目標文件。如果要拷貝的是目錄,當目標目錄已經(jīng)存在時,如果目標目錄為空,覆蓋目標目錄;如果目標目錄不為空,拋出FileAlreadyExistsException。如果要拷貝的是符號鏈接,那么拷貝符號鏈接本身。

          * COPY_ATTRIBUTES – 連文件或目錄的屬性一起拷貝。不同的文件系統(tǒng)和平臺支持不同的文件屬性,但是所有的文件系統(tǒng)和平臺都支持最后修改時間這個屬性。

          * NOFOLLOW_LINKS – 如果要拷貝的是符號鏈接,直接拷貝符號鏈接本身。

          下面是使用copyTo的代碼例子:

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

          try {
              path.copyTo(newPath, REPLACE_EXISTING,     COPY_ATTRIBUTES);
          catch (IOException x) {
              
          //Logic for error condition
              System.err.println(x);
              
          return;
          }


          移動操作

          Path還提供了moveTo方法來移動文件或目錄。如果沒有設置REPLACE_EXISTING選項,那么當目標文件或目錄存在時,操作會失敗。

          空目錄能夠被移動,但是如果目錄不為空,是否能夠移動目錄要取決于是否能夠不移動目錄的內(nèi)容。例如在Windows系統(tǒng)下,如果是同一個硬盤分區(qū)內(nèi)的移動,就可以成功,但是如果是不同硬盤分區(qū)之間的移動,就會失敗,會拋出FileSystemException異常。同時要注意的是,目的目錄的父目錄一定要存在,否則會拋出NoSuchFileException。例如將c:"temp"test移動到c:"save"test,如果c:"save目錄不存在,則會拋出異常。

          MoveTo方法也接受可變數(shù)量的參數(shù),其支持的選項有:

          REPLACE_EXISTING – 覆蓋已經(jīng)存在的文件或目錄。如果目標文件/目錄是一個符號鏈接,那么該鏈接會被覆蓋,但是起指向的文件或目錄不會受到影響。 * ATOMIC_MOVE – 移動操作是一個原子操作。如果文件系統(tǒng)不支持移動的原子操作,會拋出異常。原子操作能夠保證當你移動一個文件到一個目錄中時,監(jiān)視該目錄的進程得到的是一個完整的文件。

          下面是使用moveTo方法的例子

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

          try {
              path.moveTo(newPath, REPLACE_EXISTING);
          catch (IOException x) {
              
          // Logic for error condition
              System.err.println(x);
              
          return;
          }


          posted @ 2010-03-30 10:32 afrag 閱讀(422) | 評論 (0)編輯 收藏

          2010年3月29日

          轉(zhuǎn)自開發(fā)者的天空

          Path類提供了很多方法來對文件和目錄進行讀、寫和其他的操作。在看這些方法之前,我們先需要了解一些其他的概念:

          Varargs實際上是Variable number of arguments的縮寫,也就是可變數(shù)目的參數(shù)。例如在下面的方法聲明中,CopyOption參數(shù)后面的省略號表明這個方法接受可變個數(shù)的參數(shù)。
                  Path moveTo(Path, CopyOption...)
          當一個方法可以接受可變數(shù)目的參數(shù)時,你可以傳入以逗號分隔的多個參數(shù),或者傳入一個數(shù)組。
          對于上面的moveTo方法,可以這樣調(diào)用:
          import static java.nio.file.StandardCopyOption.*;

                  Path orig 
          = ;
                  Path 
          new = ;
                  orig.moveTo(
          new, REPLACE_EXISTING, ATOMIC_MOVE);


          Path的很多方法在文件系統(tǒng)上執(zhí)行的操作都是原子操作,例如moveTo方法。原子操作是指不會被中斷或不會部分執(zhí)行的操作。操作要么是完全成功,要么是完全失敗。當有多個進程操作同文件系統(tǒng)的相同的區(qū)域的時候這一點就很重要。


          很多的文件I/O方法支持方法鏈的概念。
          調(diào)用第一個方法會返回一個對象,我們可以直接調(diào)用這個對象的方法,這個方法依然返回一個對象,我們又可以直接調(diào)用該對象的方法,就這樣持續(xù)下去。例如:
                  String value = Charset.defaultCharset().decode(buf).toString();
                  UserPrincipal group = file.getFileSystem().getUserPrincipalLookupService().lookupPrincipalByName("me");
          這個技術能夠使我們編寫更加緊湊的代碼,避免聲明一些我們不需要的臨時變量。


          Path類實現(xiàn)了FileRef接口。FileRef接口包含了定位文件和訪問文件的方法。


          Path類有兩個方法能夠接受帶模式匹配的參數(shù)。下面是這種參數(shù)的規(guī)則:
          星號*匹配任意數(shù)目的字符(也可能是沒有)
          兩個星號**同樣是代表任意數(shù)目的字符,不同的是這個匹配可以穿越目錄邊界。例如 c:"a**"bar可以匹配c:"abc"bar,也可以匹配c:"am"cn"bar。
          問號?匹配一個字符
          花括號{}表明子模式的集合,例如{sun,moon,stars}可以匹配'sun','moon'或‘stars’;{temp*,tmp*}可以匹配以temp或tmp開始的任意字符串。
          要匹配*,?或其他的特殊字符,可以使用轉(zhuǎn)義符"。例如""匹配單個的","?匹配問號。
          方括號[]表示一組單獨的字符,當使用了-的時候,也代表一個范圍的字符,例如:
          [aeiou]匹配任何單獨的元音字符,[0-9]匹配任意數(shù)字,[A-Z]匹配任意大寫字母,[a-z,A-Z]匹配任意大寫或小寫字母。在方括號中,星號、問號和"都只是表示它們自身,不再作為特殊符號。
          下面是一些例子:
          *.html匹配所有以.html結(jié)尾的字符串。
          ???匹配所有長度為3的字符串
          *[0-9]*匹配所有包含有數(shù)字的字符串
          *.{html,htm,pdf}匹配所有以.html,.html或.pdf結(jié)尾的字符串
          a?*.java匹配所有以a開頭,后面跟至少一個字符,然后以.java結(jié)尾的字符串。
          {foo*,*[0-9]*}匹配以foo開頭的字符串或包含有數(shù)字的字符串。
          關于參數(shù)中的模式的使用,請參考FileSystem類的getPathMatcher方法的幫助文檔。
          如果這種模式匹配仍然不能夠滿足需要,我們還可以使用正則表達式。



          Path會指向文件或者目錄,但是我們還不能確定這個文件或者目錄是否存在,是否可讀,是否可寫,是否可以執(zhí)行。要確定文件/目錄是否存在以及程序是否可以訪問該文件/目錄,可以使用checkAccess(AccessMode...)方法。可選的AccessMode有:
              * READ – 檢查文件/目錄是否存在以及程序是否有權(quán)限讀該文件/目錄
              * WRITE – 檢查文件/目錄是否存在以及程序是否有權(quán)限寫該文件/目錄
              * EXECUTE – 檢查文件/目錄是否存在以及程序在該文件/目錄上是否有執(zhí)行權(quán)限
          如果調(diào)用checkAccess的時候沒有傳入任何參數(shù),該方法只是檢查文件是否存在。
          下面的例子演示了怎樣驗證文件是否存在以及程序是否有讀和執(zhí)行的權(quán)限。
          import static java.nio.file.AccessMode.*;
                
              Path file = ...;
              try {
                  file.checkAccess(READ, EXECUTE);
              } catch (IOException x) {
                  //Logic for error condition...
                  return;
              }

              //Logic for executable file...
          需要注意的是,當checkAccess執(zhí)行完之后,文件的權(quán)限可能被其他的用戶(例如系統(tǒng)管理員)修改。這實際上是很多應用程序都有的安全性的問題。如果你感興趣,可以搜索TOCTTOU (time of check to time of use)。


          當文件系統(tǒng)中存在符號鏈接的時候,可能兩個不同的路徑會指向同一個文件或目錄。方法isSamePath會比較兩個Path來檢查它們是否指向同一個文件/目錄。
              Path p1 = ...;
              Path p2 = ...;

              try {
                  if (p1.isSameFile(p2)) {
                      //Logic when the paths locate the same file
                  }
              } catch (IOException x) {
                  //Logic for error condition...
                  return;
              }
          posted @ 2010-03-29 10:02 afrag 閱讀(236) | 評論 (0)編輯 收藏

          2010年3月27日

          轉(zhuǎn)自開發(fā)者的天空
          在上面的一篇文章中,我們已經(jīng)說過了Path類的操作主要有兩種:對路徑的操作和對文件的操 作。這篇文章中我們就來了解一下對路徑的操作。
          創(chuàng)建Path實例
          Path實例包含了指定文件或目錄位置的信息,在實例化Path類時,需要指定一個或多個目錄或文件名。路徑的根目錄不是必須的;路徑信息可能僅僅是一個 目錄或文件的名稱。
          最簡單的創(chuàng)建Path實例的方式就是使用Paths(注意這里有一個s)類的get方法:
          Path p1 = Paths.get("/tmp/foo");
          Path p2 
          = Paths.get(args[0]);
          Path p3 
          = Paths.get("file:///Users/joe/FileTest.java");

          Path類接受String或URI作為參數(shù)。

          獲取路徑信息
          前面我們已經(jīng)說過了,F(xiàn)ile System一般是樹形結(jié)構(gòu),因此我們可以把Path理解為按順序存儲的一系列的名稱(目錄名稱和文件名稱)。目錄結(jié)構(gòu)中最高一層的目錄名就是序列中 index為0的那一個,目錄結(jié)構(gòu)中最低一層的目錄名或者文件名就是序列中index為n-1的那一個(這里n是路徑中層次的數(shù)目)。Path類提供方法 來通過index獲取序列中的一個元素或一個子序列。
          隨后的例子中我們使用的目錄結(jié)構(gòu)如下圖:
          io-dirStructure.JPG

              下面的代碼定義了一個Path對象并獲取其中的信息。要注意的是這些代碼中除了isHidden方法外,其他的方法并不需要指定的目錄或文件存在;如果不 存在,isHidden方法會拋出異常。
          Path path = Paths.get("C:\\home\\joe\\foo");    // Microsoft Windows syntax
          //Path path = Paths.get("/home/joe/foo");    // Solaris syntax
          System.out.format("toString: %s%n", path.toString());
          System.out.format(
          "getName: %s%n", path.getName());
          System.out.format(
          "getName(0): %s%n", path.getName(0));
          System.out.format(
          "getNameCount: %d%n", path.getNameCount());
          System.out.format(
          "subpath(0,2): %d%n", path.subpath(0,2));
          System.out.format(
          "getParent: %s%n", path.getParent());
          System.out.format(
          "getRoot: %s%n", path.getRoot());
          System.out.format(
          "isHidden: %s%n", path.isHidden());

          下面是這段代碼的輸出情況
          方法 Solaris下的輸出 Windows下的 輸出 備注
          toString /home/joe/foo C:\home\joe\foo
          getName foo foo 獲 取名稱序列中的最后一個,也就是最底層的目錄或文件名
          getName(0) home home 獲 取名稱序列中的第一個,也就是最靠近根目錄的那一層。注意根目錄不在名稱序列中
          getNameCount 3 3 獲 取名稱序列的元素個數(shù)
          subpath(0,2) home/joe home\joe 獲 取從指定的開始點到指定的結(jié)束點的子路徑。注意這里包括開始點,但不包括結(jié)束點。
          getParent /home/joe \home\joe 返 回Path指定的目錄或文件的父目錄
          getRoot / C:\ 返 回根目錄
          isHidden false false 如果文件是 隱藏文件,或者目錄是隱藏目錄,返回true。因為要訪問文件的屬性,所以如果Path指定的目錄或者文件不存在,會拋出異常。


          上面的代碼中我們創(chuàng)建Path時使用的是絕對路徑,下面我們來看看創(chuàng)建路徑時使用相對路徑時,這段代碼的執(zhí)行結(jié)果
                  //Path path = Paths.get("sally/bar");     // Solaris syntax
                  Path path = Paths.get("sally\\bar");    // Microsoft Windows syntax

          大 家可以自行去實驗一下具體的輸出是什么。

          去除Path中的冗余
          在很多文件系統(tǒng)中我們使用'.'來代表當前目錄,使用'..'代表父目錄。在有些情況下我們創(chuàng)建的路徑中會有冗余的路徑信息,例如:
                  /home/./joe/foo
                  /home/sally/../joe/foo
          方法normalize會去除這些冗余信息,包括'.'或'directory/..'。上面的兩個例子在去除冗余信息后都是/home/joe /foo。
          要注意的是normalize方法并不去檢查文件系統(tǒng),它只是簡單的進行語法操作。在第二個例子中,如果sally是一個指向其他的目錄的符號鏈接,那么 去除了sally/..后可能導致Path不在指向原來的文件或目錄。
          如果你需要清除冗余信息,又要保證結(jié)果仍然指向正確的文件或目錄,可以使用toRealPath方法。在下面我們會講到這個方法。
          轉(zhuǎn)換Path
          有3個方法用來轉(zhuǎn)換Path。
          • toUri方法
            如果你需要將Path轉(zhuǎn)換為可以在瀏覽器中打開的字符串格式,可以使用toUri方法,例如:
                  Path p1 = Paths.get("/home/logfile");
                  System.out.format(
          "%s%n", p1.toUri());  // 結(jié)果是 file:///home/logfile
          注意在這里即使/home/logfile'指向的目錄或文件不存在,這段代碼同樣能夠執(zhí)行成功。
          • toAbsolutePath 方法
            該方法將路徑轉(zhuǎn)換為絕對路徑。如果原來的Path已經(jīng)是絕對路徑,該方法直接返回原有的Path對象。
            我們來看看下面的例子:
                            Path path = Paths.get("home\\joe\\foo");
                            Path absolutePath 
            = path.toAbsolutePath();
                            System.out.println(path 
            == absolutePath); //結(jié)果是false
                            
                            Path path2 
            = Paths.get("c:\\home\\joe\\foo ");
                            Path absolutePath2 
            = path2.toAbsolutePath();
                            System.out.println(path2 
            == absolutePath2);//結(jié)果是true
          同樣的,toAbsolutePath方法并不需要 Path所指向的文件或目錄存在。
          • toRealPath方法
            這個方法會返回一個已經(jīng)存在的文件或目錄的真實路徑(如果文件或目錄不存在或無法訪問,該方法會拋出異常)。該方法會執(zhí)行以下的操作:
            如果傳入的參數(shù)是true并且文件系統(tǒng)支持符號鏈接,則解析路徑中存在的符號鏈接(如果有的話)。
            如果原來的Path是相對路徑,將其轉(zhuǎn)換成絕對路徑。
            如果路徑中含有冗余信息,返回的Path中這些冗余信息會被去除。

          連接兩個Path
          可以使用resolve方法來將兩個Path連接起來。該方法的參數(shù)是一個字符串。如果該字符串代表的是一個相對路徑,那么這個路徑會被擴展到原來的路徑 后。如果傳入的字符串是一個絕對路徑,那么返回的值就是傳入的這個絕對路徑。例如:
                  Path p1 = Paths.get("C:\\home\\joe\\foo");    
                  System.out.format(
          "%s%n", p1.resolve("bar")); // 結(jié)果是 C:\home\joe\foo\bar

                  Paths.get(
          "foo").resolve("c:\\home\joe");       // 結(jié)果是  C:\home\joe


          創(chuàng)建兩個路徑之間的路徑
          這個功能說起來有些繞口,實際的功能就是創(chuàng)建兩個指定的目錄或文件之間的相對路徑。例如:
                  Path p1 = Paths.get("joe/foo");
                  Path p2 
          = Paths.get("sally");
          在這個例子中,由于兩個路徑都是相對路徑,沒有其他的 信息,我們會認為這兩個joe和sally是同一級的兄弟目錄,因此有以下的結(jié)果

                  Path p1_to_p2 = p1.relativize(p2);   // 結(jié)果是 ../../sally
                  Path p2_to_p1 = p2.relativize(p1);   // 結(jié)果是 ../joe/foo
          讓我們看看另外一個例子
                  Path p1 = Paths.get("home");
                  Path p3 
          = Paths.get("home/sally/bar");
                  Path p1_to_p3 
          = p1.relativize(p3);  // 結(jié)果是 sally/bar
                  Path p3_to_p1 = p3.relativize(p1);  // 結(jié)果是 ../..
          在這個例子中,兩個路徑共享同一個節(jié)點-home, 所以結(jié)果并不是../home/sally/bar和../../../home.
          如果兩個路徑中有一個是絕對路徑,另外一個是相對路徑,relative方法會拋出異常。如果兩個路徑都是絕對路徑,那么relative方法的行為和系 統(tǒng)相關,不同的系統(tǒng)可能不同。
          我在Windows操作系統(tǒng)下實驗了一下,如果兩個路徑屬于同一個硬盤,那么可以執(zhí)行成功,否則會拋出異常。
          Path path1 = Paths.get("c:\\abcd\\efg");
          Path path2 
          = Paths.get("c:\\temp");
          System.out.println(path1.relativize(path2));        
          //結(jié)果是..\..\temp
          System.out.println(path2.relativize(path1));        //結(jié)果是..\abcd\efg

          Path path3 
          = Paths.get("c:\\abcd\\efg");
          Path path4 
          = Paths.get("d:\\temp");
          System.out.println(path3.relativize(path4));        
          //拋出異常


          Path 的比較
          Path提供equals方法來檢查兩個Path是否相等。但是這里 要注意的是比較的并不是兩個Path是否指向同一個目錄或者文件。請看下面的例子:
          Path path1 = Paths.get("abcd\\123");
          Path path2 
          = Paths.get("abcd\\123");
          Path path3 
          = Paths.get("abcd\\.\\123");
          System.out.println(path1.equals(path2));        
          //true
          System.out.println(path1.equals(path3));        //false
          System.out.println(path1.equals(path3.normalize())); //true
          System.out.println(path1.equals(path1.toAbsolutePath()));        //false

          Path 類還提供了startsWith和endsWith方法,這兩個方法用來檢查路徑是否以指定的字符串開始或者結(jié)束,例如:
                  Path path = ;
                  Path otherPath 
          = ;
                  Path beginning 
          = Paths.get("/home");
                  Path ending 
          = Paths.get("foo");

                  
          if (path.equals(otherPath)) {
                      
          //equality logic here
                  } else if (path.startsWith(beginning)) {
                      
          //path begins with "/home"
                  } else if (path.endsWith(ending)) {
                      
          //path ends with "foo"
                  }

          Path類實現(xiàn)了Iterable接口,iterator方法會返回一個Iterator對象,該對象中的第一個元素就是原 路徑中最上層(最靠近根節(jié)點)的目錄。下面是使用這個方法的例子:
                  Path path = ;
                  
          for (Path name: path) {
                      System.out.println(name);
                  }

          Path類還實現(xiàn)了Comparable接口,因此可以使用compareTo來比較兩個Path。比較的算法和結(jié)果是和文 件系統(tǒng)的提供者和系統(tǒng)平臺相關的。大家在使用之前,最后先實驗一下。
          Path類還提供了一個方法isSameFile來檢查兩個Path是否指向同一個目錄或文件。如果作為參數(shù)的Path為null,那么會直接返回 false,不會去檢查Path指向的文件是否存在。如果兩Path來自不同的文件系統(tǒng)提供者,那么也會直接返回false,不會去檢查文件或目錄是否存 在。如果兩個Path執(zhí)行equals方法的返回結(jié)果為true,那么這個方法直接返回true,也不會去檢查文件或目錄是否存在。其他的情況下是否會去 打開或訪問Path指向的文件或目錄是與具體的實現(xiàn)相關的,也就是說不同的JDK/JRE可能會有不同的行為。
          驗證文件或目錄是否存在
          上面所介紹的很多方法都不會去驗證Path指向的文件或目錄是否存在,只是操作Path實例自身。但是在有些情況下,你 需要訪問文件系統(tǒng)來驗證文件、目錄存在與否,這時你可以使用exists和notExists方法。需要注意的是!path.exists()并不等于 path.notExists()。當你調(diào)用這兩個方法時,有以下3中情況:
          • 文件或者目錄被證實存在
          • 文件或者目錄被證實不存在
          • 不知道文件或目錄是否存在。當程序沒有訪問這個文 件或目錄的權(quán)限的時候這個情況會發(fā)生。

          如果exists()和notExists()都返回false,說明無法驗證該文件是否存在。

          在下面一篇文章中,我們會介紹怎樣進行文件的操作。
          posted @ 2010-03-27 22:45 afrag 閱讀(299) | 評論 (0)編輯 收藏

          2010年3月25日

          轉(zhuǎn)載自開發(fā)者的天空
          1. Path的概念

          文件系統(tǒng)會把文件進行組織并存放在媒介上,通常是一個或多個硬盤上。目前使用的大多數(shù)的文件系統(tǒng)是以樹形的方式來存儲文件的。在樹的頂端是一個(或多個) 根節(jié)點,在根節(jié)點之下是文件和目錄,目錄下又可以包含文件和目錄。理論上可以這樣一層層的一直嵌套下去(當然實際中是不可能的,例如Windows系統(tǒng)對 路徑的長度有限制)。
          下面的圖中展示了一個包含一個根節(jié)點的目錄樹。(在Windows系統(tǒng)中支持多個根節(jié)點,例如C:\和D:\分別是一個根節(jié)點。)
          io-dirStructure.JPG
          Path能夠唯一的標識文件系統(tǒng)中的某一個文件。例如上面圖中的statusReport文件在Windows系統(tǒng)中就可以使用以下的Path來標識:
          c:\home\sally\statusReport
          在solaris系統(tǒng)中,其path為
          /home/sally/statusReport.
          Path中的分隔符在不同的文件系統(tǒng)中是不同的,例如在Windows系統(tǒng)中使用\,在Solaris系統(tǒng)中使用/。
          Path又可以分為絕對路徑和相對路徑。絕對路徑總是含有根節(jié)點和用來定位文件的完整的目錄列表。例如/home/sally/statusReport 就是絕對路徑。相對路徑需要和另外的路徑結(jié)合在一起才能夠確定一個文件。例如加哦加哦哦joe/foo就是一個相對路徑,如果沒有其他的信息,程序就沒有 辦法定位這個文件。我們必須說這個是相對/home的相對路徑,這樣我們才能夠找到它。
          除了我們熟悉的目錄和文件之外,有一些文件系統(tǒng)中還支持符號鏈接(symbolic link),也稱為symlink或soft link。一個符號鏈接是一個特殊的文件,它實際上是另外一個鏈接的引用。在大多數(shù)情況下符號鏈接對應用程序是透明的,對符號鏈接的操作會自動的重定向到 鏈接所指向的目的地,除非操作是刪除這個符號鏈接、重命名這個符號鏈接或修改符號鏈接的目的地。
          在下面的圖中,logFile對于用戶來說就是一個常規(guī)的文件,但是實際上是一個符號鏈接,鏈接到dir/logs/HomeLogFile文件。 HomeLogFile是這個鏈接的目的地。
          io-symlink.jpg
          不恰當?shù)氖褂梅栨溄訒е卵h(huán)引用,例如目錄A是一個符號鏈接,指向目錄B,目錄B下有一個子目錄是符號鏈接,指向目錄A的父目錄。這樣,當程序企圖遞 歸的遍歷整個目錄樹時,就會出問題。幸運的是,這個問題已經(jīng)被發(fā)現(xiàn)了,并且不會導致程序的死循環(huán)。


          2.Path類
          Path類是JDK7新引入的一個類,該類是java.io.file包的基石。
          和類的名稱所展示的一樣,Path類就是文件系統(tǒng)中path概念的程序表現(xiàn)。Path對象包含了文件名和目錄列表,這些信息可以用來創(chuàng)建path,并且用 來檢驗、定位和操作文件。
          Path實例是和底層操作系統(tǒng)相關的。在Solaris系統(tǒng)中,Path使用Solaris的句法(/home/joe/foo);在Window操作系 統(tǒng)中,Path會使用Window的句法(C:\home\joe\foo)。因此Path不是操作系統(tǒng)無關的。你不能夠比較一個來自Solaris文件 系統(tǒng)的Path和一個來自Windows文件系統(tǒng)的Path并期望它們相等,在目錄結(jié)構(gòu)和文件完全一樣的時候也不行。
          Path對應的文件或者目錄可以不存在。我們可以以不同的方式創(chuàng)建Path實例并操作它:擴展路徑、抽取路徑的一部分、和其他的Path比較。我們也可以 檢查Path對應的目錄或文件是否存在、創(chuàng)建文件或目錄、打開或刪除文件、修改許可權(quán)限等。
          Path類是能夠區(qū)分符號鏈接的。所有的Path的方法要么會檢測是否是符號鏈接并執(zhí)行不同的操作,或者提供了一個選擇來使用戶能夠配置當遇到符號鏈接的 時候執(zhí)行什么操作。
          Path類提供了很多易于使用的特性,Path類的方法可以分成兩類:

          • 路徑操作—返回路徑的一部分如根節(jié)點、名稱、父目錄的方法或者其他操作路徑的方法。
          • 文件操作—創(chuàng)建文件、打開文件、創(chuàng)建目錄、刪除文件、 拷貝文件等操作的方法。
          在下一篇文章中,我們會具體介紹Path類的這些方法。
          posted @ 2010-03-25 23:34 afrag 閱讀(248) | 評論 (0)編輯 收藏

          2006年1月20日

                 有同事問到在程序中怎樣知道數(shù)據(jù)庫表中那些字段是主鍵。當時不知道,晚上回來看了看JDK的文檔。

                 在使用JDBC來查詢數(shù)據(jù)庫的時候,通常的步驟是:

          1.  注冊驅(qū)動程序

          2.  獲取數(shù)據(jù)庫連接

          3.  執(zhí)行查詢語句

          4.  關閉連接。

                 在獲得數(shù)據(jù)庫連接后,就可以通過getMetaData()方法來獲取DatabaseMetaData;然后通過DatabaseMetaDatagetPrimaryKeys ()方法來獲取主鍵的信息。

                 下面是我做的示例程序,該程序在JBuilder2005oracle8i下通過:
          import java.sql.*;

          import javax.sql.*;

          public class TestJDBC {

              public TestJDBC() {

              }

           

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

                  Connection con = null;

                  Statement st = null;

                  ResultSet rst = null;

                  try{

                               //注冊數(shù)據(jù)庫驅(qū)動程序

                      Class.forName("oracle.jdbc.driver.OracleDriver");

                               //獲取數(shù)據(jù)庫連接

                      con = DriverManager.getConnection("jdbc:oracle:thin:@10.60.203.80:1521:TestDB","123","123");

                               //獲取主鍵信息

                      rst = con.getMetaData().getPrimaryKeys(null,null,"USER");

                               //打印主鍵信息

                      if (!rst.isAfterLast()) {

                          rst.next();

                          System.out.println(rst.getString("TABLE_NAME") + "  " +

                                             rst.getString("COLUMN_NAME"));

                      }

                  }

                  catch (Exception e){

                      System.out.println(e.getLocalizedMessage());

                  }

                  finally{

                      try{

                                      //關閉連接

                          if (rst != null)

                              rst.close();

                          if (con != null)

                              con.close();

                      }

                      catch (SQLException e){

                          throw e;

                      }

                  }

           

              }

          }

           

          上面的程序中,在獲取主鍵信息的時候,語句

          rst = con.getMetaData().getPrimaryKeys(null,null,"USER");

          用來獲取主鍵信息。關于該函數(shù)的詳細信息,請參閱JDK的文檔。這里要說的是,在測試中發(fā)現(xiàn)第三個參數(shù)(數(shù)據(jù)庫表名)是大小寫敏感的,如果寫成user是查不到結(jié)果的。

          posted @ 2006-01-20 10:52 afrag 閱讀(1526) | 評論 (1)編輯 收藏

          2005年11月2日

          在Spring 的AOP中,如果一個Proxy同時實現(xiàn)MethodBeforeAdvice、AfterReturningAdvice和MethodInterceptor接口,那么這三個Advice的執(zhí)行順序是什么樣的呢?
          經(jīng)過試驗,是和xml文件中的定義順序有關的。
          如果Proxy的接口實現(xiàn)定義為
          ?????
          ?????????
          ??????????? MethodBeforeAdvice
          ??????????? AfterReturningAdvice
          ??????????? MethodInterceptor
          ?????????

          ?????

          那么執(zhí)行的結(jié)果是
          MethodBeforeAdvice

          MethodInterceptor: before call

          Really method excuting

          MethodInterceptor: after call

          AfterReturningAdvice

          也就是說,執(zhí)行順序是:MethodBeforeAdvice,MethodInterceptor的調(diào)用前的部分,目標方法,MethodInterceptor的調(diào)用后的部分,AfterReturningAdvice。

          如果proxy的定義是
          ?????
          ?????????
          ??????????? MethodBeforeAdvice
          ??????????? MethodInterceptor
          ??????????? AfterReturningAdvice
          ?????????

          ?????

          執(zhí)行的結(jié)果是
          MethodBeforeAdvice

          MethodInterceptor: before call

          Really method excuting

          AfterReturningAdvice

          MethodInterceptor: after call
          也就是說,執(zhí)行的順序是:MethodBeforeAdvice,MethodInterceptor的調(diào)用前的部分,目標方法,AfterReturningAdvice,MethodInterceptor的調(diào)用后的部分。

          如果proxy的定義是
          ?????
          ?????????
          ??????????? MethodInterceptor
          ??????????? MethodBeforeAdvice
          ??????????? AfterReturningAdvice
          ?????????

          ?????

          執(zhí)行的結(jié)果是:
          MethodInterceptor: before call

          MethodBeforeAdvice

          Really method excuting

          AfterReturningAdvice

          MethodInterceptor: after call
          也就是說,執(zhí)行的順序是:MethodInterceptor的調(diào)用前的部分,MethodBeforeAdvice,目標方法,AfterReturningAdvice,MethodInterceptor的調(diào)用后的部分。
          以上的順序是在springframework 1.2.5中測試的。

          posted @ 2005-11-02 18:10 afrag 閱讀(3714) | 評論 (1)編輯 收藏

          2005年10月29日

          今天在看Spring in Action,看到了一個很有意思的例子。
          假如你編寫了一個類:

          public class ClassA{
          ??????private String fieldA;

          ??????public ClassA(){
          ?????????fieldA = "This is Class A";
          ???? }

          ??????public myPrint(){
          ????????????System.out.println(fieldA);
          ??????}
          }

          OK。按照面向?qū)ο蟮乃枷耄渌念悜摬荒軌蛐薷腃lassA的fieldA字段吧?因此無論什么時候你調(diào)用ClassA的myPrint方法,都應該打印的是“This is Class A”。
          ??????但是,實際情況并不是如此,請看下面的例子:
          import java.lang.reflect.Field;
          public class? TestChangeApp
          {
          ????public static void main(String[] args)
          ????{
          ????????System.out.println("Begin to test change.");
          ????????ClassA test = new ClassA();
          ????????test.myPrint();

          ????????Field[] fields = test.getClass().getDeclaredFields();
          ??
          ????????try
          ????????{
          ????????????for (int i=0;i????????????{
          ??????????????? if (fields[i].getType().equals(java.lang.String.class)){
          ???????????????????fields[i].setAccessible(true);
          ???????????????????fields[i].set(test, "This field have been changed!");
          ???????????????}
          ????????????}
          ???
          ????????}
          ????????catch (Exception e)
          ????????{
          ????????}

          ????????test.myPrint();
          ????}
          }
          運行結(jié)果是什么呢?是
          Begin to test change.
          This is ClassA
          This field have been changed!
          也就是說,在TestChangeApp類中,可以修改ClassA的私有成員變量。

          posted @ 2005-10-29 16:26 afrag 閱讀(709) | 評論 (0)編輯 收藏
           
          Copyright © afrag Powered by: 博客園 模板提供:滬江博客
          主站蜘蛛池模板: 曲沃县| 大连市| 凤山市| 长沙市| 峨山| 呼图壁县| 金山区| 玛多县| 土默特右旗| 杭锦旗| 台安县| 梅州市| 若尔盖县| 武清区| 本溪市| 民和| 鸡泽县| 额济纳旗| 教育| 屏东县| 历史| 新营市| 冕宁县| 崇左市| 丹江口市| 扎赉特旗| 凤山市| 湘阴县| 阳曲县| 托里县| 宜春市| 高阳县| 衡阳市| 高雄县| 渑池县| 宁强县| 蒙阴县| 五指山市| 彰化市| 青岛市| 临朐县|