<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在前面的文章Linux命令系列之ls——原來最簡單的ls這麼複雜當中,我們仔細的介紹了關於ls命令的使用和輸出結果,在本篇文章當中我們用Java程式碼自己實現ls命令,更加深入的瞭解ls命令。
如果我們使用Java實現一個簡單的ls命令其實並不難,因為Java已經給我們提供了一些比較方便和檔案系統相關的api了,困難的是理解api是在做什麼事兒!
事實上這些api都是作業系統給我們提供的,然後Java進行了一些列的封裝,將這些操作給我們進行提供,我們仔細來看一下封裝的層次,首先作業系統會給我們提供很多系統呼叫用於和裝置(磁碟、CPU)進行互動,比如說和檔案的互動就是讀寫資料,當然我們的Java程式也需要這些操作,因此JVM也需要給我們提供這些操作,因此JVM就對系統呼叫進行了一系列的封裝,在Java當中具體的形式就是用native修飾的方法。
如果你是一個比較有經驗Java程式設計師那麼一定見過Java當中的native
方法,這些方法都是Java給我們封裝的底層介面,比如說在FileInputStream
當中有一個read
方法,這個方法就是讀取檔案當中的內容,我們看一下這個方法是如何實現的:
public int read() throws IOException { return read0(); }
這裡讓大家的感受更加深入一點,我在這裡貼一張FileInputStream
的原始碼圖片:
從上面的圖看當我們呼叫FileInputStream
方法的時候確實呼叫了native方法。我們再來看一些與檔案操作相關的api,他們也是使用Java給我們封裝的native方法實現的。
上面主要談了一些基本的檔案操作過程的原理,簡要說明了Java將很多系統操作封裝成native方法供我們呼叫,現在我們來看看要想實現ls命令,我們需要哪些api。
在Java當中給我們提供了一個類File
,我們可以使用這個類去得到一個目錄下面有哪些檔案和目錄。
public void fileTest() { File file = new File("./"); // file.listFiles() 將當前 file 對應的目錄下所有的檔案和目錄都得到 for (File listFile : file.listFiles()) { System.out.println(listFile.getName()); // 將檔案或者目錄的名字列印 }
在Java當中給我們提供了一個工具類檢視檔案的一些元資訊(metadata),比如說檔案的uid(使用者id)、gid(使用者組id)、檔案的大小和檔案的連結數目(nlink)。
Path path = Paths.get("."); System.out.println(Files.getAttribute(path, "unix:dev")); // 列印儲存當前目錄資料的裝置的裝置id System.out.println(Files.getAttribute(path, "unix:ino")); // 列印儲存當前目錄資料inode號 System.out.println(Files.getAttribute(path, "unix:mode"));// 列印儲存當前目錄資料的mode資料 這個資料主要用於表示檔案的型別 System.out.println(Files.getAttribute(path, "unix:uid")); // 列印儲存當前目錄所屬使用者的使用者id System.out.println(Files.getAttribute(path, "unix:gid")); // 列印儲存當前目錄所屬組的組id System.out.println(Files.getAttribute(path, "unix:size"));// 列印儲存當前目錄資料所佔的空間大小 System.out.println(Files.getAttribute(path, "unix:nlink"));// 列印儲存當前目錄資料的連結數
除了上面的方式,我們還可以使用下面的方式去得到檔案的後設資料:
public void attrTest02() throws IOException { Path path = Paths.get("."); // 傳入的引數就是檔案或者目錄的路徑 這個傳入的就是當前目錄 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()); // 列印檔案的許可權 是否可讀 可寫 可執行 System.out.println(attr.lastAccessTime()); // 上一次存取時間 System.out.println(attr.creationTime()); // 建立時間 System.out.println(attr.lastModifiedTime()); // 上一次修改時間 System.out.println(attr.fileKey()); // 列印檔案其他相關引數 主要是裝置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
在Java當中給我們提供了一個類表示檔案的9中許可權(檔案的作者的讀寫執行,作者所在組的讀寫執行,和其他人的讀寫執行,一共九種許可權):
package java.nio.file.attribute; public enum PosixFilePermission { /** * Read permission, owner. 作者讀許可權 */ OWNER_READ, /** * Write permission, owner. 作者寫許可權 */ OWNER_WRITE, /** * Execute/search permission, owner. 作者的執行許可權 */ OWNER_EXECUTE, /** * Read permission, group. 作者所在組的讀許可權 */ GROUP_READ, /** * Write permission, group.作者所在組的寫許可權 */ GROUP_WRITE, /** * Execute/search permission, group. */ GROUP_EXECUTE, /** * Read permission, others. 其他人讀許可權 */ OTHERS_READ, /** * Write permission, others. 其他人寫許可權 */ OTHERS_WRITE, /** * Execute/search permission, others. 其他人執行許可權 */ OTHERS_EXECUTE; }
在上面檢視檔案或者目錄的後設資料的時候我們已經得到的檔案的所有許可權資訊:
System.out.println(attr.permissions()); //[GROUP_READ, OTHERS_EXECUTE, OWNER_WRITE, OWNER_EXECUTE, OTHERS_READ, OWNER_READ, GROUP_EXECUTE]
函數返回的是一個集合set
,裡面存放的就是檔案的各種許可權的資訊,比如在我們的例子當中我們可以看到,有組讀,其他人執行,作者自己寫,作者執行,其他人讀,作者讀許可權,如果我們想判斷某種許可權,只需要看看集合當中是否包含即可。
在上面我們已經談到了所有的關於實現 ls 命令的細節了,接下來看一下我們的程式碼實現:
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的話,就應該很容易理解了。下面我們看看程式的輸出結果:
可以看到我們的程式的輸出結果和ls命令的輸出結果是一樣的,只是在時間的表示上有所差別而已,這一點沒什麼關係。
以上就是通過Java實現自己動手寫ls命令的詳細內容,更多關於Java實現ls命令的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45