package utils; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.nio.channels.FileChannel; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import java.util.Map; public class FileUtils { public static void main(String[] args) { getCodeLinesDetail("E:\\work\\ChildrenRead\\app\\src\\main"); } /** * 递归获取的文件列表集合 */ private static List<File> allFiles = new ArrayList<>(); /** * 获取指定目录下全部文件 * * @param dir 根目录路径 * @return 获取到的文件列表 */ public static List<File> getAllFiles(String dir) { return getAllFiles(new File(dir)); } /** * 获取指定目录下全部文件 * * @param rootFile 根目录文件 * @return 获取到的文件列表 */ public static List<File> getAllFiles(File rootFile) { allFiles = new ArrayList<File>(); try { getFiles(rootFile); } catch (Exception e) { e.printStackTrace(); } return allFiles; } /** * 递归dir下全部文件并保存至allFiles * * @param dir 发起递归的根目录 */ public static void getFiles(File dir) throws Exception { File[] fs = dir.listFiles(); for (int i = 0; i < fs.length; i++) { File file = fs[i]; if (fs[i].isDirectory()) { try { getFiles(fs[i]); } catch (Exception e) { e.printStackTrace(); } } else { allFiles.add(file); } } } /** * 使用文件通道的方式复制文件 * * @param srcFile * 源文件 * @param tarFile * 复制到的新文件 */ public static void copyFileByChannel(File srcFile, File tarFile) { FileInputStream fi = null; FileOutputStream fo = null; FileChannel in = null; FileChannel out = null; try { fi = new FileInputStream(srcFile); fo = new FileOutputStream(tarFile); in = fi.getChannel();// 得到对应的文件通道 out = fo.getChannel();// 得到对应的文件通道 // 连接两个通道,并且从in通道读取,然后写入out通道 in.transferTo(0, in.size(), out); } catch (IOException e) { e.printStackTrace(); } finally { try { fi.close(); in.close(); fo.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 替换指定目录下全部java文件内符合自定义条件的字符串 * * @param rootPath 根目录的绝对路径 * @param replaceString key-原文字 value-需要替换的文字 */ public static void replaceStringOfJava(String rootPath, Map<String, String> replaceString) { // 获取全部文件 List<File> files = FileUtils.getAllFiles(rootPath); for (File file : files) { // 如果不是java后缀的文件,则跳过 if(!file.getName().endsWith(".java")) { continue; } // 将文件读取为一整个字符串 String fileContent = readToString(file); // 是否有替换操作 boolean hasReplace = false; // 遍历替换map,依次替换全部字符串 for (Map.Entry<String, String> entry : replaceString.entrySet()) { if (fileContent.contains(entry.getKey())) { fileContent = fileContent.replace(entry.getKey(), entry.getValue()); hasReplace = true; } } // 如果有替换操作,则将替换后的新文件内容字符串写入回文件中去 if(hasReplace) { writeString2File(fileContent, file); } } } /** * 替换指定目录下全部java文件内符合自定义条件的字符串,支持正则 * * @param rootPath 根目录的绝对路径 * @param replaceString key-原文字 value-需要替换的文字 */ public static void replaceAllStringOfJava(String rootPath, Map<String, String> replaceString, String charSet) { // 获取全部文件 List<File> files = FileUtils.getAllFiles(rootPath); for (File file : files) { // 如果不是java后缀的文件,则跳过 if(!file.getName().endsWith(".java")) { continue; } // 将文件读取为一整个字符串 String fileContent = readToString(file, charSet); // 是否有替换操作 boolean hasReplace = false; // 遍历替换map,依次替换全部字符串 for (Map.Entry<String, String> entry : replaceString.entrySet()) { if (fileContent.contains(entry.getKey())) { fileContent = fileContent.replaceAll(entry.getKey(), entry.getValue()); hasReplace = true; } } // 如果有替换操作,则将替换后的新文件内容字符串写入回文件中去 if(hasReplace) { writeString2File(fileContent, file, charSet); } } } /** * 删除无用java文件 * * @param rootPath 根目录的绝对路径 */ public static void delNoUseJavaFile(String rootPath) { List<File> files = getAllFiles(rootPath); out: for (File file : files) { if(!file.getName().endsWith(".java")) { continue; } for (File compareFile : files) { // 如果包含文件名,则视为有使用 String fileContent = readToString(compareFile); if (fileContent.contains(getName(file))) { continue out; } } String absname = file.getAbsoluteFile().getName(); boolean delete = file.delete(); System.out.println(absname + " ... delete=" + delete); } } /** * 获取代码行数详情,包括总/空行/注释/有效代码各个行数 * * @param rootPath 根目录的绝对路径 */ public static void getCodeLinesDetail(String rootPath) { // 全部文件中行数 int allLines = 0; // 全部文件中空行数 int allEmptyLines = 0; // 全部文件中代码行数 int allCodeLines = 0; // 全部文件中注释行数 int allAnnoLines = 0; List<File> files = FileUtils.getAllFiles(rootPath); for (File file : files) { // TODO 只统计java和xml代码 if(file.getName().endsWith(".java") || file.getName().endsWith(".xml")) { FileReader fr; try { fr = new FileReader(file); BufferedReader bufferedreader = new BufferedReader(fr); String line; // 是否属于多行注释 boolean multiLineAnno = false; while ((line=bufferedreader.readLine()) != null) { allLines ++; // 空行 if(line.trim().equals("")) { allEmptyLines ++; continue; } // 单行注释 if(line.contains("//")) { allAnnoLines ++; continue; } // 如果还是在多行注释中 if(multiLineAnno) { allAnnoLines ++; // 如果本行包含多行注释结束符,结束 if(line.contains("*/")) { multiLineAnno = false; } continue; } // 多行注释开始(包括/*和/**) if(line.contains("/*")) { allAnnoLines ++; multiLineAnno = true; continue; } // 有效代码 allCodeLines ++; } fr.close(); } catch (IOException e) { e.printStackTrace(); } } } System.out.println("文件总行数为:" + allLines); System.out.println("文件空行数为:" + allEmptyLines); System.out.println("文件注释行数为:" + allAnnoLines); System.out.println("文件有效代码行数为:" + allCodeLines); System.out.println("--------------------"); // TODO 计算比例规则为 注释行数/有效代码数 float percent = (float) allAnnoLines / allCodeLines * 100; // 格式化百分比,保留2位小数 %50.00 DecimalFormat df = new DecimalFormat("0.00"); System.out.println("注释比例(注释行数/有效代码数): %" + df.format(percent)); } /** * 获取代码行数,只统计java/xml后缀的文件 * * @param rootPath 根目录的绝对路径 */ public static void getCodeLines(String rootPath) { int allLines = 0; List<File> files = getAllFiles(rootPath); for (File file : files) { if(file.getName().endsWith(".java") || file.getName().endsWith(".xml")) { int lines = getLines(file); allLines += lines; } } System.out.println(allLines); } /** * 获取文件内文本的行数 */ public static int getLines(File file) { int lines = 0; FileReader fr; try { fr = new FileReader(file); BufferedReader bufferedreader = new BufferedReader(fr); while ((bufferedreader.readLine()) != null) { lines++; } fr.close(); } catch (IOException e) { e.printStackTrace(); } return lines; } public static File getFileByName(String proPath, String filename) { File tarFile = null; List<File> files = FileUtils.getAllFiles(proPath); for(File file : files) { String fileName = file.getName(); if(fileName.equals(filename)) { tarFile = file; break; } } return tarFile; } /** * 获取文件名,去除后缀部分 */ public static String getName(File file) { String name = file.getName(); name = name.substring(0, name.lastIndexOf(".")); // 如果是.9.png结尾的,则在去除.png后缀之后还需要去除.9的后缀 if (file.getName().endsWith(".9.png")) { name = name.substring(0, name.lastIndexOf(".")); } return name; } /** * 获取文件名,去除后缀部分 */ public static String getName(String fileAbsPath) { File file = new File(fileAbsPath); return getName(file); } /** * 文件名和后缀分开 */ public static String[] getNameMap(File file) { String[] nameMap = new String[2]; String name = file.getName(); name = name.substring(0, name.lastIndexOf(".")); // 如果是.9.png结尾的,则在去除.png后缀之后还需要去除.9的后缀 if (file.getName().endsWith(".9.png")) { name = name.substring(0, name.lastIndexOf(".")); } nameMap[0] = name; nameMap[1] = file.getName().replaceFirst(name, ""); return nameMap; } /** * 将文件读取为字符串 */ public static String readToString(File file) { Long filelength = file.length(); byte[] filecontent = new byte[filelength.intValue()]; try { FileInputStream in = new FileInputStream(file); in.read(filecontent); in.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { // 获取文件的编码格式,再根据编码格式生成字符串 String charSet = getCharSet(file); return new String(filecontent, charSet); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } } public static String parseCharset(String oldString, String oldCharset, String newCharset) { byte[] bytes; try { bytes = oldString.getBytes(oldCharset); } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new RuntimeException("UnsupportedEncodingException - oldCharset is wrong"); } try { return new String(bytes, newCharset); } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new RuntimeException("UnsupportedEncodingException - newCharset is wrong"); } } /** * 根据指定编码格式将文件读取为字符串 */ public static String readToString(File file, String charSet) { Long filelength = file.length(); byte[] filecontent = new byte[filelength.intValue()]; try { FileInputStream in = new FileInputStream(file); in.read(filecontent); in.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { return new String(filecontent, charSet); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } } /** * 将文件内容以行为单位读取 */ public static ArrayList<String> readToStringLines(File file) { ArrayList<String> strs = new ArrayList<String>(); FileReader fr = null; BufferedReader br = null; try { fr = new FileReader(file); br = new BufferedReader(fr); String line; while ((line = br.readLine()) != null) { strs.add(line); } } catch (IOException e) { e.printStackTrace(); return null; } finally { if(br != null) { try { br.close(); } catch (IOException ignored) { } } if(fr != null) { try { fr.close(); } catch (IOException ignored) { } } } return strs; } /** * 搜索某目录下所有文件的文本中,是否包含某个字段,如果包含打印改文件路径 * * @param path 搜索目录 * @param key 包含字段 */ public static void searchFileContent(String path, String key) { List<File> allFiles = FileUtils.getAllFiles(path); for(File file : allFiles) { String string = FileUtils.readToString(file); if(string.contains(key)) { System.out.println(file.getAbsoluteFile()); } } } /** * 获取文件编码格式,暂只判断gbk/utf-8 */ public static String getCharSet(File file) { String chatSet = null; try { InputStream in = new java.io.FileInputStream(file); byte[] b = new byte[3]; in.read(b); in.close(); if (b[0] == -17 && b[1] == -69 && b[2] == -65) chatSet = "UTF-8"; else chatSet = "GBK"; } catch (IOException e) { e.printStackTrace(); } return chatSet; } /** * 将字符串写入文件 */ public static void writeString2File(String str, File file, String encoding) { BufferedWriter writer = null; try { if(!file.exists()) { file.createNewFile(); } writer = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(file), encoding)); writer.write(str); } catch (IOException e) { e.printStackTrace(); } finally { try { writer.close(); } catch (IOException e) { writer = null; e.printStackTrace(); } } } public static void writeString2File(String str, File file) { writeString2File(str, file, getCharSet(file)); } /** * 将字节数组写入文件 */ public static void writeBytes2File(byte[] bytes, File file) { FileOutputStream fos = null; try { if(!file.exists()) { file.createNewFile(); } fos = new FileOutputStream(file); fos.write(bytes); } catch (IOException e) { e.printStackTrace(); } finally { try { fos.close(); } catch (IOException e) { fos = null; e.printStackTrace(); } } } }