Skip to content

JAVA 实现 grep + tail 功能

在 linux shell 下经常使用的一个命令组合: grep [-v] “filter” filePath | tail -n needLines,用来查看文件中符合条件的最后 n 行记录,尤其在监控 server 的 log 的时候。
现在有一个需求:从 web 管理后台向 search server 发送一个 stat 命令,查看搜索索引的各项统计信息,其中就包括索引更新,查询的 log 的最后 n 条记录。于是需要在 search server 里实现这样一个功能。

PS:如果是 php,我肯定会选用 exec 一条外部 shell 命令,获取命令的输出 的方式来做,但 java,只好自己动手,重复发明轮子了。
PS2:stl 的 rotate 代码真是太精炼了。有空需要多看看这样的代码,能从中学到很多“ how code talks ”

[code=java]
      /**
	 *  implenment: grep [-v] "filter" filePath | tail -n needLines
	 *
	 *  if filter start with '-', means exclude mode "grep -v", others include mode "grep"
	 *
	 *  NOTE. filter no regex support for now
	 *
	 * @param filePath
	 * @param needLines
	 * @param filter
	 * @return String[] strs
	 */
	public static String[] tailFromFile(String filePath, int needLines, String filter){

		boolean filtermod = (filter != null && filter.length() > 0) ? true : false;
		boolean exclusive = (filtermod && filter.startsWith("-")) ? true : false;

		if (needLines <= 0 || needLines >= 50){
			needLines = 10;
		}

		String[] strs = new String[needLines];

		try {
			RandomAccessFile raf = new RandomAccessFile(filePath, "rb");

			int point = 0;
			String s;
			while ((s = raf.readLine()) != null){
				if (filtermod){
					if (exclusive){
						if (s.contains(filter.substring(1))){
							continue;
						}
					}
					else {
						if (! s.contains(filter)){
							continue;
						}
					}
				}

				strs[point] = s;
				if (++ point >= needLines){
					point = 0;
				}
			}

			// need a rotate
			if (strs[needLines -1] != null){
				// stl rotate algrithm
				// see : http://www.cplusplus.com/reference/algorithm/rotate/
				int first  = 0;
				int middle = point;
				int last   = needLines;
				int next   = middle;
				while (first != next)
				{
					//swap (*first++,*next++);
					s = strs[first];
					strs[first] =  strs[next];
					strs[next]  =  s;
					first += 1;
					next  += 1;

					if (next == last){
						next = middle;
					}
					else if (first == middle){
						middle = next;
					}
				}
			}

		} catch (Exception e) {
			log.warn("read from file error: " + filePath, e);
			return null;
		}

		return strs;
	}
[/code]

Post a Comment

Your email is never published nor shared. Required fields are marked *