生成Markdown目录 字符串解析 MD
Markdown版本笔记 | 我的GitHub首页 | 我的博客 | 我的微信 | 我的邮箱 |
---|---|---|---|---|
MyAndroidBlogs | baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
文件 File 递归复制 修改后缀名 生成Markdown目录 字符串解析 MD
目录
使用方式
设计
一些常量
文件目录递归修改
递归修改文件后缀名并修改文件内容
递归修改文件后缀名
递归获取格式化后的文件名
文件复制
递归复制目录下的所有文件
复制一个文件或一个目录
复制一个文件并修改文件内容
其他工具方法
将字符串复制到剪切板
生成格式化的 Markdown 目录
生成 Markdown 的目录
用到的常量
递归为文件生成Markdown目录
插入的目录格式
其他一些用到的工具方法
源码
MDUtils
TOCUtils
DirUtils
使用方式
工具类的作用:生成GitHub
上仓库MyAndroidBlogs的REANME.MD
中博客的目录。
使用步骤式:
1、通过为知笔记导出指定目录下的所有文件,导出为U8格式的纯文本
2、执行以下代码
String DIR = "D:/为知笔记导出/导出的笔记";
MDUtils.modifyFile(new File(DIR)); //递归修改文件后缀名,同时删除不匹配的文件,并修改文件中不正常的字符
TOCUtils.insertToc(new File(DIR), false); //递归为 markdown 文件生成目录
DirUtils.getFormatFilesNames(new File(DIR)); //递归获取文件名,并将格式化后的内容复制到粘贴板
3、将粘贴板中的内容粘贴到REANME.MD
中
设计
一些常量
private static final String DIR = "D:/为知笔记导出/MyAndroidBlogs";
private static final String WEBSITE = "https://github.com/baiqiantao/MyAndroidBlogs/blob/master/";
private static final String FILTER = "MD";
private static final String SUFFIX_MD_TXT = ".md.txt";
private static final String SUFFIX_TXT = ".txt";
private static final String SUFFIX_MD = ".md";
private static final String SPACE = " ";
private static final String SPACE_FORMAT = "%20";
private static final String[] EXCLUDE_FILES = new String[]{".git", "README.md"};
private static final String[] REPLACE_STRINGS = new String[] { " " };//特殊字符
private static final String BLANK = " ";//空格
文件目录递归修改
递归修改文件后缀名并修改文件内容
/**
* 递归修改文件后缀名并修改文件内容
*/
public static void modifyFile(File from) {
if (from == null || !from.exists()) {
throw new RuntimeException("源目录或文件不存在");
}
if (from.isFile()) {
if (from.getName().contains(FILTER)) {//只处理带指定标识的文件
copyAndModifyFileContent(from, new File(from.getParent(), getNewName(from)));
}
from.delete();//删除源文件
return;
}
File[] listFiles = from.listFiles();
if (listFiles == null || listFiles.length == 0) {
System.out.println("----------------------" + from.getName() + "中不存在任何文件");
from.delete();//删除空文件夹
return;
}
for (File file : listFiles) {
if (file.isDirectory()) {
modifyFile(file);//递归
} else if (file.isFile()) {
if (file.getName().contains(FILTER)) {//只处理带指定标识的文件
copyAndModifyFileContent(file, new File(file.getParent(), getNewName(file)));
}
file.delete();
}
}
listFiles = from.listFiles();
if (listFiles == null || listFiles.length == 0) {
System.out.println("----------------------" + from.getName() + "的文件全部不符合要求");
from.delete();//删除空文件夹
}
}
递归修改文件后缀名
/**
* 递归修改文件后缀名
*/
public static void modifyFileSuffix(File from) {
if (from == null || !from.exists()) {
throw new RuntimeException("源目录或文件不存在");
}
if (from.isFile()) {
if (from.getName().contains(FILTER)) {//只处理带指定标识的文件
from.renameTo(new File(from.getParent(), getNewName(from)));
} else {
from.delete();//删除源文件
}
return;
}
File[] listFiles = from.listFiles();
if (listFiles == null || listFiles.length == 0) {
System.out.println("----------------------" + from.getName() + "中不存在任何文件");
from.delete();//删除空文件夹
return;
}
for (File file : listFiles) {
if (file.isDirectory()) {
modifyFileSuffix(file);//递归
} else if (file.isFile()) {
if (file.getName().contains(FILTER)) {//只处理带指定标识的文件
file.renameTo(new File(file.getParent(), getNewName(file)));
} else {
file.delete();
}
}
}
listFiles = from.listFiles();
if (listFiles == null || listFiles.length == 0) {
System.out.println("----------------------" + from.getName() + "的文件全部不符合要求");
from.delete();//删除空文件夹
}
}
/**
* 获取重命名的文件名
*/
private static String getNewName(File file) {
String name = file.getName();
if (name.endsWith(SUFFIX_MD_TXT)) { //处理指定后缀的文件
name = name.substring(0, name.indexOf(SUFFIX_MD_TXT) + SUFFIX_MD.length());
} else if (name.endsWith(SUFFIX_TXT)) {
name = name.substring(0, name.indexOf(SUFFIX_TXT)) + SUFFIX_MD;
}
return name;
}
递归获取格式化后的文件名
/**
* 获取指定目录及其子目录下的文件的文件名,并对文件名进行格式化,并存储到一个指定的集合中,并将内容复制到粘贴板
*/
public static List<String> getFormatFilesNames(File from) {
List<String> filePathList = new ArrayList<>();
getDirFormatFilesNames(filePathList, from, 0);
StringBuilder sBuilder = new StringBuilder();
for (String string : filePathList) {
System.out.print(string);
sBuilder.append(string);
}
setSysClipboardText(sBuilder.toString());
return filePathList;
}
/**
* 递归获取指定目录及其子目录下的文件的文件名,并对文件名进行格式化,并存储到一个指定的集合中
*
* @param filePathList 将结果保存到指定的集合中
* @param from 要遍历的目录
* @param curLeval 记录当前递归所在层级
*/
private static void getDirFormatFilesNames(List<String> filePathList, File from, int curLeval) {
if (from == null || !from.exists()) {
throw new RuntimeException("源目录或文件不存在");
} else if (isExcludeFile(from.getName())) {
System.out.println("----------------------" + "忽略文件" + from.getName());
return;
} else {
filePathList = filePathList == null ? new ArrayList<String>() : filePathList;
filePathList.add(getTitle(curLeval, from));
}
curLeval++;
File[] files = from.listFiles();
if (files == null || files.length == 0) {
System.out.println("----------------------" + from.getName() + "中不存在任何文件");
return;
}
for (File file : files) {
if (file.isDirectory()) {
getDirFormatFilesNames(filePathList, file, curLeval);//递归
} else if (file.isFile() && !isExcludeFile(file.getName())) {
filePathList.add(getTitle(curLeval, file));
}
}
}
/**
* 判断是否是忽略的文件
*/
private static boolean isExcludeFile(String fileName) {
for (String name : EXCLUDE_FILES) {
if (name.equals(fileName)) {
return true;
}
}
return false;
}
文件复制
递归复制目录下的所有文件
/**
* 递归复制目录下的所有文件
*/
public static void copyFiles(File from, File to) {
if (from == null || !from.exists() || to == null) {
throw new RuntimeException("源文件或目标文件不存在");
}
if (from.equals(to)) {
System.out.println("----------------------源文件和目标文件是同一个" + from.getAbsolutePath());
}
if (from.isDirectory()) {
if (to.isFile()) {
throw new RuntimeException("目录不能复制为文件");
}
if (!to.exists()) {
to.mkdirs();//创建目录
}
} else {
if (to.isDirectory()) {
throw new RuntimeException("文件不能复制为目录");
}
copyFile(from, to);//文件的话直接复制
return;
}
File[] files = from.listFiles();
if (files == null || files.length == 0) {
System.out.println(from.getName() + "中不存在任何文件");
return;
}
for (File file : files) {
if (file.isDirectory()) {
File copyDir = new File(to, file.getName());
if (!copyDir.exists()) {
copyDir.mkdirs();
System.out.println("创建子目录\t\t" + copyDir.getAbsolutePath());
}
copyFiles(file, copyDir);//递归
} else if (file.getName().contains(FILTER)) {
copyFile(file, new File(to, file.getName()));
}
}
}
复制一个文件或一个目录
/**
* 复制一个文件或一个目录(不会递归复制目录下的文件)
*/
public static void copyFile(File from, File to) {
if (from == null || !from.exists() || to == null) {
throw new RuntimeException("源文件或目标文件不存在");
}
if (from.equals(to)) {
System.out.println("----------------------源文件和目标文件是同一个" + from.getAbsolutePath());
}
if (from.isDirectory()) {
if (to.isFile()) {
throw new RuntimeException("目录不能复制为文件");
}
if (!to.exists()) {
to.mkdirs();//创建目录
}
return; //没有下面的刘操作
} else {
if (to.isDirectory()) {
throw new RuntimeException("文件不能复制为目录");
}
if (!to.getParentFile().exists()) {
to.getParentFile().mkdirs(); //复制父目录
}
}
try {
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream(from));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream(to));
int ch;
while ((ch = bufis.read()) != -1) {
bufos.write(ch);
}
bufis.close();
bufos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
复制一个文件并修改文件内容
/**
* 复制一个文件或目录(不会复制目录下的文件),复制的时候会修改文件中的一些内容
*/
public static void copyAndModifyFileContent(File from, File to) {
if (from == null || !from.exists() || to == null) {
throw new RuntimeException("源文件或目标文件不存在");
}
if (from.equals(to)) {
System.out.println("----------------------源文件和目标文件是同一个" + from.getAbsolutePath());
}
if (from.isDirectory()) {
if (to.isFile()) {
throw new RuntimeException("目录不能复制为文件");
}
if (!to.exists()) {
to.mkdirs();//创建目录
}
return; //没有下面的刘操作
} else {
if (to.isDirectory()) {
throw new RuntimeException("文件不能复制为目录");
}
if (!to.getParentFile().exists()) {
to.getParentFile().mkdirs(); //复制父目录
}
}
try {
BufferedReader bufr = new BufferedReader(new FileReader(from));
BufferedWriter bufw = new BufferedWriter(new FileWriter(to));
String line;
//另外开辟一个缓冲区,存储读取的一行数据,返回包含该行内容的字符串,不包含换行符,如果已到达流末尾,则返回【 null】
while ((line = bufr.readLine()) != null) {
for (String string : REPLACE_STRINGS) {
line = line.replace(string, BLANK);//替换为空格
}
bufw.write(line);
bufw.write(BLANK + BLANK);//加两个空格
bufw.newLine();// 写入一个行分隔符
bufw.flush();
}
bufr.close();
bufw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
其他工具方法
将字符串复制到剪切板
/**
* 将字符串复制到剪切板
*/
public static void setSysClipboardText(String writeMe) {
Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable tText = new StringSelection(writeMe);
clip.setContents(tText, null);
}
生成格式化的 Markdown 目录
/***
* 格式化目录
*/
private static String getTitle(int level, File file) {
StringBuilder sb = new StringBuilder();
StringBuilder parentPath = new StringBuilder();
File parent = file;
for (int x = 1; x < level; x++) {
sb.append("\t");
parent = parent.getParentFile();//逐级获取父文件
parentPath.insert(0, parent.getName() + "/");//在前面插入父文件的文件名
}
sb.append("-").append(" ")//无序列表
.append("[")//超链接显示的字符
.append(file.getName().endsWith(SUFFIX_MD) ? file.getName().substring(0, file.getName().lastIndexOf(SUFFIX_MD)) : file.getName())//
.append("]")//
.append("(")//拼接超链接
.append(WEBSITE)//前缀
.append(parentPath.toString())//父目录
.append(file.getName().replaceAll(SPACE, SPACE_FORMAT))//文件名
.append(")")//
.append("\n");
return sb.toString();
}
生成 Markdown 的目录
用到的常量
private static final String HEADER_STRING = "#";
private static final char HEADER_CHAR = '#';
private static final String TOC_TITLE = "";//在目录前插入的内容
private static final String REPLACE_TOC = "[TOC]"; //目录要替换的内容
private static final String HEADER_1 = "="; //一级目录
private static final String HEADER_2 = "--"; //二级目录
private static final String PATTERN = "%s- [%s](#%s)";//标题的格式
private static final String SPACES = " ";
private static final String CODES = "%([abcdef]|\\d){2,2}";
private static final String SPECIAL_CHARS = "[\\/?!:\\[\\]`.,()*\"';{}+=<>~\\$|#]";
private static final String DASH = "-";
private static final String EMPTY = "";
private static final String AFFIX = "\t";
递归为文件生成Markdown目录
/**
* 递归为文件生成Markdown目录
*/
public static void insertToc(File from) {
if (from == null || !from.exists()) {
throw new RuntimeException("源目录或文件不存在");
}
if (from.isFile()) {
insertTocIntoFile(from, from, REPLACE_TOC, Integer.MAX_VALUE);
return;
}
File[] listFiles = from.listFiles();
if (listFiles == null || listFiles.length == 0) {
System.out.println("----------------------" + from.getName() + "中不存在任何文件");
return;
}
for (File file : listFiles) {
if (file.isDirectory()) {
insertToc(file);//递归
} else if (file.isFile()) {
insertTocIntoFile(file, file, REPLACE_TOC, Integer.MAX_VALUE);
}
}
}
/**
* 为文件生成Markdown目录
*/
public static void insertTocIntoFile(File from, File to, String replaceAt, int deepLevel) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(from)));
String line;//当前行的内容
String previousLine = null;
List<String> contentList = new ArrayList<>();//每一行的内容集合
List<String> titleList = new ArrayList<>();//标题集合
int currentLine = 0;
int patternLineNumber = 1; //目录插在那一行
while ((line = reader.readLine()) != null) {
++currentLine;
boolean skipLine = false;
String trimLineString = line.trim();
if (trimLineString.startsWith(HEADER_STRING)) { //检测到标题
int count = getCharCount(trimLineString, HEADER_CHAR);
if (count < 1 || count > deepLevel) { //层级控制
System.out.println("----------------------------超过最大层级 " + deepLevel);
previousLine = line;
continue;
}
String headerName = trimLineString.substring(count).trim(); //去掉层级后的文字
titleList.add(getTitle(count, headerName));
} else if (line.startsWith(HEADER_1) && isNotEmpty(previousLine) && line.replaceAll(HEADER_1, "").isEmpty()) {
titleList.add(getTitle(1, previousLine));
} else if (line.startsWith(HEADER_2) && isNotEmpty(previousLine) && line.replaceAll(HEADER_2, "").isEmpty()) {
titleList.add(getTitle(2, previousLine));
} else if (patternLineNumber <= 1 && line.trim().equals(replaceAt)) {
patternLineNumber = currentLine; //找到这个字符串时就插在这一行(替换这个字符串),找到之后就不再继续找了
skipLine = true;//忽略这一行
}
if (!skipLine) {
contentList.add(line);
}
previousLine = line;
}
closeStream(reader); //必须先关掉这个读取,流才能开启写入流
if (patternLineNumber <= 0) {
System.out.println("----------------------------目录插入位置有误");
return;
}
contentList.add(patternLineNumber - 1, TOC_TITLE);//在指定位置插入目录前面的标题
for (String title : titleList) {
contentList.add(patternLineNumber, title);
patternLineNumber++;
}
writeFile(to, contentList);
} catch (Exception e) {
e.printStackTrace();
} finally {
closeStream(reader);
}
}
/**
* 写内容到指定文件
*/
private static void writeFile(File to, List<String> contentList) {
PrintWriter writer = null;
try {
writer = new PrintWriter(new FileWriter(to));
for (String string : contentList) {
writer.append(string).append("\n");
}
writer.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
closeStream(writer);
}
}
插入的目录格式
/**
* 插入的目录的模型
*/
private static String getTitle(int deepLevel, String headerName) {
StringBuilder title = new StringBuilder();
if (deepLevel > 1) {
for (int i = 0; i < deepLevel - 1; i++) {
title.append(AFFIX);
}
}
String headerLink = headerName.trim()//
.replaceAll(SPACES, DASH)//替换特殊字符,比如必须将空格换成'-'
.replaceAll(CODES, EMPTY)//
.replaceAll(SPECIAL_CHARS, EMPTY).toLowerCase();
title.append(DASH).append(SPACES)//格式为【%s- [%s](#%s)】或【缩进- [标题][#链接]】
.append("[").append(headerName).append("]")//
.append("(").append("#")//
.append(headerLink)//
.append(")");
return title.toString();
}
其他一些用到的工具方法
/**
* 关闭流
*/
public static void closeStream(Closeable... closeable) {
for (Closeable c : closeable) {
if (c != null) {
try {
c.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 计算字符串中字符的个数
*/
private static int getCharCount(String string, char c) {
int count = 0;
for (int i = 0; i < string.length(); i++) {
if (string.charAt(i) == c) {
++count;
} else {
break;
}
}
return count;
}
/**
* 获取文件行数
*/
public static int getFileLines(File file) {
LineNumberReader reader = null;
try {
reader = new LineNumberReader(new FileReader(file));
reader.skip(Long.MAX_VALUE);
return reader.getLineNumber() + 1;
} catch (IOException ignored) {
} finally {
closeStream(reader);
}
return -1;
}
/**
* 判断字符串非空
*/
public static boolean isNotEmpty(String string) {
return string != null && !string.isEmpty();
}
源码
MDUtils
public class MDUtils {
private static final String FILTER = "MD";
private static final String SUFFIX_MD_TXT = ".md.txt";
private static final String SUFFIX_TXT = ".txt";
private static final String SUFFIX_MD = ".md";
private static final String[] REPLACE_STRINGS = new String[] { " " };//特殊字符
private static final String BLANK = " ";//空格
/**
* 递归修改文件后缀名并修改文件内容
*/
public static void modifyFile(File from) {
if (from == null || !from.exists()) {
throw new RuntimeException("源目录或文件不存在");
}
if (from.isFile()) {
if (from.getName().contains(FILTER)) {//只处理带指定标识的文件
copyAndModifyFileContent(from, new File(from.getParent(), getNewName(from)));
}
from.delete();//删除源文件
return;
}
File[] listFiles = from.listFiles();
if (listFiles == null || listFiles.length == 0) {
System.out.println("----------------------" + from.getName() + "中不存在任何文件");
from.delete();//删除空文件夹
return;
}
for (File file : listFiles) {
if (file.isDirectory()) {
modifyFile(file);//递归
} else if (file.isFile()) {
if (file.getName().contains(FILTER)) {//只处理带指定标识的文件
copyAndModifyFileContent(file, new File(file.getParent(), getNewName(file)));
}
file.delete();
}
}
listFiles = from.listFiles();
if (listFiles == null || listFiles.length == 0) {
System.out.println("----------------------" + from.getName() + "的文件全部不符合要求");
from.delete();//删除空文件夹
}
}
/**
* 复制一个文件或目录(不会复制目录下的文件),复制的时候会修改文件中的一些内容
*/
private static void copyAndModifyFileContent(File from, File to) {
if (from == null || !from.exists() || to == null) {
throw new RuntimeException("源文件或目标文件不存在");
}
if (from.equals(to)) {
System.out.println("----------------------源文件和目标文件是同一个" + from.getAbsolutePath());
}
if (from.isDirectory()) {
if (to.isFile()) {
throw new RuntimeException("目录不能复制为文件");
}
if (!to.exists()) {
to.mkdirs();//创建目录
}
return; //没有下面的刘操作
} else {
if (to.isDirectory()) {
throw new RuntimeException("文件不能复制为目录");
}
if (!to.getParentFile().exists()) {
to.getParentFile().mkdirs(); //复制父目录
}
}
try {
BufferedReader bufr = new BufferedReader(new FileReader(from));
BufferedWriter bufw = new BufferedWriter(new FileWriter(to));
String line;
//另外开辟一个缓冲区,存储读取的一行数据,返回包含该行内容的字符串,不包含换行符,如果已到达流末尾,则返回【 null】
while ((line = bufr.readLine()) != null) {
for (String string : REPLACE_STRINGS) {
line = line.replace(string, BLANK);//替换为空格
}
bufw.write(line);
bufw.write(BLANK + BLANK);//加两个空格
bufw.newLine();// 写入一个行分隔符
bufw.flush();
}
bufr.close();
bufw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取重命名的文件名
*/
private static String getNewName(File file) {
String name = file.getName();
if (name.endsWith(SUFFIX_MD_TXT)) { //处理指定后缀的文件
name = name.substring(0, name.indexOf(SUFFIX_MD_TXT) + SUFFIX_MD.length());
} else if (name.endsWith(SUFFIX_TXT)) {
name = name.substring(0, name.indexOf(SUFFIX_TXT)) + SUFFIX_MD;
}
return name;
}
}
TOCUtils
public class TOCUtils {
private static final String HEADER_STRING = "#";
private static final char HEADER_CHAR = '#';
private static final String TOC_TITLE = "";//在目录前插入的内容
private static final String REPLACE_TOC = "[TOC]"; //目录要替换的内容
private static final String HEADER_1 = "="; //一级目录
private static final String HEADER_2 = "--"; //二级目录
private static final String SPACES = " ";
private static final String CODES = "%([abcdef]|\\d){2,2}";
private static final String SPECIAL_CHARS = "[\\/?!:\\[\\]`.,()*\"';{}+=<>~\\$|#]";
private static final String DASH = "-";
private static final String EMPTY = "";
private static final String AFFIX = "\t";
private static String ROOT_DIR = null;
/**
* 递归为为文件生成目录
*/
public static void insertToc(File from, boolean addHeader) {
if (from == null || !from.exists()) {
throw new RuntimeException("源目录或文件不存在");
} else if (ROOT_DIR == null) {
ROOT_DIR = from.getAbsolutePath();
}
if (from.isFile()) {
insertTocIntoFile(from, from, REPLACE_TOC, Integer.MAX_VALUE, addHeader);
return;
}
File[] listFiles = from.listFiles();
if (listFiles == null || listFiles.length == 0) {
System.out.println("----------------------" + from.getName() + "中不存在任何文件");
return;
}
for (File file : listFiles) {
if (file.isDirectory()) {
insertToc(file, addHeader);//递归
} else if (file.isFile()) {
insertTocIntoFile(file, file, REPLACE_TOC, Integer.MAX_VALUE, addHeader);
}
}
}
/**
* 为文件生成目录
*/
private static void insertTocIntoFile(File from, File to, String replaceAt, int deepLevel, boolean addHeader) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(from)));
String line;//当前行的内容
String previousLine = null;
List<String> contentList = new ArrayList<>();//每一行的内容集合
List<String> titleList = new ArrayList<>();//标题集合
int currentLine = 0;
int patternLineNumber = 1; //目录插在那一行
while ((line = reader.readLine()) != null) {
++currentLine;
boolean skipLine = false;
String trimLineString = line.trim();
if (trimLineString.startsWith(HEADER_STRING)) { //检测到标题
int count = getCharCount(trimLineString, HEADER_CHAR);
if (count < 1 || count > deepLevel) { //层级控制
System.out.println("----------------------------超过最大层级 " + deepLevel);
previousLine = line;
continue;
}
String headerName = trimLineString.substring(count).trim(); //去掉层级后的文字
System.out.println("【" + headerName + "】");
titleList.add(getTitle(count, headerName));
} else if (line.startsWith(HEADER_1) && isNotEmpty(previousLine) && line.replaceAll(HEADER_1, "").isEmpty()) {
//titleList.add(getTitle(1, previousLine.trim()));//暂时不需要
} else if (line.startsWith(HEADER_2) && isNotEmpty(previousLine) && line.replaceAll(HEADER_2, "").isEmpty()) {
//titleList.add(getTitle(2, previousLine.trim()));//暂时不需要
} else if (patternLineNumber <= 1 && line.trim().equals(replaceAt)) {
patternLineNumber = currentLine; //找到这个字符串时就插在这一行(替换这个字符串),找到之后就不再继续找了
skipLine = true;//忽略这一行
}
if (!skipLine) {
contentList.add(line);
}
previousLine = line;
}
closeStream(reader); //必须先关掉这个读取,流才能开启写入流
if (patternLineNumber <= 0) {
System.out.println("----------------------------目录插入位置有误");
return;
}
contentList.add(patternLineNumber - 1, TOC_TITLE);//在指定位置插入目录前面的标题
for (String title : titleList) {
contentList.add(patternLineNumber, title);
patternLineNumber++;
}
writeFile(to, contentList, addHeader);
} catch (Exception e) {
e.printStackTrace();
} finally {
closeStream(reader);
}
}
/**
* 写内容到指定文件
*/
private static void writeFile(File file, List<String> contentList, boolean addHeader) {
PrintWriter writer = null;
try {
writer = new PrintWriter(new FileWriter(file));
if (addHeader) {
String title = file.getName().substring(0, file.getName().indexOf(".md"));
String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(file.lastModified()));
String bqtdir = file.getParent().substring(ROOT_DIR.length() + 1).replace("\\", "/");
writer.append("---").append("\n")//
.append("title: ").append(title).append("\n")//标题
.append("date: ").append(date).append("\n")//生成日期
.append("bqtdir: ").append(bqtdir).append("\n")//自定义路径
.append("categories:").append("\n");//分类
for (String dir : bqtdir.split("/")) {
writer.append(" - ").append(dir).append("\n");//路径分类
}
writer.append("---").append("\n").append("\n");
}
for (String string : contentList) {
writer.append(string).append("\n");
}
writer.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
closeStream(writer);
}
}
/**
* 关闭流
*/
private static void closeStream(Closeable... closeable) {
for (Closeable c : closeable) {
if (c != null) {
try {
c.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 判断字符串非空
*/
private static boolean isNotEmpty(String string) {
return string != null && !string.isEmpty();
}
/**
* 计算字符串中字符的个数
*/
private static int getCharCount(String string, char c) {
int count = 0;
for (int i = 0; i < string.length(); i++) {
if (string.charAt(i) == c) {
++count;
} else {
break;
}
}
return count;
}
/**
* 插入的目录的模型
*/
private static String getTitle(int deepLevel, String headerName) {
StringBuilder title = new StringBuilder();
if (deepLevel > 1) {
for (int i = 0; i < deepLevel - 1; i++) {
title.append(AFFIX);
}
}
String headerLink = headerName.trim()//
.replaceAll(SPACES, DASH)//替换特殊字符,比如必须将空格换成'-'
.replaceAll(CODES, EMPTY)//
.replaceAll(SPECIAL_CHARS, EMPTY).toLowerCase();
title.append(DASH).append(SPACES)//格式为【%s- [%s](#%s)】或【缩进- [标题][#链接]】
.append("[").append(headerName).append("]")//
.append("(").append("#")//
.append(headerLink)//
.append(")");
return title.toString();
}
}
DirUtils
public class DirUtils {
private static final String WEBSITE = "https://github.com/baiqiantao/MyAndroidBlogs/blob/master/";
private static final String SPACE = " ";
private static final String SPACE_FORMAT = "%20";
private static final String[] EXCLUDE_FILES = new String[] { ".git", "README.md" };
private static final String SUFFIX_MD = ".md";
/**
* 获取指定目录及其子目录下的文件的文件名,并对文件名进行格式化,并存储到一个指定的集合中,并将内容复制到粘贴板
*/
public static List<String> getFormatFilesNames(File from) {
List<String> filePathList = new ArrayList<>();
getDirFormatFilesNames(filePathList, from, 0);
StringBuilder sBuilder = new StringBuilder();
for (String string : filePathList) {
System.out.print(string);
sBuilder.append(string);
}
setSysClipboardText(sBuilder.toString());
return filePathList;
}
/**
* 获取指定目录及其子目录下的文件的文件名,并对文件名进行格式化,并存储到一个指定的集合中
*
* @param filePathList 将结果保存到指定的集合中
* @param from 要遍历的目录
* @param curLeval 记录当前递归所在层级
*/
private static void getDirFormatFilesNames(List<String> filePathList, File from, int curLeval) {
if (from == null || !from.exists()) {
throw new RuntimeException("源目录或文件不存在");
} else if (isExcludeFile(from.getName())) {
System.out.println("----------------------" + "忽略文件" + from.getName());
return;
} else {
filePathList = filePathList == null ? new ArrayList<String>() : filePathList;
filePathList.add(getTitle(curLeval, from));
}
curLeval++;
File[] files = from.listFiles();
if (files == null || files.length == 0) {
System.out.println("----------------------" + from.getName() + "中不存在任何文件");
return;
}
for (File file : files) {
if (file.isDirectory()) {
getDirFormatFilesNames(filePathList, file, curLeval);//递归
} else if (file.isFile() && !isExcludeFile(file.getName())) {
filePathList.add(getTitle(curLeval, file));
}
}
}
/**
* 是否是忽略的文件
*/
private static boolean isExcludeFile(String fileName) {
for (String name : EXCLUDE_FILES) {
if (name.equals(fileName)) {
return true;
}
}
return false;
}
/**
* 将字符串复制到剪切板
*/
private static void setSysClipboardText(String writeMe) {
Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable tText = new StringSelection(writeMe);
clip.setContents(tText, null);
}
/***
* 格式化目录
*/
private static String getTitle(int level, File file) {
StringBuilder sb = new StringBuilder();
StringBuilder parentPath = new StringBuilder();
File parent = file;
for (int x = 1; x < level; x++) {
sb.append("\t");
parent = parent.getParentFile();//逐级获取父文件
parentPath.insert(0, parent.getName() + "/");//在前面插入父文件的文件名
}
sb.append("-").append(" ")//无序列表
.append("[")//超链接显示的字符
.append(file.getName().endsWith(SUFFIX_MD) ? file.getName().substring(0, file.getName().lastIndexOf(SUFFIX_MD)) : file.getName())//
.append("]")//
.append("(")//拼接超链接
.append(WEBSITE)//前缀
.append(parentPath.toString())//父目录
.append(file.getName().replaceAll(SPACE, SPACE_FORMAT))//文件名
.append(")")//
.append("\n");
return sb.toString();
}
}
2018-10-24
生成Markdown目录 字符串解析 MD的更多相关文章
- ADO.NET生成的数据库连接字符串解析
1.概述 当我们使用ADO.NET数据实体模型生成的时候,在项目目下生成一个.edmx文件的同时,还会在app.config里面出现如下一个代码串: <?xml version="1. ...
- git - gitHub生成Markdown目录
就是github-markdown-toc.go. github-markdown-toc.go Github地址 如果你有GO语言(又是你)的编译环境,可以尝试自己编译,如果没有,可以直接下载编译好 ...
- C#实现生成Markdown文档目录树
前言 之前我写了一篇关于C#处理Markdown文档的文章:C#解析Markdown文档,实现替换图片链接操作 算是第一次尝试使用C#处理Markdown文档,然后最近又把博客网站的前台改了一下,目前 ...
- [Selenium2+python2.7][Scrap]爬虫和selenium方式下拉滚动条获取简书作者目录并且生成Markdown格式目录
预计阅读时间: 15分钟 环境: win7 + Selenium2.53.6+python2.7 +Firefox 45.2 (具体配置参考 http://www.cnblogs.com/yoyok ...
- InfluxDB源码目录结构解析
操作系统 : CentOS7.3.1611_x64 go语言版本:1.8.3 linux/amd64 InfluxDB版本:1.1.0 influxdata主目录结构 [root@localhost ...
- 基于开源库jsoncpp的json字符串解析
json(JavaScript Object Notation)是一种轻量级高效数据交换格式.相比于XML,其更加简洁,解析更加方便.在实习期间,我负责的程序模块,多次使用到json进行数据传输.由于 ...
- NET 5.0 Swagger API 自动生成MarkDown文档
目录 1.SwaggerDoc引用 主要接口 接口实现 2.Startup配置 注册SwaggerDoc服务 注册Swagger服务 引用Swagger中间件 3.生成MarkDown 4.生成示例 ...
- Markdown 目录
Markdown 目录 1. TOC TOC 全称为 Table of Content,自动列出全部标题. 用法: [toc] 在 Markdown 中,自动生成目录非常简单,只需要在恰当的位置添加 ...
- 好用的Markdown编辑器一览 readme.md 编辑查看
https://github.com/pandao/editor.md https://pandao.github.io/editor.md/examples/index.html Editor.md ...
随机推荐
- C#开发Unity游戏教程之判断语句
C#开发Unity游戏教程之判断语句 游戏执行路径的选择——判断 玩家在游戏时,无时无刻不在通过判断做出选择.例如,正是因为玩家做出的选择不同,才导致游戏朝着不同的剧情发展,因此一个玩家可以对一个游戏 ...
- BZOJ2160: 拉拉队排练
Description 艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了.拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛.所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训 ...
- 【BZOJ-4261】建设游乐场 最大费用最大流
4261: 建设游乐场 Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 21 Solved: 8[Submit][Status][Discuss] D ...
- java php c# 三种语言的AES加密互转
java php c# 三种语言的AES加密互转 最近做的项目中有一个领取优惠券的功能,项目是用php写得,不得不佩服,php自带的方法简洁而又方便好用.项目是为平台为其他公司发放优惠券,结果很囧的是 ...
- activiti流程
package cn.demo.service.impl; import java.io.File; import java.io.FileInputStream; import java.io.Fi ...
- 在eclipse中查看Android源码
声明:高手跳过此文章 当我们在eclipse中开发android程序的时候.往往须要看源码(可能是出于好奇,可能是读源码习惯),那么怎样查看Android源码呢? 比方以下这样的情况 图1 如果我们想 ...
- SysTick Software Timer
#ifndef __SYSTEM_H__ #define __SYSTEM_H__ #include <stdint.h> #include <stddef.h> #inclu ...
- [Ubuntu] 编译安装 PHP 依赖库
编译环境 sudo apt-get -y install build-essential xml sudo apt-get -y install libxml2-dev pcre sudo apt-g ...
- [Winform]缓存处理
摘要 在对winform做的项目优化的时候,首先想到的是对查询,并不经常变化的数据进行缓存,但对web项目来说有System.Web.Caching.Cache类进行缓存,那么winform端该如何呢 ...
- PostgreSQL代码分析,查询优化部分,canonicalize_qual
这里把规范谓词表达式的部分就整理完了.阅读的顺序例如以下: 一.PostgreSQL代码分析,查询优化部分,canonicalize_qual 二.PostgreSQL代码分析,查询优化部分,pull ...