Java文件I/O帮助
我的代码有问题。我需要对具有此结构的日志文件执行多个操作:Java文件I/O帮助,java,io,Java,Io,我的代码有问题。我需要对具有此结构的日志文件执行多个操作: 190.12.1.100 2011-03-02 12:12 test.html 190.12.1.100 2011-03-03 13:18 data.html 128.33.100.1 2011-03-03 15:25 test.html 128.33.100.1 2011-03-04 18:30 info.html 我需要得到每月的访问次数,每页的访问次数和基于IP的唯一访问者的数量。这不是问题,我设法让这三个操作都正常
190.12.1.100 2011-03-02 12:12 test.html
190.12.1.100 2011-03-03 13:18 data.html
128.33.100.1 2011-03-03 15:25 test.html
128.33.100.1 2011-03-04 18:30 info.html
我需要得到每月的访问次数,每页的访问次数和基于IP的唯一访问者的数量。这不是问题,我设法让这三个操作都正常工作。问题是,只有第一个选项正确运行,而其他选项随后只返回值0,就好像文件是空的一样,所以我猜我在某个地方犯了i/O错误。代码如下:
import java.io.*;
import java.util.*;
public class WebServerAnalyzer {
private Map<String, Integer> hm1;
private Map<String, Integer> hm2;
private int[] months;
private Scanner input;
public WebServerAnalyzer() throws IOException {
hm1 = new HashMap<String, Integer>();
hm2 = new HashMap<String, Integer>();
months = new int[12];
for (int i = 0; i < 12; i++) {
months[i] = 0;
}
File file = new File("webserver.log");
try {
input = new Scanner(file);
} catch (FileNotFoundException fne) {
input = null;
}
}
public String nextLine() {
String line = null;
if (input != null && input.hasNextLine()) {
line = input.nextLine();
}
return line;
}
public int getMonth(String line) {
StringTokenizer tok = new StringTokenizer(line);
if (tok.countTokens() == 4) {
String ip = tok.nextToken();
String date = tok.nextToken();
String hour = tok.nextToken();
String page = tok.nextToken();
StringTokenizer dtok = new StringTokenizer(date, "-");
if (dtok.countTokens() == 3) {
String year = dtok.nextToken();
String month = dtok.nextToken();
String day = dtok.nextToken();
int m = Integer.parseInt(month);
return m;
}
}
return -1;
}
public String getIP(String line) {
StringTokenizer tok = new StringTokenizer(line);
if (tok.countTokens() == 4) {
String ip = tok.nextToken();
String date = tok.nextToken();
String hour = tok.nextToken();
String page = tok.nextToken();
StringTokenizer dtok = new StringTokenizer(date, "-");
return ip;
}
return null;
}
public String getPage(String line) {
StringTokenizer tok = new StringTokenizer(line);
if (tok.countTokens() == 4) {
String ip = tok.nextToken();
String date = tok.nextToken();
String hour = tok.nextToken();
String page = tok.nextToken();
StringTokenizer dtok = new StringTokenizer(date, "-");
return page;
}
return null;
}
public void visitsPerMonth() {
String line = null;
do {
line = nextLine();
if (line != null) {
int m = getMonth(line);
if (m != -1) {
months[m - 1]++;
}
}
} while (line != null);
// Print the result
String[] monthName = {"JAN ", "FEB ", "MAR ",
"APR ", "MAY ", "JUN ", "JUL ", "AUG ", "SEP ",
"OCT ", "NOV ", "DEC "};
for (int i = 0; i < 12; i++) {
System.out.println(monthName[i] + months[i]);
}
}
public int count() throws IOException {
InputStream is = new BufferedInputStream(new FileInputStream("webserver.log"));
try {
byte[] c = new byte[1024];
int count = 0;
int readChars = 0;
while ((readChars = is.read(c)) != -1) {
for (int i = 0; i < readChars; ++i) {
if (c[i] == '\n')
++count;
}
}
return count;
} finally {
is.close();
}
}
public void UniqueIP() throws IOException{
String line = null;
for (int x = 0; x <count(); x++){
line = nextLine();
if (line != null) {
if(hm1.containsKey(getIP(line)) == false) {
hm1.put(getIP(line), 1);
} else {
hm1.put(getIP(line), hm1.get(getIP(line)) +1 );
}
}
}
Set set = hm1.entrySet();
Iterator i = set.iterator();
System.out.println("\nNumber of unique visitors: " + hm1.size());
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
System.out.print(me.getKey() + " - ");
System.out.println(me.getValue() + " visits");
}
}
public void pageVisits() throws IOException{
String line = null;
for (int x = 0; x <count(); x++){
line = nextLine();
if (line != null) {
if(hm2.containsKey(getPage(line)) == false)
hm2.put(getPage(line), 1);
else
hm2.put(getPage(line), hm2.get(getPage(line)) +1 );
}
}
Set set = hm2.entrySet();
Iterator i = set.iterator();
System.out.println("\nNumber of pages visited: " + hm2.size());
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
System.out.print(me.getKey() + " - ");
System.out.println(me.getValue() + " visits");
}
}
import java.io.*;
导入java.util.*;
公共类WebServerAnalyzer{
私有地图hm1;
私有地图hm2;
私人整数[]个月;
专用扫描仪输入;
公共WebServerAnalyzer()引发IOException{
hm1=新的HashMap();
hm2=新的HashMap();
月份=新整数[12];
对于(int i=0;i<12;i++){
月份[i]=0;
}
File File=新文件(“webserver.log”);
试一试{
输入=新扫描仪(文件);
}捕获(FileNotFoundException fne){
输入=空;
}
}
公共字符串nextLine(){
字符串行=null;
if(input!=null&&input.hasNextLine()){
line=input.nextLine();
}
回流线;
}
public int getMonth(字符串行){
StringTokenizer tok=新的StringTokenizer(行);
if(tok.countTokens()==4){
字符串ip=tok.nextToken();
字符串日期=tok.nextToken();
字符串hour=tok.nextToken();
字符串page=tok.nextToken();
StringTokenizer dtok=新的StringTokenizer(日期“-”);
if(dtok.countTokens()==3){
字符串year=dtok.nextToken();
字符串month=dtok.nextToken();
字符串day=dtok.nextToken();
int m=整数.parseInt(月);
返回m;
}
}
返回-1;
}
公共字符串getIP(字符串行){
StringTokenizer tok=新的StringTokenizer(行);
if(tok.countTokens()==4){
字符串ip=tok.nextToken();
字符串日期=tok.nextToken();
字符串hour=tok.nextToken();
字符串page=tok.nextToken();
StringTokenizer dtok=新的StringTokenizer(日期“-”);
返回ip;
}
返回null;
}
公共字符串getPage(字符串行){
StringTokenizer tok=新的StringTokenizer(行);
if(tok.countTokens()==4){
字符串ip=tok.nextToken();
字符串日期=tok.nextToken();
字符串hour=tok.nextToken();
字符串page=tok.nextToken();
StringTokenizer dtok=新的StringTokenizer(日期“-”);
返回页面;
}
返回null;
}
公共无效访问每月(){
字符串行=null;
做{
line=nextLine();
如果(行!=null){
int m=getMonth(行);
如果(m!=-1){
月[m-1]++;
}
}
}while(line!=null);
//打印结果
字符串[]monthName={“一月”、“二月”、“三月”,
“四月”、“五月”、“六月”、“七月”、“八月”、“九月”,
“十月”、“十一月”、“十二月”};
对于(int i=0;i<12;i++){
System.out.println(月[i]+月[i]);
}
}
public int count()引发IOException{
InputStream is=new BufferedInputStream(新文件InputStream(“webserver.log”);
试一试{
字节[]c=新字节[1024];
整数计数=0;
int readChars=0;
而((readChars=is.read(c))!=-1){
for(int i=0;i 对于(int x=0;x我还没有完全阅读代码,但我猜您在启动新操作时没有将读取位置设置回文件的开头。因此nextLine()
将返回null
您应该为每个操作创建一个新的扫描程序,然后将其关闭。AFAIK扫描程序不提供返回第一个字节的方法
目前,我还可以想出3个备选方案:
使用BufferedReader
并为每个新操作调用reset()
。如果您没有在某处调用mark()
,这将导致读卡器返回字节0
读取文件内容一次并在内存中的行上迭代,即将所有行放入列表中
,然后从每行开始
读取文件一次,分析每一行,并构造一个包含所需数据的适当数据结构。例如,您可以使用树形映射
,即,您将为每个日期存储每页每页每页的访问次数。然后,您可以按日期、页面和ip地址选择适当的子映射
我还没有完全阅读代码,但我猜您在启动新操作时没有将读取位置设置回文件的开头。因此nextLine()
将返回null
您应该为每个操作创建一个新的扫描程序,然后将其关闭。AFAIK扫描程序不提供返回第一个字节的方法
目前,我还可以想出3个备选方案:
使用BufferedReader
并为每个新操作调用reset()
。如果您没有在某处调用mark()
,这将导致读卡器返回字节0
读取文件内容一次并在内存中的行上迭代,即将所有行放入列表中
,然后从每行开始
读取文件一次,分析每一行,并构造一个包含所需数据的适当数据结构。例如,您可以使用树形映射
,即,您将为每个日期存储每页每页每页的访问次数。然后,您可以按日期、页面和ip地址选择适当的子映射
建议的BufferedReader
重置方法只有在文件大小小于缓冲区大小或调用时具有足够大的预读限制时才有效
我建议您通读该文件一次,并为每行更新地图和月数组。顺便说一句,您不需要扫描仪来读取行,BufferedReader有一个readLine
方法I
BufferedReader br = ...;
String line;
while (null != (line = br.readLine())) {
String ip = getIP(line);
String page = getPage(line);
int month = getMonth(line);
// update hashmaps and arrays
}