通過Java實(shí)現(xiàn)自己動手寫ls命令
介紹
在前面的文章Linux命令系列之ls——原來最簡單的ls這么復(fù)雜當(dāng)中,我們仔細(xì)的介紹了關(guān)于ls命令的使用和輸出結(jié)果,在本篇文章當(dāng)中我們用Java代碼自己實(shí)現(xiàn)ls命令,更加深入的了解ls命令。
代碼實(shí)現(xiàn)
文件操作的基本原理
如果我們使用Java實(shí)現(xiàn)一個簡單的ls命令其實(shí)并不難,因?yàn)镴ava已經(jīng)給我們提供了一些比較方便和文件系統(tǒng)相關(guān)的api了,困難的是理解api是在做什么事兒!
事實(shí)上這些api都是操作系統(tǒng)給我們提供的,然后Java進(jìn)行了一些列的封裝,將這些操作給我們進(jìn)行提供,我們仔細(xì)來看一下封裝的層次,首先操作系統(tǒng)會給我們提供很多系統(tǒng)調(diào)用用于和設(shè)備(磁盤、CPU)進(jìn)行交互,比如說和文件的交互就是讀寫數(shù)據(jù),當(dāng)然我們的Java程序也需要這些操作,因此JVM也需要給我們提供這些操作,因此JVM就對系統(tǒng)調(diào)用進(jìn)行了一系列的封裝,在Java當(dāng)中具體的形式就是用native修飾的方法。
如果你是一個比較有經(jīng)驗(yàn)Java程序員那么一定見過Java當(dāng)中的native
方法,這些方法都是Java給我們封裝的底層接口,比如說在FileInputStream
當(dāng)中有一個read
方法,這個方法就是讀取文件當(dāng)中的內(nèi)容,我們看一下這個方法是如何實(shí)現(xiàn)的:
????public?int?read()?throws?IOException?{ ????????return?read0(); ????}
這里讓大家的感受更加深入一點(diǎn),我在這里貼一張FileInputStream
的源代碼圖片:
從上面的圖看當(dāng)我們調(diào)用FileInputStream
方法的時候確實(shí)調(diào)用了native方法。我們再來看一些與文件操作相關(guān)的api,他們也是使用Java給我們封裝的native方法實(shí)現(xiàn)的。
上面主要談了一些基本的文件操作過程的原理,簡要說明了Java將很多系統(tǒng)操作封裝成native方法供我們調(diào)用,現(xiàn)在我們來看看要想實(shí)現(xiàn)ls命令,我們需要哪些api。
查看一個目錄下面有哪些文件和目錄
在Java當(dāng)中給我們提供了一個類File
,我們可以使用這個類去得到一個目錄下面有哪些文件和目錄。
??public?void?fileTest()?{ ????File?file?=?new?File("./"); ????//?file.listFiles()?將當(dāng)前?file?對應(yīng)的目錄下所有的文件和目錄都得到 ????for?(File?listFile?:?file.listFiles())?{ ??????System.out.println(listFile.getName());?//?將文件或者目錄的名字打印 ????}
查看文件和目錄的元數(shù)據(jù)
在Java當(dāng)中給我們提供了一個工具類查看文件的一些元信息(metadata),比如說文件的uid(用戶id)、gid(用戶組id)、文件的大小和文件的鏈接數(shù)目(nlink)。
??Path?path?=?Paths.get("."); ??System.out.println(Files.getAttribute(path,?"unix:dev"));?//?打印存儲當(dāng)前目錄數(shù)據(jù)的設(shè)備的設(shè)備id ??System.out.println(Files.getAttribute(path,?"unix:ino"));?//?打印存儲當(dāng)前目錄數(shù)據(jù)inode號 ??System.out.println(Files.getAttribute(path,?"unix:mode"));//?打印存儲當(dāng)前目錄數(shù)據(jù)的mode數(shù)據(jù)?這個數(shù)據(jù)主要用于表示文件的類型 ??System.out.println(Files.getAttribute(path,?"unix:uid"));?//?打印存儲當(dāng)前目錄所屬用戶的用戶id ??System.out.println(Files.getAttribute(path,?"unix:gid"));?//?打印存儲當(dāng)前目錄所屬組的組id ??System.out.println(Files.getAttribute(path,?"unix:size"));//?打印存儲當(dāng)前目錄數(shù)據(jù)所占的空間大小 ??System.out.println(Files.getAttribute(path,?"unix:nlink"));//?打印存儲當(dāng)前目錄數(shù)據(jù)的鏈接數(shù)
除了上面的方式,我們還可以使用下面的方式去得到文件的元數(shù)據(jù):
??public?void?attrTest02()?throws?IOException?{ ????Path?path?=?Paths.get(".");?//?傳入的參數(shù)就是文件或者目錄的路徑?這個傳入的就是當(dāng)前目錄 ????PosixFileAttributes?attr?=?Files.readAttributes(path,?PosixFileAttributes.class,?NOFOLLOW_LINKS); ????System.out.println(attr.owner());?//?打印用戶名 ????System.out.println(attr.group());?//?打印用戶組名 ????System.out.println(attr.isRegularFile());?//?是不是一般文件 ????System.out.println(attr.isSymbolicLink());?//?是不是一個符號鏈接 ????System.out.println(attr.isDirectory());?//?是否是目錄 ????System.out.println(attr.isOther());?//其他類型 ????System.out.println(attr.permissions());?//?打印文件的權(quán)限?是否可讀?可寫?可執(zhí)行 ????System.out.println(attr.lastAccessTime());?//?上一次訪問時間 ????System.out.println(attr.creationTime());?//?創(chuàng)建時間 ????System.out.println(attr.lastModifiedTime());?//?上一次修改時間 ????System.out.println(attr.fileKey());?//?打印文件其他相關(guān)參數(shù)?主要是設(shè)備id和inode編號 ????System.out.println(attr.size());?//?文件的大小 ??}
root?//?這里是用戶名 root?//?這里是用戶組名 false false true false [GROUP_READ,?OTHERS_EXECUTE,?OWNER_WRITE,?OWNER_EXECUTE,?OTHERS_READ,?OWNER_READ,?GROUP_EXECUTE] 2022-10-09T18:08:47.791072133Z 2022-10-09T13:10:51Z 2022-10-09T18:08:23.746949182Z (dev=1000012,ino=16176823) 192
文件權(quán)限
在Java當(dāng)中給我們提供了一個類表示文件的9中權(quán)限(文件的作者的讀寫執(zhí)行,作者所在組的讀寫執(zhí)行,和其他人的讀寫執(zhí)行,一共九種權(quán)限):
package?java.nio.file.attribute; public?enum?PosixFilePermission?{ ????/** ?????*?Read?permission,?owner.?作者讀權(quán)限 ?????*/ ????OWNER_READ, ????/** ?????*?Write?permission,?owner.?作者寫權(quán)限 ?????*/ ????OWNER_WRITE, ????/** ?????*?Execute/search?permission,?owner.?作者的執(zhí)行權(quán)限 ?????*/ ????OWNER_EXECUTE, ????/** ?????*?Read?permission,?group.?作者所在組的讀權(quán)限 ?????*/ ????GROUP_READ, ????/** ?????*?Write?permission,?group.作者所在組的寫權(quán)限 ?????*/ ????GROUP_WRITE, ????/** ?????*?Execute/search?permission,?group. ?????*/ ????GROUP_EXECUTE, ????/** ?????*?Read?permission,?others.?其他人讀權(quán)限 ?????*/ ????OTHERS_READ, ????/** ?????*?Write?permission,?others.?其他人寫權(quán)限 ?????*/ ????OTHERS_WRITE, ????/** ?????*?Execute/search?permission,?others.?其他人執(zhí)行權(quán)限 ?????*/ ????OTHERS_EXECUTE; }
在上面查看文件或者目錄的元數(shù)據(jù)的時候我們已經(jīng)得到的文件的所有權(quán)限信息:
System.out.println(attr.permissions()); //[GROUP_READ,?OTHERS_EXECUTE,?OWNER_WRITE,?OWNER_EXECUTE,?OTHERS_READ,?OWNER_READ,?GROUP_EXECUTE]
函數(shù)返回的是一個集合set
,里面存放的就是文件的各種權(quán)限的信息,比如在我們的例子當(dāng)中我們可以看到,有組讀,其他人執(zhí)行,作者自己寫,作者執(zhí)行,其他人讀,作者讀權(quán)限,如果我們想判斷某種權(quán)限,只需要看看集合當(dāng)中是否包含即可。
完整代碼實(shí)現(xiàn)
在上面我們已經(jīng)談到了所有的關(guān)于實(shí)現(xiàn) ls 命令的細(xì)節(jié)了,接下來看一下我們的代碼實(shí)現(xiàn):
import?java.io.File; import?java.io.IOException; import?java.nio.file.Files; import?java.nio.file.Path; import?java.nio.file.Paths; import?java.nio.file.attribute.PosixFileAttributes; import?java.nio.file.attribute.PosixFilePermission; import?java.util.Objects; import?java.util.Set; import?static?java.nio.file.LinkOption.NOFOLLOW_LINKS; public?class?LS?{ ??public?static?boolean?hasRight(Set<PosixFilePermission>?set,?PosixFilePermission ?????????????????????????????????permission)?{ ????return?set.contains(permission); ??} ??public?static?void?echoCharacter(Set<PosixFilePermission>?set)?{ ????//?user ????if?(hasRight(set,?PosixFilePermission.OWNER_READ)) ??????System.out.print('r'); ??????else ??????System.out.print('-'); ????if?(hasRight(set,?PosixFilePermission.OWNER_WRITE)) ??????System.out.print('w'); ????else ??????System.out.print('-'); ????if?(hasRight(set,?PosixFilePermission.OWNER_EXECUTE)) ??????System.out.print('x'); ????else ??????System.out.print('-'); ????//?group ????if?(hasRight(set,?PosixFilePermission.GROUP_READ)) ??????System.out.print('r'); ????else ??????System.out.print('-'); ????if?(hasRight(set,?PosixFilePermission.GROUP_WRITE)) ??????System.out.print('w'); ????else ??????System.out.print('-'); ????if?(hasRight(set,?PosixFilePermission.GROUP_EXECUTE)) ??????System.out.print('x'); ????else ??????System.out.print('-'); ????//?others ????if?(hasRight(set,?PosixFilePermission.OTHERS_READ)) ??????System.out.print('r'); ????else ??????System.out.print('-'); ????if?(hasRight(set,?PosixFilePermission.OTHERS_WRITE)) ??????System.out.print('w'); ????else ??????System.out.print('-'); ????if?(hasRight(set,?PosixFilePermission.OTHERS_EXECUTE)) ??????System.out.print('x'); ????else ??????System.out.print('-'); ??} ??public?static?void?echoType(PosixFileAttributes?attributes)?{ ????if?(attributes.isDirectory()) ??????System.out.print('d'); ????else?if?(attributes.isRegularFile()) ??????System.out.print('-'); ????else?if?(attributes.isSymbolicLink()) ??????System.out.print('l'); ????else ??????System.out.print('o'); ??} ??public?static?void?echoFileInformation(String?args)?throws?IOException?{ ????Path?path?=?Paths.get(args); ????PosixFileAttributes?attributes?=?Files.readAttributes(path,?PosixFileAttributes.class,?NOFOLLOW_LINKS); ????echoType(attributes); ????echoCharacter(attributes.permissions()); ????System.out.printf("\t%-2d",?Files.getAttribute(path,?"unix:nlink")); ????System.out.print("\t"?+?attributes.owner().getName()); ????System.out.print("\t"?+?attributes.group().getName()); ????System.out.printf("\t%-5d",?attributes.size()); ????System.out.printf("\t?%10s",?attributes.lastAccessTime()); ????System.out.println("\t"?+?path.getFileName()); ??} ??public?static?void?main(String[]?args)?throws?IOException?{ ????File?file?=?new?File(args[0]); ????for?(File?listFile?:?Objects.requireNonNull(file.listFiles()))?{ ??????echoFileInformation(listFile.toString()); ????} ??} }
上面的代碼很短,如果大家了解了上main所談到的api的話,就應(yīng)該很容易理解了。下面我們看看程序的輸出結(jié)果:
可以看到我們的程序的輸出結(jié)果和ls命令的輸出結(jié)果是一樣的,只是在時間的表示上有所差別而已,這一點(diǎn)沒什么關(guān)系。
以上就是通過Java實(shí)現(xiàn)自己動手寫ls命令的詳細(xì)內(nèi)容,更多關(guān)于Java實(shí)現(xiàn)ls命令的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot項目導(dǎo)入aliyun oss starter依賴后啟動報錯問題
這篇文章主要介紹了SpringBoot項目導(dǎo)入aliyun oss starter依賴后啟動報錯問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01Java 詳解單向加密--MD5、SHA和HMAC及簡單實(shí)現(xiàn)實(shí)例
這篇文章主要介紹了Java 詳解單向加密--MD5、SHA和HMAC及簡單實(shí)現(xiàn)實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02詳解Kotlin:forEach也能break和continue
這篇文章主要介紹了詳解Kotlin:forEach也能break和continue的相關(guān)資料,需要的朋友可以參考下2017-06-06