更新時(shí)間:2022-08-24 來(lái)源:黑馬程序員 瀏覽量:
作者原創(chuàng):黑馬程序員講師——?jiǎng)⒉?版權(quán)所有
引入
Markdown文檔的好處
相信很多朋友在開(kāi)發(fā)和工作過(guò)程中都會(huì)使用MarkDown格式來(lái)編寫(xiě)文檔,Markdown文檔的好處多多:
- 它基于純文本,方便修改和共享;
- 幾乎可以在所有的文本編輯器中編寫(xiě);
- 有眾多編程語(yǔ)言的實(shí)現(xiàn)和應(yīng)用的相關(guān)擴(kuò)展;
- 在 GitHub 等網(wǎng)站中有很好的應(yīng)用;
- 很容易轉(zhuǎn)換為 HTML 文檔或其他格式;
- 適合用來(lái)編寫(xiě)文檔、記錄筆記、撰寫(xiě)文章。
而在眾多的MarkDown文檔的編輯器中,我們比較常用的一款工具是Typora,前幾年是免費(fèi)的,最近1.0正式版以后開(kāi)始要收費(fèi)了。
Typora的優(yōu)勢(shì)
Typora容許隨時(shí)隨地開(kāi)展無(wú)縫拼接瀏覽,從而可以在編輯的同時(shí)及時(shí)的看到效果。筆者現(xiàn)在寫(xiě)這個(gè)文檔就是使用的這個(gè)工具。它有以下好處:
1. 在Win,Mac和Linux上能用
2. 它具備審校作用,能夠檢查拼讀和英語(yǔ)的語(yǔ)法
3. 全自動(dòng)匹配Markdown標(biāo)記,比如括弧
4. 支持大概100種語(yǔ)言并支持英語(yǔ)的語(yǔ)法突顯
5. 豐富多彩的作用和鍵盤(pán)快捷鍵
6. 與內(nèi)聯(lián)公式和顯示信息公式適配
Typora的不足
工具可以做到圖文并茂的編寫(xiě)文檔,所有插入的圖片默認(rèn)放在當(dāng)前文檔的assets目錄下,也可以通過(guò)設(shè)置指定圖片保存的位置,使用起來(lái)很方便。
但不足的是,如果文檔進(jìn)行了修改,圖片從文檔中刪除了,殘留在當(dāng)前目錄下的assets目錄下的圖片并不會(huì)一同刪除。隨著文檔不斷的更新和修改,這個(gè)目錄下的圖片文件會(huì)越留越多,有時(shí)多達(dá)幾十M。不但占用空間,而且毫無(wú)用處。
<img src="assets/image-20220721102804143.png" alt="image-20220721102804143" style="zoom:80%;" />
雖然我們可以手動(dòng)點(diǎn)擊每張圖片查看具體是哪張圖片,再一張張手工去刪除,但圖片如果多的話,也是很繁瑣的事情,而且考驗(yàn)人的耐心。
<img src="assets/image-20220721102924085.png" alt="image-20220721102924085" style="zoom:80%;" />
我們能不能自己寫(xiě)個(gè)程序,分析整個(gè)Markdown文檔中的圖片地址,然后批量刪除呢?有了這個(gè)想法以后,我就自己花了一些時(shí)間做了一個(gè),目前已經(jīng)使用了一年多了,沒(méi)有發(fā)現(xiàn)什么問(wèn)題,特意寫(xiě)出來(lái)分享給大家。
實(shí)現(xiàn)思路
思路
首先我們需要分析Markdown文檔的格式,它本質(zhì)上就是一個(gè)文本文件。大致實(shí)現(xiàn)思路如下:
1. 使用Java中的IO流API對(duì)文檔進(jìn)行解析
2. 找到文檔中圖片的地址,使用正則表達(dá)式進(jìn)行分析,將所有文檔中出現(xiàn)的圖片文件名保存成一個(gè)集合。
3. 再到assets文件夾下去查找所有的圖片文件名,也保存成一個(gè)集合。
4. 對(duì)比兩個(gè)文件名的集合,將在assets目錄下存在的文件,文檔中不存在的圖片文件全部找出來(lái)
5. 刪除所有不存在的圖片文件
源代碼
```java package org.newboy.utils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.HashSet; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author NewBoy * @version 1.0 * @since 2020-12-04 * 刪除MarkDown目錄下多余的圖片文件 */ public class MarkDownPictureCleaner { public static void main(String[] args) { System.out.println("=== MarkDown下冗余圖片清理工具(開(kāi)發(fā)者:NewBoy 版本:1.0) ==="); Scanner scanner = new Scanner(System.in); //MarkDown的文件名 String path = null; try { System.out.println("請(qǐng)輸入Markdown文件的路徑和文件名(可直接將md文件拖到命令窗口):"); path = scanner.nextLine(); } catch (Exception e) { // 用戶(hù)可能按下 Ctrl + C 終止程序 System.out.println("程序結(jié)束!"); scanner.close(); System.exit(0); } // 預(yù)檢查,判斷用戶(hù)輸入的文件是否存在 File file = null; //圖片所在目錄 String picDir = null; if (StringUtils.isNotBlank(path)) { //如果用戶(hù)在DOS命令窗口拖入,前后有雙引號(hào),去掉雙引號(hào) path = path.trim().replace("\"", ""); //創(chuàng)建文件對(duì)象 file = new File(path); if (!file.exists()) { System.out.println("Markdown文件不存在!"); file = null; } else { System.out.println("請(qǐng)輸入圖片目錄(默認(rèn)為assets):"); //圖片所在目錄 picDir = scanner.nextLine(); //如果為空,空串,或者空格 if (StringUtils.isBlank(picDir)) { picDir = "assets"; } } } // 讀取 Markdown 文件的內(nèi)容 String content = null; if (file != null) { // 如果用戶(hù)輸入的文件不存在,跳過(guò)此次操作 System.out.println("您輸入的路徑:" + file.getAbsolutePath()); try { content = FileUtils.readFileToString(file, "UTF-8"); } catch (IOException e) { System.out.println("文件讀取異常:" + e.getMessage()); content = null; } } if (content != null) { // 找出 Markdown 文件中所有圖片的引用 String regex = "(!\\[.*\\])(\\(.*\\))|(<img\\b.*?(?:\\>|\\/>))"; // 捕獲組,匹配類(lèi)似于 "![*](*)" 的字符串 Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(content); HashSet<String> picturesInMarkdown = new HashSet<>(); while (matcher.find()) { String ref = matcher.group(0); String picture = null; int beginIndex = 0; int endIndex = 0; //如果是!開(kāi)頭 if (ref.startsWith("!")) { // 獲取圖片名稱(chēng) beginIndex = ref.lastIndexOf("/") + 1; endIndex = ref.length() - 1; } else if (ref.startsWith("<")) { //或者以<開(kāi)頭的 beginIndex = ref.indexOf("/") + 1; endIndex = ref.indexOf('"', beginIndex); } picture = ref.substring(beginIndex, endIndex); //logger.info(picture); // 保存圖片名稱(chēng) picturesInMarkdown.add(picture); } System.out.println("MarkDown中一共有:" + picturesInMarkdown.size() + "個(gè)圖片文件"); // 列出 Markdown 文件所在目錄中的圖片名稱(chēng) File directory = file.getParentFile(); String[] extensions = {"png", "jpg", "jpeg", "bmp"}; // 圖片擴(kuò)展名 boolean recursive = true; // 不掃描子目錄 HashSet<String> picturesInDirectory = new HashSet<String>(); //獲取所有文件的集合 Collection<File> files = FileUtils.listFiles(directory, extensions, recursive); System.out.println("圖片目錄下一共有:" + files.size() + "個(gè)圖片文件"); for (File picture : files) { String name = picture.getName(); picturesInDirectory.add(name); } // 列出冗余圖片,并將其刪除 picturesInDirectory.removeAll(picturesInMarkdown); int count = 0; for (String picture : picturesInDirectory) { String pic = directory.getAbsolutePath() + File.separator + picDir + File.separator + picture; System.out.println("刪除圖片:" + pic); FileUtils.deleteQuietly(new File(pic)); count++; } System.out.println("操作完成,共刪除了" + count + "個(gè)圖片文件!"); } scanner.close(); System.exit(0); } } ```
使用說(shuō)明
因?yàn)槭褂肑ava編寫(xiě),使用需要安裝Java虛擬機(jī),為了方便用戶(hù)的使用,特意編寫(xiě)了一個(gè)DOS下的命令行
``` @echo off java -jar markdown-picture-cleaner-1.0.jar pause ```
1. 運(yùn)行的時(shí)候會(huì)出現(xiàn)一個(gè)窗口,需要輸入Markdown文件的路徑和文件名,這個(gè)比較麻煩,但可以將需要清理的文件直接拖到窗口中,則會(huì)自動(dòng)填充文件路徑和文件名
2. 拖到窗口中會(huì)自動(dòng)輸入路徑和文件名
<img src="assets/image-20220721105304355.png" alt="image-20220721105304355" style="zoom:80%;" />
3. 按下回車(chē)會(huì)讓你輸入圖片的目錄,默認(rèn)是當(dāng)前目錄下的assets,如果圖片是在這個(gè)目錄下,直接按回車(chē)即可。
4. 最后顯示清理的結(jié)果
最后
以上是給各位讀者提供了一種思路,大家也可以使用其它語(yǔ)言進(jìn)行編寫(xiě),比如可以直接運(yùn)行在Windows下的VC或是VB,還有圖形界面,用戶(hù)體驗(yàn)會(huì)更好一些。同時(shí)軟件本身只提供了基礎(chǔ)功能,作者提供了源代碼,懂Java的朋友可以在這個(gè)基礎(chǔ)上去進(jìn)一步完善。