这是之前面试测试岗的时候出的,然后当时就答了个大概,写得不太好,今天特地好好学习了一波。
输入:
120.37.246.238 - - [16v/2017:19:20:08 +0800] "POST /c/s/newlog HTTP/1.1" 200
127.0.0.1 - - [16v/2017:19:20:08 +0800] "GET /n/apage-runtime/api/search/getSearchRecommend HTTP/1.0" 200
43.250.201.62 - - [16v/2017:19:20:08 +0800] "GET /n/apage-runtime/api/search/getSearchRecommend HTTP/1.1" 200
115.214.64.252 - - [16v/2017:19:20:08 +0800] "POST /c/s/newlog HTTP/1.1" 200
127.0.0.1 - - [16v/2017:19:20:08 +0800] "GET /n/apage-runtime/api/search/getSearchRecommend HTTP/1.0" 200
127.0.0.1 - - [16v/2017:19:20:06 +0800] "GET /n/apage-runtime/api/search/search_thread?word=%E4%BA%92%E6%8B%89&pn=1&tt=3 HTTP/1.0" 200
58.247.38.17 - - [16v/2017:19:20:06 +0800] "GET /n/apage-runtime/api/search/search_thread?word=%E7%94%9F%E4%B8%AA%E5%A5%B3%E5%AD%A9&pn=1&st=3&ct=1&cv=8.9.0&tt=1 HTTP/1.1" 200
输出:
/n/apage-runtime/api/search/search_thread 2
/c/s/newlog 2
/n/apage-runtime/api/search/getSearchRecommend 3
仔细分析,也就是从日志文件中把url出现的次数统计下来。当时面试官刚说出来,我一下子没有发现比较本质的规律,想着把T和H里面的东西或者把T和?里面的东西取出来就行了,当时的代码是这样的:
while ((lineTxt = bufferedReader.readLine()) != null)
String url = subString(lineTxt, "T", "?");
if (url == null) {
url = subString(lineTxt, "T", "H");
}
唉,虽然确实把数据提取出来了,可是却是投机取巧的那种,大伙分析一下就明白了。后面我还用list去存储url,最后都没想出来怎么统计次数(因为当时想的方法很麻烦,就不想写了)
然后就凉凉了。
接下来说一下我现在认为正确的解法吧。
首先,分析日志数据的规律,发现url都是处于第六个空格后面,这就是它的一般规律。所以应该先用spilt切割字符串成字符串数组,然后取出数组的第六组数据。代码如下:
String[] strings = lineTxt.split(" ");
String url = strings[6];
然后url中还有带参数的,而我们统计的是不带参数的,所以得把后面的参数去掉,根据特点分析我们知道就是把?号及其后面的字符串去掉就行了,所以这里我是先用indexof函数获取?号的位置,然后用substring方法取出从0到?号位置的字符串,这就是我们要的url了,代码如下:
if (url.contains("?")) {
int divide = url.indexOf("?");
url = url.substring(0, divide);
}
正确的获取url之后,需要统计每个url出现的次数,这里要利用hashmap来进行存储,也就是说一个entry节点的key用来存放url,value用来存储出现的次数。第一次存放是value为1,后面存放时就先取出再加1。具体代码如下:
if (map.containsKey(url)) {
int count = map.get(url);
map.put(url, ++count);
} else {
map.put(url, 1);
}
最后遍历entry输出就完事了
public class GetUrl {
public static void main(String[] args) {
Map map = readTxtFileIntoStringMap("d://access.txt");
for (Map.Entry entry : map.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
System.out.println("finish");
}
public static Map readTxtFileIntoStringMap(String filePath) {
Map map = new HashMap();
try {
String encoding = "GBK";
File file = new File(filePath);
if (file.isFile() && file.exists()) { // 判断文件是否存在
InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);// 考虑到编码格式
BufferedReader bufferedReader = new BufferedReader(read);
String lineTxt = null;
while ((lineTxt = bufferedReader.readLine()) != null) {
String[] strings = lineTxt.split(" ");
String url = strings[6];
if (url.contains("?")) {
int divide = url.indexOf("?");
url = url.substring(0, divide);
}
System.out.println("取出的url=" + url);
if (map.containsKey(url)) {
int count = map.get(url);
map.put(url, ++count);
} else {
map.put(url, 1);
}
}
bufferedReader.close();
read.close();
} else {
System.out.println("找不到指定的文件");
}
} catch (Exception e) {
System.out.println("读取文件内容出错");
e.printStackTrace();
}
return map;
}
}
输出结果如下:
取出的url=/c/s/newlog
取出的url=/n/apage-runtime/api/search/getSearchRecommend
取出的url=/n/apage-runtime/api/search/getSearchRecommend
取出的url=/c/s/newlog
取出的url=/n/apage-runtime/api/search/getSearchRecommend
取出的url=/n/apage-runtime/api/search/search_thread
取出的url=/n/apage-runtime/api/search/search_thread
/n/apage-runtime/api/search/search_thread 2
/c/s/newlog 2
/n/apage-runtime/api/search/getSearchRecommend 3
finish
现在感觉是很完美的。