亚洲成人在线网站,国产精品亚洲午夜一区二区三区,色噜噜亚洲精品中文字幕 http://m.tkk7.com/afrag/記錄學(xué)習(xí)和成長(zhǎng)的歷程zh-cnSun, 11 May 2025 07:51:39 GMTSun, 11 May 2025 07:51:39 GMT60Java SE 7新特性之文件操作(6) - 創(chuàng)建和讀寫文件 http://m.tkk7.com/afrag/archive/2010/04/05/317501.htmlafragafragMon, 05 Apr 2010 09:30:00 GMThttp://m.tkk7.com/afrag/archive/2010/04/05/317501.htmlhttp://m.tkk7.com/afrag/comments/317501.htmlhttp://m.tkk7.com/afrag/archive/2010/04/05/317501.html#Feedback0http://m.tkk7.com/afrag/comments/commentRss/317501.htmlhttp://m.tkk7.com/afrag/services/trackbacks/317501.html開發(fā)者的天空

本文中我們來討論在NIO2中怎樣創(chuàng)建文件、讀取文件和寫文件。NIO2提供了多種創(chuàng)建 文件的方法,使得我們?cè)趧?chuàng)建文件的時(shí)候就可以指定文件的某些初始屬性。例如在支持POSIX的文件系統(tǒng)上指定文件的所有者,訪問權(quán)限等。關(guān)于文件的屬性, 請(qǐng)看上一篇文章Java SE 7新特性之文件操作(5) - 管理元數(shù)據(jù)
創(chuàng)建文件
可以調(diào)用createFile(FileAttribute<?>)方法創(chuàng)建一個(gè)空文件。該方法的參數(shù)就是文件的初始屬性。下面的例子是怎樣 在創(chuàng)建文件的時(shí)候賦予該文件某些權(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í)候沒有傳入任何參數(shù),那么創(chuàng)建的文件將具有缺省的文件屬性。下面的代碼創(chuàng)建了一個(gè)具有缺省文件屬性的文件:
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);
}
如 果要?jiǎng)?chuàng)建的文件已經(jīng)存在,該方法會(huì)拋出異常。
注意在調(diào)用createFile方法時(shí),檢查文件是否存在和創(chuàng)建具有特定的屬性的文件是在同一個(gè)原子操作中。
還可以使用newOutputSteam方法來創(chuàng)建文件,在本文的后面我們會(huì)講到怎樣使用newOutputStream方法來創(chuàng)建文件。
通過Stream I/O讀文件
我們可以通過newInputStream(OpenOption...)方法打開和讀取文件。這個(gè)方法返回一個(gè)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();
}
注 意該方法接受可變個(gè)數(shù)的參數(shù),參數(shù)類型為OpenOption,指定了文件怎樣打開。如果不傳入?yún)?shù),則使用默認(rèn)的READ方式打開。READ方式是所有 的實(shí)現(xiàn)都支持的方式。有一些實(shí)現(xiàn)也支持其他的打開方式。
如果傳入的OpenOption或其組合不正確,會(huì)拋出異常。如果程序沒有讀權(quán)限或I/O錯(cuò)誤,也會(huì)拋出異常。
Creating and Writing a File by Using Stream I/O
使用Stream I/O來創(chuàng)建和寫文件
我們可以使用newOutputStream方法來創(chuàng)建文件、擴(kuò)展文件或覆蓋已有文件。這個(gè)方法為了寫文件而打開或創(chuàng)建文件,該方法返回一個(gè) unbuffered的輸出流(output stream)。newOutputStream方法有兩種形式:

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

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

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

如果沒有指定OpenOption,該方法的行為是:如果文件不存在,則創(chuàng)建新文件;如果文件存在,那么截?cái)嗨R簿褪钦f缺省的選擇是CREATE和 TRUNCATE_EXISTING選項(xiàng)的組合。
下面的代碼打開一個(gè)日志文件,如果文件不存在,則創(chuàng)建一個(gè)新文件。如果文件 存在,這將新的內(nèi)容擴(kuò)展到文件尾部。
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每次讀取一個(gè)字符,Channel I/O每次讀取一個(gè)緩沖塊的數(shù)據(jù)。ByteChannel接口提供了基本的讀寫功能。SeekableByteChannel擴(kuò)展了 ByteChannel并提供了維護(hù)一個(gè)channel中的位置并改變?cè)撐恢玫哪芰ΑeekableByteChannel還支持截?cái)辔募筒樵兾募? 小的功能。
移動(dòng)到文件中不同的位置,從該位置開始讀或?qū)懙哪芰κ刮覀兛梢?span onclick="tagshow(event)" class="t_tag">隨機(jī)訪問文件。有兩種形式的 newByteChannel方法可以用來讀或?qū)懳募@兩種形式和newOutputStream方法一樣。

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

這兩個(gè)方法都允許指定OpenOption,newOutputStream所支持的選擇這里也支持,而且這里還支持另外一個(gè)選項(xiàng)READ,因?yàn)? SeekableByteChannel既支持讀也支持寫。
如果選項(xiàng)是READ,那么該channel就是為了讀訪問打開。如果選項(xiàng)是WRITE或APPEND,則該channel就是為了寫訪問打開。如果沒有指 定,該channel默認(rèn)是為了讀打開。
下面的代碼從文件中讀取內(nèi)容并輸出到控制臺(tá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)建一個(gè)新的日志文件或者擴(kuò)展原有的日志文件,該日志文件創(chuàng)建時(shí)指定了訪問權(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();
}


afrag 2010-04-05 17:30 發(fā)表評(píng)論
]]>
Java SE 7文件操作新特性之管理元數(shù)據(jù)http://m.tkk7.com/afrag/archive/2010/04/01/317135.htmlafragafragThu, 01 Apr 2010 02:49:00 GMThttp://m.tkk7.com/afrag/archive/2010/04/01/317135.htmlhttp://m.tkk7.com/afrag/comments/317135.htmlhttp://m.tkk7.com/afrag/archive/2010/04/01/317135.html#Feedback0http://m.tkk7.com/afrag/comments/commentRss/317135.htmlhttp://m.tkk7.com/afrag/services/trackbacks/317135.html開發(fā)者的天空

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

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

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

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

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

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

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

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

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

設(shè)置 時(shí)間戳

前面的文件基本屬性的代碼中演示了怎樣獲取文件的時(shí)間戳,Attributes類還提供了兩個(gè)方法來設(shè)置時(shí)間戳:setLastAccessTime和 setLastModifiedTime,下面是這兩個(gè)方法的示例:
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的文件屬性
要獲取一個(gè)文件的DOS的文件屬性,需要調(diào)用readDosFileAttributes方法。這個(gè)方法會(huì)返回一個(gè)DosFileAttributes對(duì) 象,該對(duì)象提供了獲取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方法來設(shè)置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定義很多標(biāo)準(zhǔn)來保證不同的UNIX之間的戶操作性,因此對(duì)于開發(fā)人員來說,針對(duì)POSIX編寫的程序能夠很容易的運(yùn) 行在不同的兼容POSIX的文件系統(tǒng)上。
要讀取POSIX文件屬性,需要調(diào)用readPosixFileAttributes方法。除了文件所有者和所屬組,POSIX還支持9種文件權(quán)限許可組 合:讀、寫、執(zhí)行三種權(quán)限和文件所有者、同組的用戶和其他用戶三種角色的組合(3 × 3 = 9)。下面就是讀取POSIX文件屬性的簡(jiǎn)單的例子:
Path file = ;
PosixFileAttributes attr 
= Attributes.readPosixFileAttributes(file);
System.out.format(
"%s %s %s%n", attr.owner().getName, attr.group().getName(),
                  PosixFilePermissions.toString(attr.permissions()));

下面的代碼讀取了一個(gè)文件的屬性,然后創(chuàng)建了一個(gè)新的 文件,將原有的文件的權(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類,該類是一個(gè)幫助類,提供了一些方法來讀取和生成文件權(quán)限,這里就不詳細(xì)解釋了。
如果想指定創(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);
}
文 件有所有者的屬性和所屬組的屬性,在設(shè)置這些屬性的時(shí)候,我們需要傳入一個(gè)UserPrincipal對(duì)象作為參數(shù),我們可以使用 UserPrincipalLookupService來根據(jù)用戶名或組名來創(chuàng)建該對(duì)象。UserPrincipalLookupService實(shí)例可以 通過FileSystem.getUserPrincipalLookupService方法獲得。下面就是設(shè)置所有者屬性的例子:
Path file = ;
try {
    UserPrincipal owner 
= file.GetFileSystem().getUserPrincipalLookupService()
                          .lookupPrincipalByName(
"sally");
    Attributes.setOwner(file, owner);
catch (IOException x) {
    System.err.println(x);
}
Attributes 類沒有提供設(shè)置所屬組的方法,如果要設(shè)置所屬組,需要調(diào)用POSIX文件屬性視圖來進(jìn)行,下面是示例代碼:
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)支持的屬性對(duì)你來說還不夠用,你可以通過UserDefinedAttributeView來創(chuàng)建和跟蹤自己的文件屬性。
下面的例子中,我們將MIME類型作為一個(gè)用戶自定義的屬性:
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)不支持?jǐn)U展屬性,那么會(huì)拋出一個(gè) UnsupportedOperationException異常,你可以咨詢系統(tǒng)管理員來確認(rèn)系統(tǒng)是否支持文件的擴(kuò)展屬性并進(jìn)行相應(yīng)的配置。

文件存儲(chǔ)屬性
文件存儲(chǔ)屬性其實(shí)我們應(yīng)該非常熟悉的屬性,我們查看硬盤屬性的時(shí)候,經(jīng)常看到硬盤總的存儲(chǔ)空間,使用了的存儲(chǔ)空間,空閑的存儲(chǔ)空間等就是文件存儲(chǔ)屬性。下 面是獲取文件存儲(chǔ)屬性的代碼:
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() );



afrag 2010-04-01 10:49 發(fā)表評(píng)論
]]>
Java SE 7 文件操作特性之刪除、拷貝和移動(dòng)文件http://m.tkk7.com/afrag/archive/2010/03/30/316907.htmlafragafragTue, 30 Mar 2010 02:32:00 GMThttp://m.tkk7.com/afrag/archive/2010/03/30/316907.htmlhttp://m.tkk7.com/afrag/comments/316907.htmlhttp://m.tkk7.com/afrag/archive/2010/03/30/316907.html#Feedback0http://m.tkk7.com/afrag/comments/commentRss/316907.htmlhttp://m.tkk7.com/afrag/services/trackbacks/316907.html

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

刪除操作

通過Path類,我們可以刪除文件、目錄或符號(hào)鏈接。要注意的是當(dāng)我們刪除符號(hào)鏈接時(shí),其指向的目的目錄或文件不會(huì)被刪除。當(dāng)要?jiǎng)h除一個(gè)目錄時(shí),該目錄必須為空,否則會(huì)失敗。

Path類提供了兩個(gè)刪除方法。第一個(gè)是delete方法。Delete方法會(huì)直接刪除文件或目錄,如果刪除失敗則會(huì)拋出異常。例如如果要?jiǎng)h除的文件不存在,則會(huì)拋出NoSuchFileException。程序員可以catch這些異常并進(jìn)行相應(yīng)的處理。

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);
}


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


拷貝操作

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

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

在拷貝符號(hào)鏈接時(shí),默認(rèn)的行為是拷貝符號(hào)鏈接指向的目的文件或目錄。如果需要拷貝符號(hào)鏈接本身,需要指定NOFOLLOW_LINKS REPLACE_EXISTING選項(xiàng)。

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

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

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

* NOFOLLOW_LINKS – 如果要拷貝的是符號(hào)鏈接,直接拷貝符號(hào)鏈接本身。

下面是使用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;
}


移動(dòng)操作

Path還提供了moveTo方法來移動(dòng)文件或目錄。如果沒有設(shè)置REPLACE_EXISTING選項(xiàng),那么當(dāng)目標(biāo)文件或目錄存在時(shí),操作會(huì)失敗。

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

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

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

下面是使用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;
}




afrag 2010-03-30 10:32 發(fā)表評(píng)論
]]>
Java SE 7文件操作新特性之一些相關(guān)概念http://m.tkk7.com/afrag/archive/2010/03/29/316789.htmlafragafragMon, 29 Mar 2010 02:02:00 GMThttp://m.tkk7.com/afrag/archive/2010/03/29/316789.htmlhttp://m.tkk7.com/afrag/comments/316789.htmlhttp://m.tkk7.com/afrag/archive/2010/03/29/316789.html#Feedback0http://m.tkk7.com/afrag/comments/commentRss/316789.htmlhttp://m.tkk7.com/afrag/services/trackbacks/316789.html開發(fā)者的天空

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

Varargs實(shí)際上是Variable number of arguments的縮寫,也就是可變數(shù)目的參數(shù)。例如在下面的方法聲明中,CopyOption參數(shù)后面的省略號(hào)表明這個(gè)方法接受可變個(gè)數(shù)的參數(shù)。
        Path moveTo(Path, CopyOption...)
當(dāng)一個(gè)方法可以接受可變數(shù)目的參數(shù)時(shí),你可以傳入以逗號(hào)分隔的多個(gè)參數(shù),或者傳入一個(gè)數(shù)組。
對(duì)于上面的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方法。原子操作是指不會(huì)被中斷或不會(huì)部分執(zhí)行的操作。操作要么是完全成功,要么是完全失敗。當(dāng)有多個(gè)進(jìn)程操作同文件系統(tǒng)的相同的區(qū)域的時(shí)候這一點(diǎn)就很重要。


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


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


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



Path會(huì)指向文件或者目錄,但是我們還不能確定這個(gè)文件或者目錄是否存在,是否可讀,是否可寫,是否可以執(zhí)行。要確定文件/目錄是否存在以及程序是否可以訪問該文件/目錄,可以使用checkAccess(AccessMode...)方法。可選的AccessMode有:
    * READ – 檢查文件/目錄是否存在以及程序是否有權(quán)限讀該文件/目錄
    * WRITE – 檢查文件/目錄是否存在以及程序是否有權(quán)限寫該文件/目錄
    * EXECUTE – 檢查文件/目錄是否存在以及程序在該文件/目錄上是否有執(zhí)行權(quán)限
如果調(diào)用checkAccess的時(shí)候沒有傳入任何參數(shù),該方法只是檢查文件是否存在。
下面的例子演示了怎樣驗(yàn)證文件是否存在以及程序是否有讀和執(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...
需要注意的是,當(dāng)checkAccess執(zhí)行完之后,文件的權(quán)限可能被其他的用戶(例如系統(tǒng)管理員)修改。這實(shí)際上是很多應(yīng)用程序都有的安全性的問題。如果你感興趣,可以搜索TOCTTOU (time of check to time of use)。


當(dāng)文件系統(tǒng)中存在符號(hào)鏈接的時(shí)候,可能兩個(gè)不同的路徑會(huì)指向同一個(gè)文件或目錄。方法isSamePath會(huì)比較兩個(gè)Path來檢查它們是否指向同一個(gè)文件/目錄。
    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;
    }

afrag 2010-03-29 10:02 發(fā)表評(píng)論
]]>
Java SE 7文件操作之Path的基本操作http://m.tkk7.com/afrag/archive/2010/03/27/316727.htmlafragafragSat, 27 Mar 2010 14:45:00 GMThttp://m.tkk7.com/afrag/archive/2010/03/27/316727.htmlhttp://m.tkk7.com/afrag/comments/316727.htmlhttp://m.tkk7.com/afrag/archive/2010/03/27/316727.html#Feedback0http://m.tkk7.com/afrag/comments/commentRss/316727.htmlhttp://m.tkk7.com/afrag/services/trackbacks/316727.html轉(zhuǎn)自開發(fā)者的天空
在上面的一篇文章中,我們已經(jīng)說過了Path類的操作主要有兩種:對(duì)路徑的操作和對(duì)文件的操 作。這篇文章中我們就來了解一下對(duì)路徑的操作。
創(chuàng)建Path實(shí)例
Path實(shí)例包含了指定文件或目錄位置的信息,在實(shí)例化Path類時(shí),需要指定一個(gè)或多個(gè)目錄或文件名。路徑的根目錄不是必須的;路徑信息可能僅僅是一個(gè) 目錄或文件的名稱。
最簡(jiǎn)單的創(chuàng)建Path實(shí)例的方式就是使用Paths(注意這里有一個(gè)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理解為按順序存儲(chǔ)的一系列的名稱(目錄名稱和文件名稱)。目錄結(jié)構(gòu)中最高一層的目錄名就是序列中 index為0的那一個(gè),目錄結(jié)構(gòu)中最低一層的目錄名或者文件名就是序列中index為n-1的那一個(gè)(這里n是路徑中層次的數(shù)目)。Path類提供方法 來通過index獲取序列中的一個(gè)元素或一個(gè)子序列。
隨后的例子中我們使用的目錄結(jié)構(gòu)如下圖:
io-dirStructure.JPG

    下面的代碼定義了一個(gè)Path對(duì)象并獲取其中的信息。要注意的是這些代碼中除了isHidden方法外,其他的方法并不需要指定的目錄或文件存在;如果不 存在,isHidden方法會(huì)拋出異常。
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 獲 取名稱序列中的最后一個(gè),也就是最底層的目錄或文件名
getName(0) home home 獲 取名稱序列中的第一個(gè),也就是最靠近根目錄的那一層。注意根目錄不在名稱序列中
getNameCount 3 3 獲 取名稱序列的元素個(gè)數(shù)
subpath(0,2) home/joe home\joe 獲 取從指定的開始點(diǎn)到指定的結(jié)束點(diǎn)的子路徑。注意這里包括開始點(diǎn),但不包括結(jié)束點(diǎn)。
getParent /home/joe \home\joe 返 回Path指定的目錄或文件的父目錄
getRoot / C:\ 返 回根目錄
isHidden false false 如果文件是 隱藏文件,或者目錄是隱藏目錄,返回true。因?yàn)橐L問文件的屬性,所以如果Path指定的目錄或者文件不存在,會(huì)拋出異常。


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

大 家可以自行去實(shí)驗(yàn)一下具體的輸出是什么。

去除Path中的冗余
在很多文件系統(tǒng)中我們使用'.'來代表當(dāng)前目錄,使用'..'代表父目錄。在有些情況下我們創(chuàng)建的路徑中會(huì)有冗余的路徑信息,例如:
        /home/./joe/foo
        /home/sally/../joe/foo
方法normalize會(huì)去除這些冗余信息,包括'.'或'directory/..'。上面的兩個(gè)例子在去除冗余信息后都是/home/joe /foo。
要注意的是normalize方法并不去檢查文件系統(tǒng),它只是簡(jiǎn)單的進(jìn)行語(yǔ)法操作。在第二個(gè)例子中,如果sally是一個(gè)指向其他的目錄的符號(hào)鏈接,那么 去除了sally/..后可能導(dǎo)致Path不在指向原來的文件或目錄。
如果你需要清除冗余信息,又要保證結(jié)果仍然指向正確的文件或目錄,可以使用toRealPath方法。在下面我們會(huì)講到這個(gè)方法。
轉(zhuǎn)換Path
有3個(gè)方法用來轉(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)換為絕對(duì)路徑。如果原來的Path已經(jīng)是絕對(duì)路徑,該方法直接返回原有的Path對(duì)象。
    我們來看看下面的例子:
                    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方法
    這個(gè)方法會(huì)返回一個(gè)已經(jīng)存在的文件或目錄的真實(shí)路徑(如果文件或目錄不存在或無法訪問,該方法會(huì)拋出異常)。該方法會(huì)執(zhí)行以下的操作:
    如果傳入的參數(shù)是true并且文件系統(tǒng)支持符號(hào)鏈接,則解析路徑中存在的符號(hào)鏈接(如果有的話)。
    如果原來的Path是相對(duì)路徑,將其轉(zhuǎn)換成絕對(duì)路徑。
    如果路徑中含有冗余信息,返回的Path中這些冗余信息會(huì)被去除。

連接兩個(gè)Path
可以使用resolve方法來將兩個(gè)Path連接起來。該方法的參數(shù)是一個(gè)字符串。如果該字符串代表的是一個(gè)相對(duì)路徑,那么這個(gè)路徑會(huì)被擴(kuò)展到原來的路徑 后。如果傳入的字符串是一個(gè)絕對(duì)路徑,那么返回的值就是傳入的這個(gè)絕對(duì)路徑。例如:
        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)建兩個(gè)路徑之間的路徑
這個(gè)功能說起來有些繞口,實(shí)際的功能就是創(chuàng)建兩個(gè)指定的目錄或文件之間的相對(duì)路徑。例如:
        Path p1 = Paths.get("joe/foo");
        Path p2 
= Paths.get("sally");
在這個(gè)例子中,由于兩個(gè)路徑都是相對(duì)路徑,沒有其他的 信息,我們會(huì)認(rèn)為這兩個(gè)joe和sally是同一級(jí)的兄弟目錄,因此有以下的結(jié)果

        Path p1_to_p2 = p1.relativize(p2);   // 結(jié)果是 ../../sally
        Path p2_to_p1 = p2.relativize(p1);   // 結(jié)果是 ../joe/foo
讓我們看看另外一個(gè)例子
        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é)果是 ../..
在這個(gè)例子中,兩個(gè)路徑共享同一個(gè)節(jié)點(diǎn)-home, 所以結(jié)果并不是../home/sally/bar和../../../home.
如果兩個(gè)路徑中有一個(gè)是絕對(duì)路徑,另外一個(gè)是相對(duì)路徑,relative方法會(huì)拋出異常。如果兩個(gè)路徑都是絕對(duì)路徑,那么relative方法的行為和系 統(tǒng)相關(guān),不同的系統(tǒng)可能不同。
我在Windows操作系統(tǒng)下實(shí)驗(yàn)了一下,如果兩個(gè)路徑屬于同一個(gè)硬盤,那么可以執(zhí)行成功,否則會(huì)拋出異常。
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方法來檢查兩個(gè)Path是否相等。但是這里 要注意的是比較的并不是兩個(gè)Path是否指向同一個(gè)目錄或者文件。請(qǐng)看下面的例子:
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方法,這兩個(gè)方法用來檢查路徑是否以指定的字符串開始或者結(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類實(shí)現(xiàn)了Iterable接口,iterator方法會(huì)返回一個(gè)Iterator對(duì)象,該對(duì)象中的第一個(gè)元素就是原 路徑中最上層(最靠近根節(jié)點(diǎn))的目錄。下面是使用這個(gè)方法的例子:
        Path path = ;
        
for (Path name: path) {
            System.out.println(name);
        }

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

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

在下面一篇文章中,我們會(huì)介紹怎樣進(jìn)行文件的操作。

afrag 2010-03-27 22:45 發(fā)表評(píng)論
]]>
Java SE 7 文件操作特性之Path概念http://m.tkk7.com/afrag/archive/2010/03/25/316607.htmlafragafragThu, 25 Mar 2010 15:34:00 GMThttp://m.tkk7.com/afrag/archive/2010/03/25/316607.htmlhttp://m.tkk7.com/afrag/comments/316607.htmlhttp://m.tkk7.com/afrag/archive/2010/03/25/316607.html#Feedback0http://m.tkk7.com/afrag/comments/commentRss/316607.htmlhttp://m.tkk7.com/afrag/services/trackbacks/316607.html轉(zhuǎn)載自開發(fā)者的天空
1. Path的概念
文件系統(tǒng)會(huì)把文件進(jìn)行組織并存放在媒介上,通常是一個(gè)或多個(gè)硬盤上。目前使用的大多數(shù)的文件系統(tǒng)是以樹形的方式來存儲(chǔ)文件的。在樹的頂端是一個(gè)(或多個(gè)) 根節(jié)點(diǎn),在根節(jié)點(diǎn)之下是文件和目錄,目錄下又可以包含文件和目錄。理論上可以這樣一層層的一直嵌套下去(當(dāng)然實(shí)際中是不可能的,例如Windows系統(tǒng)對(duì) 路徑的長(zhǎng)度有限制)。
下面的圖中展示了一個(gè)包含一個(gè)根節(jié)點(diǎn)的目錄樹。(在Windows系統(tǒng)中支持多個(gè)根節(jié)點(diǎn),例如C:\和D:\分別是一個(gè)根節(jié)點(diǎn)。)
io-dirStructure.JPG
Path能夠唯一的標(biāo)識(shí)文件系統(tǒng)中的某一個(gè)文件。例如上面圖中的statusReport文件在Windows系統(tǒng)中就可以使用以下的Path來標(biāo)識(shí):
c:\home\sally\statusReport
在solaris系統(tǒng)中,其path為
/home/sally/statusReport.
Path中的分隔符在不同的文件系統(tǒng)中是不同的,例如在Windows系統(tǒng)中使用\,在Solaris系統(tǒng)中使用/。
Path又可以分為絕對(duì)路徑和相對(duì)路徑。絕對(duì)路徑總是含有根節(jié)點(diǎn)和用來定位文件的完整的目錄列表。例如/home/sally/statusReport 就是絕對(duì)路徑。相對(duì)路徑需要和另外的路徑結(jié)合在一起才能夠確定一個(gè)文件。例如加哦加哦哦joe/foo就是一個(gè)相對(duì)路徑,如果沒有其他的信息,程序就沒有 辦法定位這個(gè)文件。我們必須說這個(gè)是相對(duì)/home的相對(duì)路徑,這樣我們才能夠找到它。
除了我們熟悉的目錄和文件之外,有一些文件系統(tǒng)中還支持符號(hào)鏈接(symbolic link),也稱為symlink或soft link。一個(gè)符號(hào)鏈接是一個(gè)特殊的文件,它實(shí)際上是另外一個(gè)鏈接的引用。在大多數(shù)情況下符號(hào)鏈接對(duì)應(yīng)用程序是透明的,對(duì)符號(hào)鏈接的操作會(huì)自動(dòng)的重定向到 鏈接所指向的目的地,除非操作是刪除這個(gè)符號(hào)鏈接、重命名這個(gè)符號(hào)鏈接或修改符號(hào)鏈接的目的地。
在下面的圖中,logFile對(duì)于用戶來說就是一個(gè)常規(guī)的文件,但是實(shí)際上是一個(gè)符號(hào)鏈接,鏈接到dir/logs/HomeLogFile文件。 HomeLogFile是這個(gè)鏈接的目的地。
io-symlink.jpg
不恰當(dāng)?shù)氖褂梅?hào)鏈接會(huì)導(dǎo)致循環(huán)引用,例如目錄A是一個(gè)符號(hào)鏈接,指向目錄B,目錄B下有一個(gè)子目錄是符號(hào)鏈接,指向目錄A的父目錄。這樣,當(dāng)程序企圖遞 歸的遍歷整個(gè)目錄樹時(shí),就會(huì)出問題。幸運(yùn)的是,這個(gè)問題已經(jīng)被發(fā)現(xiàn)了,并且不會(huì)導(dǎo)致程序的死循環(huán)。


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

  • 路徑操作—返回路徑的一部分如根節(jié)點(diǎn)、名稱、父目錄的方法或者其他操作路徑的方法。
  • 文件操作—?jiǎng)?chuàng)建文件、打開文件、創(chuàng)建目錄、刪除文件、 拷貝文件等操作的方法。
在下一篇文章中,我們會(huì)具體介紹Path類的這些方法。

afrag 2010-03-25 23:34 發(fā)表評(píng)論
]]>
在java程序中如何知道數(shù)據(jù)庫(kù)表的主鍵http://m.tkk7.com/afrag/archive/2006/01/20/28737.htmlafragafragFri, 20 Jan 2006 02:52:00 GMThttp://m.tkk7.com/afrag/archive/2006/01/20/28737.htmlhttp://m.tkk7.com/afrag/comments/28737.htmlhttp://m.tkk7.com/afrag/archive/2006/01/20/28737.html#Feedback1http://m.tkk7.com/afrag/comments/commentRss/28737.htmlhttp://m.tkk7.com/afrag/services/trackbacks/28737.html       有同事問到在程序中怎樣知道數(shù)據(jù)庫(kù)表中那些字段是主鍵。當(dāng)時(shí)不知道,晚上回來看了看JDK的文檔。

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

1.  注冊(cè)驅(qū)動(dòng)程序

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

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

4.  關(guān)閉連接。

       在獲得數(shù)據(jù)庫(kù)連接后,就可以通過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{

                     //注冊(cè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序

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

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

            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{

                            //關(guān)閉連接

                if (rst != null)

                    rst.close();

                if (con != null)

                    con.close();

            }

            catch (SQLException e){

                throw e;

            }

        }

 

    }

}

 

上面的程序中,在獲取主鍵信息的時(shí)候,語(yǔ)句

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

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



afrag 2006-01-20 10:52 發(fā)表評(píng)論
]]>
Spring AOP中MethodBeforeAdvice、AfterReturningAdvice和MethodInterceptor的執(zhí)行順序http://m.tkk7.com/afrag/archive/2005/11/02/17861.htmlafragafragWed, 02 Nov 2005 10:10:00 GMThttp://m.tkk7.com/afrag/archive/2005/11/02/17861.htmlhttp://m.tkk7.com/afrag/comments/17861.htmlhttp://m.tkk7.com/afrag/archive/2005/11/02/17861.html#Feedback1http://m.tkk7.com/afrag/comments/commentRss/17861.htmlhttp://m.tkk7.com/afrag/services/trackbacks/17861.html在Spring 的AOP中,如果一個(gè)Proxy同時(shí)實(shí)現(xiàn)MethodBeforeAdvice、AfterReturningAdvice和MethodInterceptor接口,那么這三個(gè)Advice的執(zhí)行順序是什么樣的呢?
經(jīng)過試驗(yàn),是和xml文件中的定義順序有關(guān)的。
如果Proxy的接口實(shí)現(xiàn)定義為
?????
?????????
??????????? MethodBeforeAdvice
??????????? AfterReturningAdvice
??????????? MethodInterceptor
?????????

?????

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

MethodInterceptor: before call

Really method excuting

MethodInterceptor: after call

AfterReturningAdvice

也就是說,執(zhí)行順序是:MethodBeforeAdvice,MethodInterceptor的調(diào)用前的部分,目標(biā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)用前的部分,目標(biā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,目標(biāo)方法,AfterReturningAdvice,MethodInterceptor的調(diào)用后的部分。
以上的順序是在springframework 1.2.5中測(cè)試的。



afrag 2005-11-02 18:10 發(fā)表評(píng)論
]]>
關(guān)于Java的封裝性http://m.tkk7.com/afrag/archive/2005/10/29/17348.htmlafragafragSat, 29 Oct 2005 08:26:00 GMThttp://m.tkk7.com/afrag/archive/2005/10/29/17348.htmlhttp://m.tkk7.com/afrag/comments/17348.htmlhttp://m.tkk7.com/afrag/archive/2005/10/29/17348.html#Feedback0http://m.tkk7.com/afrag/comments/commentRss/17348.htmlhttp://m.tkk7.com/afrag/services/trackbacks/17348.html今天在看Spring in Action,看到了一個(gè)很有意思的例子。
假如你編寫了一個(gè)類:

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

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

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

OK。按照面向?qū)ο蟮乃枷耄渌念悜?yīng)該不能夠修改ClassA的fieldA字段吧?因此無論什么時(shí)候你調(diào)用ClassA的myPrint方法,都應(yīng)該打印的是“This is Class A”。
??????但是,實(shí)際情況并不是如此,請(qǐng)看下面的例子:
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();
????}
}
運(yùn)行結(jié)果是什么呢?是
Begin to test change.
This is ClassA
This field have been changed!
也就是說,在TestChangeApp類中,可以修改ClassA的私有成員變量。



afrag 2005-10-29 16:26 發(fā)表評(píng)論
]]>
主站蜘蛛池模板: 四虎亚洲国产成人久久精品| 亚洲中文字幕无码不卡电影| 中文字幕人成人乱码亚洲电影| 久久夜色精品国产噜噜噜亚洲AV | 99热这里只有精品免费播放| 午夜老司机免费视频| 亚洲乱码日产一区三区| 亚洲娇小性色xxxx| 一级做a爱片特黄在线观看免费看| 在线观看免费av网站| 亚洲男人第一无码aⅴ网站| 亚洲成电影在线观看青青| 一级成人生活片免费看| 国产在线观看片a免费观看| 中文字幕中韩乱码亚洲大片| jlzzjlzz亚洲jzjzjz| 久久久久久久国产免费看| 免费可以在线看A∨网站| 国产精品亚洲成在人线| 色五月五月丁香亚洲综合网| 精品无码国产污污污免费网站 | 久久精品九九亚洲精品| 最好2018中文免费视频| 91免费国产在线观看| 亚洲人成77777在线播放网站| 亚洲av午夜国产精品无码中文字| 国产精品免费福利久久| 亚洲AV伊人久久青青草原| 色婷五月综激情亚洲综合| 中文字幕日本人妻久久久免费| 永久中文字幕免费视频网站| 亚洲成无码人在线观看| 天堂在线免费观看| 亚洲国产成人爱av在线播放| 国产成人亚洲综合网站不卡| 18以下岁毛片在免费播放| 亚洲av无码一区二区三区不卡 | 青青草无码免费一二三区| 国内精品99亚洲免费高清| 国产精品久久久久久亚洲影视| 青青青免费国产在线视频小草|