A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© jiubaK 中级黑马   /  2016-9-23 22:51  /  2488 人查看  /  24 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

为了方便从多个文件中查找目标字符串,写了这个工具类
[Java] 纯文本查看 复制代码
package com.itheima.file;

/**
 * 文本内容查找工具类,可以在查找一个目录下所有文件中查找指定的文本,要查找的文本可以是多行,但需要是一个字符串
 * 查找时,可以指定不同类型文件的编码,如果没有指定文件编码,将使用平台默认编码进行解码
 * 也可以传入文件名过滤器,如果不传文件名过滤器,将查找所有文件中的内容
 * @author Administrator
 */

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class Find {
        private static final FilenameFilter defaultFilter ;
        private static final Map<String,String> defaultCharsetOfFileType;
        
        static {
                defaultFilter = new FilenameFilter() {
                        public boolean accept(File dir, String name) {
                                return true;
                        }
                };
                defaultCharsetOfFileType = new HashMap<>();
                defaultCharsetOfFileType.put("default", System.getProperty("file.encoding"));
        }
        
        /**
         * 用于测试工具类,本不应该写在这里,只是为了方便
         * @param args
         */
        public static void main(String[] args) {
                File root = new File("C:\\Users\\Administrator\\Desktop");
                String info = "任意一个";
                HashMap<String,String> charsetOfFileType = new HashMap<>();
                charsetOfFileType.put("default", "gbk");
                charsetOfFileType.put(".md", "utf-8");
                ArrayList<Map.Entry<File, Integer>> al = find(root, charsetOfFileType, info, new FilenameFilter() {
                        public boolean accept(File dir, String name) {
                                return name.matches("^.*\\.(txt$)?(md$)?(java$)?") || new File(dir, name).isDirectory();
                        }
                });
                for (Entry<File, Integer> en : al) {
                        System.out.println( en.getKey() + " : " + en.getValue() );
                }
        }
        
        /**
         * 查找root文件中或者root目录下所有的文件,通过默认编码打开,查找指定的文本,查找到的文件和对应行数存入集合中返回
         * @param root 要查找的文件或者目录
         * @param info 要查找的文本
         * @return 一个ArrayList集合,以Map.Entry作为元素存放查询结果,Map.Entry中是文件和行数的对应关系
         */
        public static ArrayList<Map.Entry<File, Integer>> find(File root, String info) {
                return find(root, defaultCharsetOfFileType, info);
        }
        
        /**
         * 查找root文件中或者root目录下所有过滤后的文件中,通过默认编码打开,查找指定的文本,查找到的文件和对应行数存入集合中返回
         * @param root 要查找的文件或者目录
         * @param info 要查找的文本
         * @param filter 文件名过滤器
         * @return 一个ArrayList集合,以Map.Entry作为元素存放查询结果,Map.Entry中是文件和行数的对应关系
         */
        public static ArrayList<Map.Entry<File, Integer>> find(File root, String info, FilenameFilter filter) {
                return find(root, defaultCharsetOfFileType, info, filter);
        }
        
        /**
         * 查找root文件中或者root目录下所有的文件,通过指定编码打开,查找指定的文本,查找到的文件和对应行数存入集合中返回
         * @param root 要查找的文件或者目录
         * @param charsetOfFileType 一个Map集合,存放的是后缀名和编码的键值对
         * @param info 要查找的文本
         * @return 一个ArrayList集合,以Map.Entry作为元素存放查询结果,Map.Entry中是文件和行数的对应关系
         */
        public static ArrayList<Map.Entry<File, Integer>> find(File root, Map<String,String> charsetOfFileType, String info) {
                return find(root, charsetOfFileType, info, defaultFilter);
        }
        
        /**
         * 递归查找root文件中或者root目录下所有过滤后的文件中,通过指定编码打开,查找指定的文本,查找到的文件和对应行数存入集合中
         * @param root 要查找的文件或者目录
         * @param charsetOfFileType 一个Map集合,存放的是后缀名和编码的键值对
         * @param infos 要查找的文本
         * @param filter 文件名过滤器
         * @return 一个ArrayList集合,以Map.Entry作为元素存放查询结果,Map.Entry中是文件和行数的对应关系
         */
        public static ArrayList<Map.Entry<File, Integer>> find(File root, Map<String,String> charsetOfFileType, String info, FilenameFilter filter) {
                ArrayList<Map.Entry<File, Integer>> al = new ArrayList<>();
                String nl = System.getProperty("line.separator");
                while( info.startsWith(nl) ) {
                        info = info.substring(nl.length());
                }
                if( !"".equals(info) ) {
                        String infos[] = info.split( nl );
                        find(root, charsetOfFileType, infos, filter, al);
                }
                return al;
        }
        
        /**
         * 递归查找root文件中或者root目录下所有过滤后的文件中,通过指定编码打开,查找指定的文本,查找到的文件和对应行数存入集合中
         * @param root 要查找的文件或者目录
         * @param charsetOfFileType 一个Map集合,存放的是后缀名和编码的键值对
         * @param infos 要查找的文本数组
         * @param filter 文件名过滤器
         * @param al 一个ArrayList集合,以Map.Entry作为元素存放查询结果,Map.Entry中是文件和行数的对应关系
         */
        private static void find(File root, Map<String,String> charsetOfFileType, String[] infos, FilenameFilter filter, ArrayList<Map.Entry<File, Integer>> al) {
                if( root.isFile() ) {
                        LineNumberReader lnr = null; 
                        try {
                                String suf = getSuffix(root);
                                if( suf == null || ".".equals(suf) || "".equals(suf) )
                                        suf = "default";
                                String charset = charsetOfFileType.get(suf);
                                if( charset == null )
                                        charset = System.getProperty("file.encoding");
                                lnr = new LineNumberReader(new InputStreamReader(new FileInputStream(root),charset));
                                for(String line; (line = lnr.readLine()) != null ; ) {
                                        if( infos.length == 1 ) {
                                                if( line.contains( infos[0] ) ) {
                                                        addToArrayList(al, root, lnr.getLineNumber());
                                                }
                                        } else {
                                                while( line != null && line.endsWith( infos[0] ) ) {
                                                        int t_linenumber = lnr.getLineNumber();
                                                        for(int i=1 ;( line = lnr.readLine()) != null ; i++) {
                                                                if( i == infos.length - 1 ) {
                                                                        if( line.startsWith( infos[i] ) ) {
                                                                                addToArrayList(al, root, t_linenumber);
                                                                        }
                                                                        break;
                                                                } else {
                                                                        if( !line.equals( infos[i] ) ) {
                                                                                break;
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                        } catch (FileNotFoundException e) {
                                e.printStackTrace();
                        } catch (IOException e) {
                                e.printStackTrace();
                        } finally {
                                if( lnr != null ) {
                                        try {
                                                lnr.close();
                                        } catch (IOException e) {
                                                e.printStackTrace();
                                        }
                                }
                        }
                } else if ( root.isDirectory() ) {
                        File[] files = root.listFiles(filter);
                        if( files == null )
                                return;
                        for( File f : files ) {
                                find(f, charsetOfFileType, infos, filter, al);
                        }
                }
        }
        
        /*
         * 获取文件后缀名,如果没有后缀则返回空字符串
         */
        private static String getSuffix(File file) {
                String name = file.getName();
                int index = name.lastIndexOf('.');
                if( index < 0 )
                        return "";
                return name.substring(index);
        }
        /*
         * 将File和int数据作为一个键值对,存入ArrayList<Map.Entry<File,Integer>>集合
         */
        private static void addToArrayList(ArrayList<Map.Entry<File, Integer>> al, final File file, final int lineNumber) {
                al.add(new Entry<File, Integer>() {
                        private File k = file;
                        private Integer v = lineNumber;
                        public Integer setValue(Integer value) {
                                Integer _ov = v;
                                v = value;
                                return _ov;
                        }
                        public Integer getValue() {
                                return v;
                        }
                        public File getKey() {
                                return k;
                        }
                });
        }
}

24 个回复

倒序浏览
CreScert 来自手机 中级黑马 2016-9-23 22:54:39
沙发
顶起,不错努力,就是注释少点,这是个坏习惯
回复 使用道具 举报
CreScert 发表于 2016-9-23 22:54
顶起,不错努力,就是注释少点,这是个坏习惯

谢谢支持,我没有写那么多注释,只写了每个函数的功能,
本来还想修改下的,忘了私有构造函数,但是你都回帖了,就在这里说明下
回复 使用道具 举报
好帖,顶起来,让更多人看到
回复 使用道具 举报
顶起,叼爆了
回复 使用道具 举报
天河边吃紫英 发表于 2016-9-24 09:19
好帖,顶起来,让更多人看到

谢谢支持,一起努力+_+
回复 使用道具 举报
jiubaK 中级黑马 2016-9-24 10:43:01
7#

其实也不难,用到的知识在基础班都学了的
回复 使用道具 举报
jiubaK 发表于 2016-9-23 22:57
谢谢支持,我没有写那么多注释,只写了每个函数的功能,
本来还想修改下的,忘了私有构造函数,但是你都回帖了 ...

哦,那我回早啦....细细
回复 使用道具 举报
jiubaK 中级黑马 2016-9-25 09:39:23
9#
CreScert 发表于 2016-9-24 21:07
哦,那我回早啦....细细

额,我的错,没有考虑周全。你一个“细细”让俺浮想联翩
回复 使用道具 举报
很好,如果有注释就更好了
回复 使用道具 举报
读书可以当饭吃 发表于 2016-9-25 10:34
很好,如果有注释就更好了

嗯,谢谢支持,后期其它帖子会根据需要添加注释的。
回复 使用道具 举报
6666666666666!
回复 使用道具 举报
jiubaK 发表于 2016-9-25 09:39
额,我的错,没有考虑周全。你一个“细细”让俺浮想联翩

刚刚才发现,错别字。。。
回复 使用道具 举报
学习了,努力!
回复 使用道具 举报
技术贴,支持支持!!!
回复 使用道具 举报
又学习到了一个知识,谢谢
回复 使用道具 举报
稻香灬 发表于 2016-9-27 11:22
又学习到了一个知识,谢谢

共同进步,多发帖
回复 使用道具 举报
橘子哥 发表于 2016-9-26 10:55
技术贴,支持支持!!!

谢谢橘子哥支持!
回复 使用道具 举报
nicezt 发表于 2016-9-25 22:29
学习了,努力!

谢谢支持,一起努力^_^
回复 使用道具 举报

谢谢支持,一起加油吧,少年
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马