久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

NIO

 印度阿三17 2020-03-23

前言

  將File操作進(jìn)行分離、封裝,、改進(jìn),,最終形成Path(Paths),、Files,、FileSystem(FileSystems)三個主要類,。

我們親切的叫它NIO2,。

其中,,Paths,、Files中提供了大量便捷的靜態(tài)操作方法;NIO2還提供了有關(guān)文件權(quán)限(屬性)操作,、軟連接,、文件查找等高級API,使得NIO2具有更全面的文件系統(tǒng)操作接口,。

1,、Path

文件系統(tǒng)都是Tree或者層級結(jié)構(gòu)來組織文件的,任何一個節(jié)點(diǎn)可以是一個目錄或者一個文件,,在NIO2中稱為Path,,這和原來的File有很多相似之處,只是Path具有更多的表述語義,。

1.1,、基本屬性

以下代碼展示了它的基本屬性。

Path path = Paths.get("/data/logs/web.log");
//屬性
//獲取路徑中的文件名或者最后一個節(jié)點(diǎn)元素
System.out.printf("FileName:%s%n", path.getFileName());
//路徑節(jié)點(diǎn)元素的格式
System.out.printf("NameCount:%s%n", path.getNameCount());
//遍歷路徑節(jié)點(diǎn)方法1
Iterator<Path> names = path.iterator();
int i = 0;
while (names.hasNext()) {
   Path name = names.next();
   System.out.printf("Name %s:%s%n",i,name.toString());
   i ;
}
//方法2
for(int j = 0; j < path.getNameCount(); j ) {
   System.out.printf("Name %s:%s%n",j,path.getName(j));
}
//父路徑
System.out.printf("Parent:%s%n",path.getParent());
//跟路徑,比如"/",、"C:";如果是相對路徑,,則返回null。System.out.printf("Root:%s%n",path.getRoot());
//子路徑,,結(jié)果中不包含root,,前開后閉
System.out.printf("Subpath[0,2]:%s%n",path.subpath(0,2));

結(jié)果:

FileName:web.log
NameCount:3
Name 0:data
Name 1:logs
Name 2:web.log
Name 0:data
Name 1:logs
Name 2:web.log
Parent:/data/logs
Root:/
Subpath[0,2]:data/logs

1.2、路徑轉(zhuǎn)換

1)比如“/data/logs/./web.log”,、“/data/logs/../db”這種包含“冗余”路徑的,,有時候我們需要轉(zhuǎn)換為正常路徑語句,則使用“Path.normalize()”方法,,無比的清爽清潔。

Path path = Paths.get("/data/logs/../web.log");
//輸出結(jié)果:/data/web.log
System.out.printf("%s%n",path.normalize());

2)如果文件需要被外部資源訪問(resource),,你可以通過Path.toUri()來轉(zhuǎn)換,,path對應(yīng)的文件或者目錄可以不存在,此方法不會check異常:

Path path = Paths.get("/data/logs/web.log");
//表示本地文件的uri,輸出結(jié)果:file:///data/logs/web.log
System.out.printf("%s%n",path.toUri());

3)toAbsolutePath():如果路徑為相對路徑,,則轉(zhuǎn)換為絕對路徑,,對于JAVA程序而言,,起始路徑為classpath。此方法不會檢測文件是否真的存在或者有權(quán)限,。

4)其中toRealPath()是比較重要的方法,,不過它會對文件是否存在、訪問權(quán)限進(jìn)行檢測,,需要捕獲異常,。首先檢測文件是否存在、是否有權(quán)限,;如果path為相對路徑,,則將會轉(zhuǎn)換為絕對路徑,同“3)”,;如果是“符號連接”文件(軟連接),,則獲取其實(shí)際target路徑(除非指定了NO_FOLLOW_LINKS);如果路徑中包含“冗余”,,則移除,,同1)。這個方法,,通常用于對“用戶輸入的path”進(jìn)行校驗(yàn)和轉(zhuǎn)換,,使用比較多。

5)resolve():路徑合并,,當(dāng)前path與參數(shù)進(jìn)行路徑合并,,append。

6)relativize():獲取相對路徑,,“/data”與“/data/logs/p1”的相對路徑為“l(fā)ogs/p1”,,反之為“../../”。

2,、Files

Files類中提供了大量靜態(tài)方法,,用于實(shí)現(xiàn)文件(目錄)的創(chuàng)建、復(fù)制,、遷移,、刪除以及訪問文件數(shù)據(jù)等操作。

2.1,、檢測文件或目錄

Files.exists(Path)和notExists(Path)兩個方法,,這兩個方法都會實(shí)際檢測文件或者目錄是否存在、以及是否有訪問權(quán)限,。注意:!exist() 與notExists()并不完全相等,,exist可能有三種狀態(tài):如果不存在或者安全校驗(yàn)不通過則返回false,如果返回true則表示文件確實(shí)存在且有權(quán)限,。notExists()檢測類似,,對于沒有通過安全校驗(yàn)的也會返回false,;當(dāng)exists與notExists同時返回false時,說明文件不可以驗(yàn)證(即無權(quán)限),,所以通常這兩個方法需要同時使用,。

判斷文件(目錄)具有讀、寫,、執(zhí)行的權(quán)限,,可以通過如下方法:

Path path = Paths.get("data/logs/web.log");
boolean isRegularExecutableFile = Files.isRegularFile(path) &
       Files.isReadable(path) & Files.isExecutable(path);

有時候,兩個不同的path,,會指向同一個文件,,比如當(dāng)一個path是軟連接時,此時可以使用Files.isSameFile(p1,p2)來檢測,,當(dāng)然你可以通過Path LinkOption相關(guān)組合獲取target實(shí)際path來比較,。

2.2、刪除

delete和deleteIfExists兩個方法均可刪除文件,,前者嘗試刪除的文件如果不存在則會拋出異常,。如果文件是軟連接,則只刪除連接文件而不會刪除target文件,,如果path為目錄,,則目錄需要為空,否則刪除失?。↖OException),。在刪除操作之前,最后做一些常規(guī)的檢測,,比如文件是否存在(有權(quán)限),、目錄是否為空等。稍后我們再介紹“遞歸刪除目錄樹和文件”,。

2.3,、文件(目錄)復(fù)制

copy(Path,Path,CopyOption…)方法可以復(fù)制文件,不過,,需要注意CopyOption的相關(guān)選項,。

當(dāng)copy一個軟連接文件時,默認(rèn)將會復(fù)制target文件,,如果只想復(fù)制軟連接文件而不是target內(nèi)容,,可以指定NOFOLLOW_LINKS選項。CopyOption的實(shí)現(xiàn)類為StandardCopyOption,,此外CopyOption也擴(kuò)展了LinkOption,,即包含NOFOLLOW_LINKS選項。如下為CopyOption選項列表:

1)REPLACE_EXISTING:如果目標(biāo)文件已經(jīng)存在,則直接覆蓋,;如果目標(biāo)文件是個軟連接,則軟連接文件本身被覆蓋(而非連接文件的target文件),;如果復(fù)制的是目錄,,且目標(biāo)目錄不為空時,則會拋出異常(DirectoryNotEmptyException),,稍后介紹“遞歸復(fù)制目錄樹和文件”,。此參數(shù)通常必選。復(fù)制目錄時,,目標(biāo)目錄會自動創(chuàng)建,,源目錄中如果有文件,則不會復(fù)制文件,,只會創(chuàng)建空的目標(biāo)目錄,。source和target,要么同時是目錄,、要么同時是文件,。

2)COPY_ATTRIBUTES:復(fù)制文件時,也同時復(fù)制目標(biāo)文件的屬性(metadata),,對于文件屬性(FileAttribute)的支持依賴于文件系統(tǒng)(和平臺),,不過lastModifiedTime通常會被復(fù)制。

3)NOFOLLOW_LINKS:繼承自LinkOption,,表示如果文件是軟連接,,則不followed,即只復(fù)制連接文件,,不復(fù)制其target實(shí)際文件內(nèi)容,。

4)ATOMIC_MOVE:只支持move操作,copy不支持,。

Path source = Paths.get("/data/logs/web.log");
Path target = Paths.get("/data/logs/web.log.copy");
Files.copy(source,target,REPLACE_EXISTING,COPY_ATTRIBUTES,NOFOLLOW_LINKS);

2.4,、移動

move(Path,Path,CopyIOption),基本原則同copy,。需要注意,,如果是目錄,目錄中包含文件時也可以移動的(這可能依賴于平臺),,子目錄也一起移動,,但是目標(biāo)目錄必須為空(DirectoryNotEmptyException)?;菊Z義同“mv -rf”,,目標(biāo)目錄不需要提前創(chuàng)建,move結(jié)束后,源目錄將不存在,。支持兩種選項:

1)REPLACE_EXISTING:如果目標(biāo)文件已存在,,則覆蓋;如果目標(biāo)文件是軟連接,,則連接文件被覆蓋但是其指向不會受影響,。

2)ATOMIC_MOVE:原子復(fù)制,需要平臺的文件系統(tǒng)支持(不支持則拋出異常),,指定此參數(shù)時其他選項將被忽略,;如果文件不能被原子復(fù)制(或者替換),則會拋出AtomicMoveNotSupportedException,。

2.5,、打開文件

Files類中提供了多個靜態(tài)的方法,用于直接讀寫文件,。如下為文件打開的幾個選項參數(shù)(StandardOpenOptions):

1)WRITE: 打開文件用于write訪問,。

2)APPEND:在文件尾部追加數(shù)據(jù),伴隨用于WRITE或CREATE選項,。

3)TRUNCATE_EXISTING:將文件truncate為空,,伴隨用于WRITE選項。比如,,文件存在時,,將文件數(shù)據(jù)清空并重新寫入。

4)CREATE_NEW:創(chuàng)建新文件,,如果文件已存在則拋出異常,。

5)CREATE:如果文件已存在則直接打開,否則創(chuàng)建文件,。

6)DELETE_ON_CLOSE:當(dāng)文件操作關(guān)閉時則刪除文件(close方法或者JVM關(guān)閉時),,此選項適用于臨時文件(臨時文件不應(yīng)該被其他進(jìn)程并發(fā)訪問)。

7)SPARSE:創(chuàng)建一個“稀疏”文件,,伴隨使用CREATE_NEW,,適用于某些特殊的文件系統(tǒng)比如NTFS,這些大文件允許出現(xiàn)“gaps”(空洞)在某些情況下可以提高性能且這些gaps不消耗磁盤空間,。

8)SYNC:對文件內(nèi)容(data)或者metadata的修改,,都會同步到底層存儲。

9)DSYNC:對文件內(nèi)容的修改,,會同步到底層存儲,。

對于一些小文件(M級別),通常我們希望一次全部讀取所有內(nèi)容,,而不再使用傳統(tǒng)的方式迭代讀取,。

//全部讀取小文件中的數(shù)據(jù)
//Files.readAllBytes(Paths.get("/data/web.log"));
List<String> lines = Files.readAllLines(Paths.get("/data/web.log"),Charset.forName("utf-8"));

//將準(zhǔn)備好的數(shù)據(jù),直接全部寫入文件。(打開,、寫入)
Files.write(Paths.get("/data/web-1.log"),lines,Charset.forName("utf-8"),
       StandardOpenOption.APPEND,
       StandardOpenOption.CREATE));

//傳統(tǒng)操作
try (BufferedReader reader = Files.newBufferedReader(Paths.get("/data/web.log"))) {
   while (true) {
       String line = reader.readLine();
       if (line == null) {
           break;
       }
       System.out.println(line);
   }
} catch (IOException e) {
   //
}

//傳統(tǒng)操作
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("/data/web.log"),Charset.forName("utf-8"),StandardOpenOption.APPEND,
       StandardOpenOption.CREATE)) {
   for(String line : lines) {
       writer.write(line);
   }
} catch (IOException e) {
   //
}

此外Files中還提供了基于buffer的channel操作,,返回類型為SeekableByteChannel,這種操作通常適用于讀或者寫,,以及數(shù)據(jù)可以基于buffer進(jìn)行拆封包,,其他特性類似“隨機(jī)訪問文件”。(Files.newByteChannel(),,功能同F(xiàn)ile.open())

Path path = Paths.get("/data/web.log");
//創(chuàng)建一個普通文件,如果已存在則拋出異常,,文件屬性為默認(rèn),。Files.createFile(path);

//創(chuàng)建臨時文件,臨時文件的目錄和前綴可以為null,,后綴如果為null時默認(rèn)使用".tmp";
Files.createTempFile(null,null,".tmp");
//創(chuàng)建一個軟連接文件
Files.createSymbolicLink(Paths.get("/data/link.log"),Paths.get("/data/web.log"));

2.6,、Metadata管理

2.6.1、BasicFileAttributes

BasicFileAttributes基本接口,,提供了一些基本的文件metadata,,比如lastAccessTime、lastModifiedTime等,,它的實(shí)現(xiàn)類因平臺而已有:DosFileAttributes,、PosixFileAttribute、UnixFileAttribute等,;不同平臺所能支持的屬性有所不同,。(在跨平臺場景下,你可能需要使用FileStore來判斷當(dāng)前文件系統(tǒng)是否支持相應(yīng)的FileAttributeView)

Path path = Paths.get("/data/logs/web.log");
BasicFileAttributes attributes = Files.readAttributes(path,BasicFileAttributes.class);
System.out.println("regular file:" attributes.isRegularFile());
System.out.println("directory:" attributes.isDirectory());
System.out.println("symbolic link:" attributes.isSymbolicLink());
System.out.println("modified time:" attributes.lastModifiedTime().toMillis());

//修改系統(tǒng)更新屬性
Files.setLastModifiedTime(path,FileTime.fromMillis(System.currentTimeMillis()));

//修改其他屬性
Files.setAttribute(path,"dos:hidden",true);

屬性名格式為“view-name:attribute-name”,,比如“dos:hidden”,;其中合法的view-name目前有“basic”、“posix”,、“unix”、“owner”(所有者信息,,權(quán)限),屬性的列表需要根據(jù)自己的平臺對應(yīng)相應(yīng)的Attributes類,否則會導(dǎo)致設(shè)置異常,。

2.6.2,、PosixFileAttributes

Path path = Paths.get("/data/logs/web.log");
PosixFileAttributes attributes = Files.readAttributes(path,PosixFileAttributes.class);

//用戶組和權(quán)限
UserPrincipal userPrincipal = attributes.owner();
System.out.println(userPrincipal.toString());

GroupPrincipal groupPrincipal =  attributes.group();
System.out.println(groupPrincipal.toString());

Set<PosixFilePermission> permissions = attributes.permissions();
//將權(quán)限轉(zhuǎn)換為文件屬性,,用于創(chuàng)建新的文件,目前文件權(quán)限也是一種屬性
FileAttribute<Set<PosixFilePermission>> fileAttribute = PosixFilePermissions.asFileAttribute(permissions);

Files.createFile(Paths.get("/data/test.log"),fileAttribute);

//修改文件權(quán)限,,可以在permissions中增減權(quán)限列表,枚舉
Files.setPosixFilePermissions(path,permissions);

從權(quán)限字符串中,,構(gòu)建權(quán)限列表

Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("-rw-r--r--");
Files.setPosixFilePermissions(path, permissions);

修改文件(目錄)的所有者或者所在組:

Path path = Paths.get("/data/logs/web.log");
//首先找到系統(tǒng)中的其他用戶,根據(jù)用戶名
UserPrincipal userPrincipal = path.getFileSystem().getUserPrincipalLookupService().lookupPrincipalByName("userName");
Files.setOwner(path,userPrincipal);
//或者
Files.getFileAttributeView(path,FileOwnerAttributeView.class).setOwner(userPrincipal);

//修改group
GroupPrincipal groupPrincipal = path.getFileSystem().getUserPrincipalLookupService().lookupPrincipalByGroupName("groupName");
Files.getFileAttributeView(path,PosixFileAttributeView.class).setGroup(groupPrincipal);

2.6.3,、UserDefinedFileAttributeView

用戶自定義文件屬性(即擴(kuò)展文件屬性),,以及屬性值的長度,,這取決于底層文件系統(tǒng)或者平臺是否支持,。目前,,主流的平臺和文件系統(tǒng)都支持?jǐn)U展文件屬性,,比如FreeBSD(ZFS),、Linux(ext3、ext4,、ZFS),、MacOS等,。默認(rèn)情況下,,此操作是開啟的,如果已關(guān)閉,,可以通過“sudo mount -o remount,user_xattr {你的文件系統(tǒng)掛載路徑}”,,否則也會拋出UnsupportedOperationException。

Path path = Paths.get("/data/logs/web.log");
UserDefinedFileAttributeView view = Files.getFileAttributeView(path,UserDefinedFileAttributeView.class);
String name = "user.mimetype";
int size = view.size(name);//我個人認(rèn)為JDK應(yīng)該直接支持獲取屬性值,,而不是再周折一番
ByteBuffer buffer = ByteBuffer.allocate(size);
view.read(name,buffer);
buffer.flip();
String value = Charset.defaultCharset().decode(buffer).toString();
System.out.println(value);
//其他操作,,比如list獲取所有屬性的列表等,。//寫入或者跟新自定義屬性
view.write(name,Charset.defaultCharset().encode("text/html"));

3,、FileSystem

FileStore是新增的API,用于描述底層存儲系統(tǒng),,一個平臺有多個FileStore,我們可以通過FileSystem獲取FileStore的列表,,以及每個store的存儲狀態(tài)、文件列表等,。

Path path = Paths.get("/data/logs/web.log");
path.getFileSystem().getFileStores();//獲取文件所屬的文件系統(tǒng)的所有的存儲器,。//當(dāng)前文件系統(tǒng)所能支持的FileAttributeView,此后可以對文件使用相應(yīng)的view獲取或者修改屬性
Set<String> viewNames = FileSystems.getDefault().supportedFileAttributeViews();
System.out.println(viewNames);//basic,,unix,posix,,owner,,dos等

//或者,,全局
//遍歷所有的磁盤存儲
Iterable<FileStore> fileStores = FileSystems.getDefault().getFileStores();//獲取默認(rèn)文件系統(tǒng)的所有存儲器
for(FileStore store : fileStores) {
   System.out.println("\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-");
   System.out.println("className:" store.getClass().getName());
   System.out.println("name:" store.name());//磁盤名稱
   System.out.println("type:" store.type());//類型
   System.out.println("readOnly:" store.isReadOnly());//是否為只讀
   System.out.println("usableSpace:" store.getUsableSpace() "/" store.getTotalSpace());
   boolean supported = store.supportsFileAttributeView(BasicFileAttributeView.class);
   //或者
   //boolean supported =  store.supportsFileAttributeView("basic");
   //fileStore的屬性,不同于FileAttributes,,這些屬性應(yīng)該與FileStore的各個實(shí)現(xiàn)類對應(yīng),。Long totalSpace = (Long)store.getAttribute("totalSpace");
   System.out.println(totalSpace);

可以獲取每個FileStore支持的FileAttributeView,,此后即可通過Files.getFileAttributeView()來獲取相應(yīng)的視圖類,。每個view都有簡寫名稱,,比如BasicFileAttributeView.name()返回其簡寫名稱為“basic”,。目前JDK支持很多FileAttributeView,,比如BasicFileAttributeView,、UnixFileAttributeView等等,以及允許自定義的UserDefinedFileAttributeView等,。JDK將獲取文件屬性,、修改文件屬性的操作全部基于對應(yīng)的FileAttributeView類來實(shí)現(xiàn)。

PosixFileAttributeView view = Files.getFileAttributeView(path,PosixFileAttributeView.class);
PosixFileAttributes fileAttributes = view.readAttributes();

此外,,根據(jù)FileStore的底層存儲不同,,有多種實(shí)現(xiàn),,可以參看FileStore的實(shí)現(xiàn)類,比如UnixFileStore,、BsfFileStore(Mac)等,,每個FileStore所能支持的attribute也不太相同,需要根據(jù)其對應(yīng)的實(shí)現(xiàn)類獲取,,也可以使用FileStore.getAttribute()來獲取,,但是屬性名需要與類中支持的屬性名對應(yīng)。

4,、目錄操作

JAVA中目錄也用Path表示,,其基本屬性與File一樣。

4.1,、列舉根目錄

//遍歷文件系統(tǒng)的所有根目錄
Iterable<Path> roots = FileSystems.getDefault().getRootDirectories();
for(Path root : roots) {
   System.out.print(root);
}

4.2,、創(chuàng)建、刪除

Path dir = Paths.get("/data/xyz");
Files.createDirectories(dir);
Files.createDirectory(dir);

其中createDirectory()方法是一個“嚴(yán)格校驗(yàn)”的方法,,如果父路徑不存在則會拋出異常,,如果路徑已經(jīng)存在或者同名文件存在則會拋出異常,,簡單來說此方法只能創(chuàng)建最后一級目錄(且此前不存在),。對于createDirectories()方法,,比較兼容,,會逐層校驗(yàn)并創(chuàng)建父路徑,,如果不存在則創(chuàng)建,。

創(chuàng)建目錄時,,也可以像文件那樣,,指定文件屬性(包括權(quán)限)

Path dir = Paths.get("/data/xyz/12x/123x");
Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("\-rw\-rw\-\-\-\-");
FileAttribute<Set<PosixFilePermission>> fileAttribute = PosixFilePermissions.asFileAttribute(permissions);
Files.createDirectories(dir,fileAttribute);

4.3,、遍歷目錄

Path dir = Paths.get("/data");
DirectoryStream<Path> stream = Files.newDirectoryStream(dir);
for (Path path : stream) {
   System.out.println(path);
}
stream.close();

stream方式會遍歷指定目錄下的所有文件,包括文件,。目錄,。連接、隱藏文件或者目錄等,。

此外,,JDK還支持基于filter模式,,在遍歷時過濾“非必要”的文件或者目錄。

Path dir = Paths.get("/data");
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
   @Override
   public boolean accept(Path entry) throws IOException {
       return Files.isRegularFile(entry);
   }
};
DirectoryStream<Path> stream = Files.newDirectoryStream(dir,filter);
for (Path path : stream) {
   System.out.println(path);
}
stream.close();

4.4,、Glob文件過濾器

NIO2中新增支持了基于Glob的文件過濾器,,一種類似于正則表達(dá)式的匹配語法;glob是來自unlix(shell指令)用于文件匹配的表達(dá)式,,很多主流語言和平臺(dos,、window)都支持,不過不同語言對glob的支持程度不同(需要注意),。

1,、*:匹配任意多個任意字符,包括空字符(none),。比如“/data/*.log”匹配“data”目錄下所有以“.log”結(jié)尾的文件,。

2、**:類似于*,,匹配任意多個字符,,不過它可以越過目錄分割符,此語法通常用于匹配全路徑,。比如:“/data/**”

3,、?:只匹配一個字符。

4,、\:轉(zhuǎn)義符,,用于轉(zhuǎn)義特殊字符,比如“\”,、“-”,、“{”、“}”,、“[”等等。比如需要匹配“{”那么其字面表達(dá)式為“\{”,,“\\”用于匹配單斜杠,。

5、!:非,不包含,,通常配合[]使用,。(貌似不支持^)

6、{}:指定一組子規(guī)則,,比如:

1){sum,moon,stars}:匹配“sun”或者“moon”或者“starts”(其一即可),,子規(guī)則使用“,”分割。

2){temp*,tmp*}:匹配以temp或者tmp開頭的所有字符串,。

7,、[]:匹配一組字符串中的單個字符,如果字符串集中包含“-”則匹配區(qū)間中單個字符,。比如[abc]匹配“a”或者“b”或者“c”,[a-z]匹配a到z小寫字符中的一個,,[0-9]匹配0~9任意一個數(shù)字??梢曰旌鲜褂?,比如[abce-g]匹配“a”、“b”,、“c”,、“e”、“f”,、“g”,,[!a-c]匹配除a、b,、c之外的任意一個字符,。復(fù)合子規(guī)則使用“,”分割,比如[a-z,0-9]匹配a~z或者0~9任意一個字符,。

在[]中,,“*”、“?”,、“\”只匹配其自己(字面),,如果“-”在[]內(nèi)且是第一個字符或者在!之后,也匹配自己,。

8,、文件中的前導(dǎo)字符,、“.”將作為普通字符對待,。比如“*”可以匹配“.tmp”這個文件,F(xiàn)Iles.isHidden()可以用來檢測此文件為隱藏文件,。

9,、其他所有字符匹配其自己(取決于因平臺而已的實(shí)現(xiàn)方式,包括路徑分隔符等),。

示例:

1,、*.html匹配任意“.html”結(jié)尾的文件。

2,、???:匹配任意三個字符(包括數(shù)字字符)

3,、*[0-9]*:匹配包含一個數(shù)字的任意多個字符。

4,、*.{htm,html},,匹配任意以“html”或者“htm”結(jié)尾的字符串。

GLobbing表達(dá)式,,一種比較便捷的過濾策略,,對于一些簡單的操作(主要是只根據(jù)文件或者路徑名特性匹配時),可以不使用Filter的情況下完成,,當(dāng)然glob的內(nèi)部實(shí)現(xiàn)仍然是基于封裝的Filter來實(shí)現(xiàn)(PathMatcher),;但是glob語法相對簡單,JDK NIO2有關(guān)文件過濾表達(dá)式,,可以同時支持glob和正則表達(dá)式,。稍后介紹如何使用PathMatcher來遍歷文件或者目錄樹。

Path dir = Paths.get("/data");
//內(nèi)部,,默認(rèn)會對glob表達(dá)式增加前綴,glob,為了兼容PathMatcher
DirectoryStream<Path> stream = Files.newDirectoryStream(dir,"\*.txt");
for (Path path : stream) {
   System.out.println(path);
}
stream.close();

4.5、操作鏈接文件

硬連接(或者連接):

1)文件有相同的 inode 及 data block,;

2)只能對已存在的文件進(jìn)行創(chuàng)建;

3)不能交叉文件系統(tǒng)進(jìn)行硬鏈接的創(chuàng)建,;

4)不能對目錄進(jìn)行創(chuàng)建,只可對文件創(chuàng)建;

5)刪除一個硬鏈接文件并不影響其他有相同 inode 號的文件,。

軟連接(符號連接):軟鏈接與硬鏈接不同,,若文件用戶數(shù)據(jù)塊中存放的內(nèi)容是另一文件的路徑名的指向,則該文件就是軟連接,。軟鏈接就是一個普通文件,,只是數(shù)據(jù)塊內(nèi)容有點(diǎn)特殊。軟鏈接有著自己的 inode 號以及用戶數(shù)據(jù)塊,。因此軟鏈接的創(chuàng)建與使用沒有類似硬鏈接的諸多限制:

1)軟鏈接有自己的文件屬性及權(quán)限等,;

2)可對不存在的文件或目錄創(chuàng)建軟鏈接;

3)軟鏈接可交叉文件系統(tǒng),;

4)軟鏈接可對文件或目錄創(chuàng)建,;

5)創(chuàng)建軟鏈接時,鏈接計數(shù) i_nlink 不會增加,;

6)刪除軟鏈接并不影響被指向的文件,,但若被指向的原文件被刪除,則相關(guān)軟連接被稱為死鏈接(即 dangling link,,若被指向路徑文件被重新創(chuàng)建,,死鏈接可恢復(fù)為正常的軟鏈接)。

##創(chuàng)建連接
ln 目標(biāo) 連接名
## 創(chuàng)建軟連接
ln \-s 目標(biāo) 連接名

##查看軟連接目標(biāo)指向,,對于硬連接是不顯示,。ls \-l 軟連接文件

##通過stat指令可以查看軟硬連接的inode和block信息
##發(fā)現(xiàn)硬連接與目標(biāo)文件的信息完全一致。##軟連接文件有單獨(dú)的inode和block,。

創(chuàng)建連接

Path target = Paths.get("/data/test.log");
//target必須存在
Files.createLink(Paths.get("/data/hard\-link.log"),target);
Files.createSymbolicLink(Paths.get("/data/soft\-link.log"),target);

//檢測文件是否為軟連接問題
boolean isSymbolicLink = Files.isSymbolicLink(Paths.get("/data/soft\-link.log"));

Path target2 = Files.readSymbolicLink(Paths.get("/data/soft\-link.log"));
//檢測是否為同一個文件
System.out.println(Files.isSameFile(target,target2));//true
System.out.println(Files.isSameFile(target,Paths.get("/data/hard\-link.log")));//true
System.out.println(Files.isSameFile(target,Paths.get("/data/soft\-link.log")));//true

通過Files.isSameFile()比較,,我們會發(fā)現(xiàn),無論是軟連接,、硬鏈接,,都與目標(biāo)文件是同一個文件。

4.6,、查找文件

前文中介紹了有關(guān)PathMatcher,,在JAVA NIO2中用于匹配文件的表達(dá)式,可以支持glob和正則表達(dá)式(regex)兩種方式,。其中g(shù)lob的語法更接近linux shell,,regex是更廣泛、更豐富的一種方式,。比如文件:/data/test.log

Path path = Paths.get("/data/test.log");
PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:\*\*.log");

System.out.println(pathMatcher.matches(path));

//基于正則
pathMatcher = FileSystems.getDefault().getPathMatcher("regex:.\*\\\\.log");
System.out.println(pathMatcher.matches(path));

表達(dá)式規(guī)則:syntax:pattern,,其中合法的syntax為“glob”和“regex”,;需要注意這兩種表達(dá)式的區(qū)別。內(nèi)部實(shí)現(xiàn)也比較簡單,,對于glob字符串將會轉(zhuǎn)化為正則表達(dá)式字符串,,然后統(tǒng)一使用正則匹配。

4.7,、遞歸遍歷目錄樹

曾經(jīng),,使用JAVA遍歷文件數(shù)是一件比較繁瑣的事情,在NIO2中增加了原生提供了此操作,。主要API為FileVisitor,,其簡單實(shí)現(xiàn)類為SimpleFileVisitor:

1、preVisitDirectory:在瀏覽目錄之前,。前置操作,。比如遍歷并復(fù)制文件時,可以在進(jìn)入目錄之前,,創(chuàng)建遷移的目標(biāo)新目錄,。

2、postVisitDirectory:在瀏覽目錄中所有文件之后(瀏覽其他目錄之前),。后置操作,。

3、visitFile:瀏覽文件,,Path和BaseFileAttributes會傳遞入方法,。

4、visitFileFailed:瀏覽文件失敗時調(diào)用,,比如文件屬性無法獲取,、目錄無法打開等異常時,調(diào)用此方法,,同時傳入Path和Exception,。

簡單的遍歷(查找、篩選匹配)

Path dir = Paths.get("/data/redis");
Stream<Path> stream = Files.walk(dir);
stream.forEach(path \-> {
   System.out.println(path);
});
stream.close();

復(fù)雜遍歷(遍歷查找,、文件遷移校驗(yàn))

public static void main(String\[\] args) throws Exception{
   Path dir = Paths.get("/data/redis");
   Files.walkFileTree(dir,new Finder());
}

public static class Finder implements FileVisitor<Path> {

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

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

   @Override
   public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
       System.out.println("visitFileFailed:" file ",exception:" (exc != null ? exc.getMessage() : "\-"));
       return FileVisitResult.CONTINUE;
   }

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

FileVisitResult用于表示執(zhí)行狀態(tài):

1)CONTINUE:表示繼續(xù)執(zhí)行(繼續(xù)下一步操作)

2)TERMINATE:終止遞歸遍歷,,其他的后續(xù)方法不會被執(zhí)行,尚未瀏覽的文件也將不會被訪問,。

3)SKIP_SUBTREE:跳過子樹,,即當(dāng)前目錄以及其子目錄都將被跳過。適用在preVisitDirectory(),,其他方法返回此值則等效于CONTINUE,。

4)SKIP_SIBLINGS:跳過此文件(或者目錄)的同級文件或者文件,適用在postVisitDirectory(),,如果preVisitDirectory返回此值,,則當(dāng)前目錄也會跳過,,且postVisitDirectory()不會被執(zhí)行。

End

好了,,關(guān)于NIO2新增的API,,就已經(jīng)介紹完畢了。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多