I have a text file which has details like date,time,phone number, etc. I am trying to retrieve these details using the java indexOf concept. However, the digits in the phone number would change depending on the type of call.
How can I improve the code so I am able to retrieve every phone number from the file. Here's what I've been trying :
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String getIndex="";
while ((line = reader.readLine()) != null) {
line = line.replaceAll("[\\s]+", " "); //remove all large spaces from the file.
/*
the dialledNo is chosen with the help of a combo box.
calculating the start and end index in order to print the dialled no.
*/
int startIndex = getIndex.indexOf(dialledNo);
int endIndex = getIndex.indexOf(" ", startIndex);
strDialedNo= (startIndex + "," + endIndex);
And the code to retrieve the number is mentioned below :
String[] arrDialedNo = strDialedNo.split(",");
int DialedNoStart = Integer.parseInt(arrDialedNo[0]);
int DialedNoEnd = Integer.parseInt(arrDialedNo[1]);
DialedNo = line.substring(DialedNoStart, DialedNoEnd);
This is how my text file looks like:
0356 524 000 8861205063 12/03 18:59 00:08 01:20
0357 524 000 9902926868 12/03 20:01
0373 511 000 09886863637 13/03 11:46 01:01 02:40 S
0376 504 000 9845014967 13/03 11:46 00:11 01:20
0382 508 000 04443923200 13/03 12:04 03:11 04:80 S
0411 516 000 8884103111 13/03 16:25 01:03 01:20
This should work,
String[] b = line.split(" ");
String phoneNumber = null;
for (String x : b) {
boolean z = false;
if (x.length() == 10) {
char[] c = x.toCharArray();
for (char g : c) {
if (Character.isDigit(g)) {
z = true;
} else {
z = false;
break;
}
}
} else {
z = false;
}
if (z) {
phoneNumber = x;
}
}
/* Easiest way to to retrieve Phone number from Text file using Java */
package TestProject.EndToEnd;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class FileReader {
public static void main(String[] args) throws FileNotFoundException {
File file = new File("//File//Path//");
List<Object> ph = new ArrayList<Object>();
Scanner scan = new Scanner(file);
while(scan.hasNext()) {
scan.next();
if(scan.hasNextBigInteger()) {
ph.add(scan.next());
}
}
for (int i = 0; i < ph.size(); i++) {
if(ph.get(i).toString().length()==10) {
System.out.println(ph.get(i));
}
}
}
}
Related
I'm creating a program which reads the contents of a .txt file, it validates and then outputs the contents of that file in a nice formatted table. My program currently reads the file and then outputs the content, I'm trying to implement the validation of said file content.
I'll now explain the way my program reads the file:
The .txt contents:
firstname lastname
Gameone : 120 : 1428
Gametwo : 20 : 10
Gamethree : 90 : 800
Gamefour : 190 : 2001
Gamefive : 25 : 80
Gamesix : 55 : 862
The txt file contains data in this format:
{gamename} : {gamescore} : {minutesplayed}
To read the .txt I use:
System.out.println("*FILE HAS BEEN LOCATED*");
System.out.println("*File contains: \n");
while(scan.hasNext())
{
a = scan.nextLine();
b = scan.nextLine();
c = scan.nextLine();
d = scan.nextLine();
e = scan.nextLine();
f = scan.nextLine();
g = scan.nextLine();
}
To then split the data I use this for loop on each letter from a-to-g as shown below:
//~~~~a-line-split~~~~//
String[] aline;
aline = a.split(":");
for (int i=0; i<aline.length; i++)
{
aline[i] = aline[i].trim();
//System.out.println(aline[i]);
}
To clarify by validation I need to inform the user if data is missing from a line for example if line one had:
gameone : {missing} : 1428
currently I have this simple if statement for each line:
if (bline.length < 3)
{
System.out.println("There is an error in row one!");
}
However I need to the program to know exactly where on each line the data is missing. Not just a generic response of:
System.out.println("There is an error in row one!");
But instead something along the lines of:
System.out.println("There is data missing, row: 1 column: 2");
Full code as requested:
package readfile;
import java.io.*;
import java.util.*;
public class readfile
{
public static void main(String[] args)
{
Scanner scan = new Scanner (System.in);
String FileN = " ";
String a = " ";
String b = " ";
String c = " ";
String d = " ";
String e = " ";
String f = " ";
String g = " ";
boolean fileExists = false;
File newFile = null;
while(!fileExists)
{
System.out.println("Enter the name of the file you want to open: ");
FileN = scan.nextLine();
newFile = new File(FileN);
fileExists = newFile.exists();
if (!fileExists)
{
System.out.println(FileN + " not found...");
}
}
try {
Scanner scan2;
scan = new Scanner(newFile);
}
catch(FileNotFoundException fnfe) {
System.out.println("sorry but the file doesn't seem to exist");
}
//++++++++++++++=FILE READ=++++++++++++++++++++
System.out.println("*FILE HAS BEEN LOCATED*");
System.out.println("*File contains: \n");
while(scan.hasNext())
{
a = scan.nextLine();
b = scan.nextLine();
c = scan.nextLine();
d = scan.nextLine();
e = scan.nextLine();
f = scan.nextLine();
g = scan.nextLine();
}
//+++++++++++++++ARRAYS FOR THE LINES+++++++++++++++++++
//~~~~A-LINE~~~~//
String[] aline;
aline = a.split(":");
for (int i=0; i<aline.length; i++)
{
aline[i] = aline[i].trim();
//System.out.println(aline[i]);
}
//~~~~B-LINE~~~~//
String[] bline;
bline = b.split(":");
for (int i=0; i<bline.length; i++)
{
bline[i] = bline[i].trim();
//System.out.println(bline[i]);
}
//~~~~C-LINE~~~~//
String[] cline;
cline = c.split(":");
for (int i=0; i<cline.length; i++)
{
cline[i] = cline[i].trim();
//System.out.println(cline[i]);
}
//~~~~D-LINE~~~~//
String[] dline;
dline = d.split(":");
for (int i=0; i<dline.length; i++)
{
dline[i] = dline[i].trim();
//System.out.println(dline[i]);
}
//~~~~e-LINE~~~~//
String[] eline;
eline = e.split(":");
for (int i=0; i<eline.length; i++)
{
eline[i] = eline[i].trim();
//System.out.println(eline[i]);
}
//~~~~f-LINE~~~~//
String[] fline;
fline = f.split(":");
for (int i=0; i<fline.length; i++)
{
fline[i] = fline[i].trim();
//System.out.println(fline[i]);
}
//~~~~g-LINE~~~~//
String[] gline;
gline = g.split(":");
for (int i=0; i<gline.length; i++)
{
gline[i] = gline[i].trim();
//System.out.println(gline[i]);
}
String user = aline [0];
//~~~~~~~~~GAME NAMES~~~~~~~~~~~~~//
//GTA
String gameone = bline [0];
//MINECRAFT
String gametwo = cline [0];
//ASSASSIN'S CREED IV
String gamethree = dline [0];
//PAYDAY2
String gamefour = eline [0];
//WOLFENSTEIN
String gamefive = fline [0];
//FARCRY 4
String gamesix = gline [0];
//~~~~~~~~~~Achievement Score~~~~~~~~~~~~//
//GTA SCORE
String scoreone = bline [1];
//MINECRAFT SCORE
String scoretwo = cline [1];
//ASSASSIN'S CREED IV SCORE
String scorethree = dline [1];
//PAYDAY2 SCORE
String scorefour = eline [1];
//WOLFENSTEIN SCORE
String scorefive = fline [1];
//FARCRY 4 SCORE
String scoresix = gline [1];
//+++++++++++++++++++++TOTAL~~CALC++++++++++++++++++++++//
double totalcount = 79.566; // change to the amount played.
int totalhours = (int)totalcount;
int totalmin = (int)(totalcount*60)%60;
int totalsec = (int)(totalcount*(60*60))%60;
System.out.println("TOTAL TIME PLAYED:");
System.out.println(String.format("%s(hours) %s(minutes) %s(seconds)",
totalhours, totalmin, totalsec));
//~~~~~~~~~~Minutes Played~~~~~~~~~~~~//
//GTA min
String minone = bline [2];
//MINECRAFT min
String mintwo = cline [2];
//ASSASSIN'S CREED IV min
String minthree = dline [2];
//PAYDAY2 min
String minfour = eline [2];
//WOLFENSTEIN min
String minfive = fline [2];
//FARCRY 4 min
String minsix = gline [2];
//~~~~~~~~~GAMES TEST~~~~~~~~~~~~//
System.out.println("\nUSER: "+user);
System.out.println("\nDATA: ");
System.out.println("1: "+gameone+" | score: "+scoreone+"
| minutes played: "+minone);
System.out.println("2: "+gametwo+" | score: "+scoretwo+"
| minutes played: "+mintwo);
System.out.println("3: "+gamethree+" | score: "+scorethree+"
| minutes played: "+minthree);
System.out.println("4: "+gamefour+" | score:
"+scorefour+" | minutes played: "+minfour);
System.out.println("5: "+gamefive+" | score: "+scorefive+"
| minutes played: "+minfive);
System.out.println("6: "+gamesix+" | score: "+scoresix+"
| minutes played: "+minsix);
if (bline.length < 3)
{
int column = 0;
for(int i = 0; i<bline.length; i++){
column = i;
if(bline[i] == null || bline[i].trim() == ""){
System.out.println("There is an error in row two
column "+(i+1));
}
}
}
}
}
if (bline.length < 3)
{
int column = 0;
for(int i = 0; i<bline.length; i++){
column = i;
if(bline[i] == null || bline[i].trim() == ""){
System.out.println("There is an error in row two column "+(i+1));
}
}
}
Didn't test this but it should work
EDIT:
Looking at your full code bline[2], cline[2]... and so on will give you an Index Out of bounds exception if those values are missing from the file in the first place so before making that call you should do a check first you can create a static method to do the check
public static String getAtIndex(String[] array, int indexToCkeck){
if(indexToCkeck >=array.length){
return "";
}
else{
return array[indexToCkeck];
}
}
So instead of doing bline[2], cline[2] ... use readfile.getAtIndex(bline, 2) so this way if the info is missing it will return an empty string
Also not tested, should be fine though
Use a well tested library like supercsv or any other. This will save you some hours as soon as your text format gets more complex. It also provides a good set of build-in data types to be used to validate each single column of your data. Also you can map the data directly to a POJO which can be handy in some situations.
To load just each row into a map you could do the following:
Prepare your file in stack47220687.txt:
Gamename: Gamescore: Minutestoplay
Gameone : 120 : 1428
Gametwo : 20 : 10
Gamethree : 90 : 800
Gamefour : 190 : 2001
Gamefive : 25 : 80
Gamesix : 55 : 862
And use something like this
package stack47220687;
import java.io.FileReader;
import java.util.Map;
import org.junit.Test;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvMapReader;
import org.supercsv.io.ICsvMapReader;
import org.supercsv.prefs.CsvPreference;
public class HowToReadACSVFile {
private static final CsvPreference COLON_DELIMITED = new CsvPreference.Builder('"', ':', "\n").build();
private static CellProcessor[] getProcessors() {
final CellProcessor[] processors = new CellProcessor[] { new NotNull(), // gamename
new NotNull(), // gamescore
new NotNull(), // minutestoplay
};
return processors;
}
#Test
public void read() throws Exception {
ICsvMapReader mapReader = null;
try {
mapReader = new CsvMapReader(new FileReader(
Thread.currentThread().getContextClassLoader().getResource("stack47220687.txt").getPath()),
COLON_DELIMITED);
// the header columns are used as the keys to the Map
final String[] header = mapReader.getHeader(true);
final CellProcessor[] processors = getProcessors();
Map<String, Object> oneRecordInAMap;
while ((oneRecordInAMap = mapReader.read(header, processors)) != null) {
System.out.println(String.format("lineNo=%s, rowNo=%s, this line stored in a map=%s",
mapReader.getLineNumber(), mapReader.getRowNumber(), oneRecordInAMap));
/**
* oneRecordInAMap.get("Gamescore");
*/
}
} finally {
if (mapReader != null) {
mapReader.close();
}
}
}
}
works with super-csv 2.4.0
<dependency>
<groupId>net.sf.supercsv</groupId>
<artifactId>super-csv</artifactId>
<version>2.4.0</version>
</dependency>
and will print
lineNo=2, rowNo=2, this line stored in a map={ Gamescore= 120 , Gamename=Gameone , Minutestoplay= 1428 }
lineNo=3, rowNo=3, this line stored in a map={ Gamescore= 20 , Gamename=Gametwo , Minutestoplay= 10 }
lineNo=4, rowNo=4, this line stored in a map={ Gamescore= 90 , Gamename=Gamethree , Minutestoplay= 800 }
lineNo=5, rowNo=5, this line stored in a map={ Gamescore= 190 , Gamename=Gamefour , Minutestoplay= 2001 }
lineNo=6, rowNo=6, this line stored in a map={ Gamescore= 25 , Gamename=Gamefive , Minutestoplay= 80 }
lineNo=7, rowNo=7, this line stored in a map={ Gamescore= 55 , Gamename=Gamesix , Minutestoplay= 862}
It will also provide meaningful error messages if your format is not correct.
I am working on implementing a generic code to solve left recursion problem in a grammar using java so my code is working as follows I am reading an input like this as each line goes to the next line:
E
E+T|T
T
T*F|F
F
(E)|id|number
and the required output is supposed to be like this one :
E->[TE']
T->[FT']
F->[(E), id, number]
E'->[+TE', !]
T'->[*FT', !]
I wrote that code which is storing input in Arraylists to iterate over them and produce the output:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class IleftRecursion {
//storing each line in its corresponding Arraylist
static ArrayList<String> leftRules = new ArrayList<>();
static ArrayList<String> rightRules = new ArrayList<>();
public static void read_file(String file) throws IOException {
FileReader in = new FileReader(file);
BufferedReader br = new BufferedReader(in);
String line;
while ((line = br.readLine()) != null) {
leftRules.add(line);
rightRules.add(br.readLine());
}
br.close();
}
public static void ss() {
for (int i = 0; i < leftRules.size(); i++) {
for (int j = 1; j <= i - 1; j++) {
//splitting inputs on bars "|" to iterate through them
for (String x : rightRules.get(i).split("\\|")) {
if (x.contains(leftRules.get(j))) {
String f = "";
String ff = "";
for (int k=0; k<rightRules.get(k).split("\\|").length;k++) {
f = x;
f = f.replaceAll(leftRules.get(i), rightRules.get(k).split("\\|")[k]);
ff += f;
}
rightRules.remove(i);
rightRules.add(i, ff);
}
}
}
//Recursive or Not boolean
boolean isRec = false;
for (String z : rightRules.get(i).split("\\|")) {
if (z.startsWith(leftRules.get(i))) {
isRec = true;
break;
}
}
if (isRec) {
String a = "";
String b = "";
for (String s : rightRules.get(i).split("\\|")) {
if (s.startsWith(leftRules.get(i))) {
b += s.replaceAll(leftRules.get(i), "") + leftRules.get(i) + "',";
} else {
a += s + leftRules.get(i) + "'";
}
}
b += "!";
if(a.length()>=1)
a.substring(1, a.length() - 1);
rightRules.add(i, a);
rightRules.add(i + 1, b);
leftRules.add(leftRules.get(i) + "'");
}
}
}
public static void main(String[] args) throws IOException {
read_file("Sample.in");
ss();
for (int i=0;i<leftRules.size();i++)
{
System.out.print(leftRules.get(i)+"->");
System.out.println("["+rightRules.get(i)+"]");
}
}
}
I debugged the code many times trying to figure out why Am I getting output like this
E->[TE']
T->[+TE',!]
F->[T]
E'->[T*F]
Which is missing One rule and also not all the new productions generated in the right way but I couldn't fix could anyone help me through that ?
I am trying to open two text files and find similar lines in them.
My code is correctly reading all the lines from both the text files.
I have used nested for loops to compare line1 of first text file with all lines of second text file and so on.
However, it is only detecting similar lines which have same line number,
(eg. line 1 of txt1 is cc cc cc and line 1 of txt2 is cc cc cc, then it correctly finds and prints it),
but it doesn't detect same lines on different line numbers in those files.
import java.io.*;
import java.util.*;
public class FeatureSelection500 {
public static void main(String[] args) throws FileNotFoundException, IOException {
// TODO code application logic here
File f1 = new File("E://implementation1/practise/ComUpdatusPS.exe.hex-04-ngrams-Freq.txt");
File f2 = new File("E://implementation1/practise/top-300features.txt");
Scanner scan1 = new Scanner(f1);
Scanner scan2 = new Scanner(f2);
int i = 1;
List<String> txtFileOne = new ArrayList<String>();
List<String> txtFileTwo = new ArrayList<String>();
while (scan1.hasNext()) {
txtFileOne.add(scan1.nextLine());
}
while (scan2.hasNext())
{
txtFileTwo.add(scan2.nextLine());
}
/*
for(String ot : txtFileTwo )
{
for (String outPut : txtFileOne)
{
// if (txtFileTwo.contains(outPut))
if(outPut.equals(ot))
{
System.out.print(i + " ");
System.out.println(outPut);
i++;
}
}
}
*/
for (int j = 0; j < txtFileTwo.size(); j++) {
String fsl = txtFileTwo.get(j);
// System.out.println(fileContentSingleLine);
for (int z = 0; z < 600; z++) // z < txtFileOne.size()
{
String s = txtFileOne.get(z);
// System.out.println(fsl+"\t \t"+ s);
if (fsl.equals(s)) {
System.out.println(fsl + "\t \t" + s);
// my line
// System.out.println(fsl);
} else {
continue;
}
}
}
}
}
I made your code look nicer, you're welcome :)
Anyway, I don't understand that you get that bug. It runs through all of the list2 for every line in the list1...
import java.io.*;
import java.util.*;
public class FeatureSelection500 {
public static void main(String[] args) throws FileNotFoundException, IOException {
// TODO code application logic here
File file1 = new File("E://implementation1/practise/ComUpdatusPS.exe.hex-04-ngrams-Freq.txt");
File file2 = new File("E://implementation1/practise/top-300features.txt");
Scanner scan1 = new Scanner(file1);
Scanner scan2 = new Scanner(file2);
List<String> txtFile1 = new ArrayList<String>();
List<String> txtFile2 = new ArrayList<String>();
while (scan1.hasNext()) {
txtFile1.add(scan1.nextLine());
}
while (scan2.hasNext()) {
txtFile2.add(scan2.nextLine());
}
for (int i = 0; i < txtFile2.size(); i++) {
String lineI = txtFile2.get(i);
// System.out.println(fileContentSingleLine);
for (int j = 0; j < txtFile1.size(); j++){ // z < txtFileOne.size(
String lineJ = txtFile1.get(j);
// System.out.println(fsl+"\t \t"+ s);
if (lineI.equals(lineJ)) {
System.out.println(lineI + "\t \t" + lineJ);
// my line
// System.out.println(fsl);
}
}
}
}
}
I don't see any problem with your code. Even the block you commented is absolutely fine. Since, you are doing equals() you should make sure that you have same text (same case) in the two files for them to be able to satisfy the condition successfully.
for(String ot : txtFileTwo )
{
for (String outPut : txtFileOne)
{
if(outPut.equals(ot)) /* Check Here */
{
/* Please note that here i will not give you line number,
it will just tell you the number of matches in the two files */
System.out.print(i + " ");
System.out.println(outPut);
i++;
}
}
}
i have a text file that has date/time, name, amount tipped, total tips
I am able to get it reduced to just names (In one arraylist) and amount tipped(in a second arraylist)
Now I'm trying to get it to where it adds up the amount tipped per person.
So if X tipped 10,20,30,40 it will output X tipped 100.
From Text file
Dec. 6, 2013, 8:31 p.m. Tip from y
25 7687
Dec. 6, 2013, 8:30 p.m. Tip from x
30 7662
Dec. 6, 2013, 8:30 p.m. Tip from z
25 7632
Dec. 6, 2013, 8:31 p.m. Tip from z
25 7687
Dec. 6, 2013, 8:30 p.m. Tip from z
30 7662
Dec. 6, 2013, 8:30 p.m. Tip from x
25 7632
Here is where I am at so far
import java.io.*;
import java.util.*;
public class TipTester {
public static void main(String[] args) {
int lineNumber = 1;
List<String> name = new ArrayList<String>();
List<String> tip = new ArrayList<String>();
String fileName = "C:\\Users\\David\\Desktop\\tips.txt";
System.out.println("Reading text from file");
try {
FileReader inputFile = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(inputFile);
String line;
while ((line = bufferedReader.readLine()) != null) {
if (lineNumber % 2 != 0) {
System.out.println(line.substring(line.indexOf("from ") + 5) + "\\");
name.add(line.substring(line.indexOf("from ") + 5) + "\\");
} else {
System.out.println(line.substring(0, line.indexOf("\t")) + "\\");
tip.add(line.substring(0, line.indexOf("\t")) + "\\");
}
lineNumber ++;
}
bufferedReader.close();
name.add("-");
tip.add("-");
} catch (Exception e) {
System.out.println("Error while reading file line by line: " + e.getMessage());
}
}
}
Instead of using two different lists. You can just use a map.
Map<String, Double> map = new HashMap<String, Double>();
while ((line = br.readLine()) != null){
double tip = // get tip from line
String name = // get name from line
if (!map.containsKey(name)){ // if map doesn't contain name
map.put(name, tip); // put in the initial name and tip amount
} else {
double value = map.get(name); // else get the current value from the map
map.put(name, value + tip); // put in the new value to the map
}
}
Now your map contains names and total tips
Edit: If you're using two different lists, you want to keep the name and tips in parallel indices.
You could do something like this
ArrayList<String> nameList = new ArrayList<>();
ArrayList<Integer> tipList = new ArrayList<>();
while ((line = br.readLine()) != null){
String name = // get name from line
int tip = // get tip from next line
if (!nameList.contains(name)){ // if list doesnt contain the name
nameList.add(name); // add the name
tipList.add(tip); // add the tpi
} else {
int index = nameList.indexOf(name); // else get the index of the name
int newTip = tipList.get(index) + tip; // get the tip amount + new tip
tipList.set(index, newTip); // set the tip amount
}
}
Without too much modifications of your code (introduced a Map and used Integer for tips):
package com.stackoverflow.so20560521;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Map;
public class Tip {
public static void main(String[] args)
{
int lineNumber = 1;
Map<String, Integer> tipsByName = new HashMap<String, Integer>();
String fileName = "C:\\Users\\David\\Desktop\\tips.txt";
System.out.println("Reading text from file");
try {
FileReader inputFile = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(inputFile);
String line;
String currentTipper = null;
while ((line = bufferedReader.readLine()) != null) {
if (lineNumber % 2 != 0) {
final String tipperName = line.substring(line.indexOf("from ") + 5);
System.out.println(tipperName);
currentTipper = tipperName;
} else {
final Integer tipValue = Integer.parseInt(line.substring(0, line.indexOf("\\t")));
System.out.println(tipValue);
// here we store the tip in the map. If we have a record we sum, else
// we store as is
tipsByName.put(currentTipper, (tipsByName.get(currentTipper) == null ? 0 : tipsByName.get(currentTipper))
+ tipValue);
}
lineNumber++;
}
bufferedReader.close();
System.out.println(tipsByName); // output the map
} catch (Exception e) {
System.out.println("Error while reading file line by line: " + e.getMessage());
}
}
}
This outputs
Reading text from file
y
25
x
30
z
25
z
25
z
30
x
25
{z=80, y=25, x=55}
I have a problem with my code. I need to do several operations on a log file with this structure:
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
I need to get the number of visits per month, number of visits per page and number of unique visitors based on the IP. That is not the question, I managed to get all three operations working. The problem is, only the first choice runs correctly while the other choices just return values of 0 afterwards, as if the file is empty, so i am guessing i made a mistake with the I/O somewhere. Here's the code:
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");
}
}
Any help figuring out the problem would be much appreciated as I am quite stuck.
I didn't read the code thoroughly yet, but I guess you're not setting the read position back to the beginning of the file when you start a new operation. Thus nextLine() would return null.
You should create a new Scanner for each operation and close it afterwards. AFAIK scanner doesn't provide a method to go back to the first byte.
Currently I could also think of 3 alternatives:
Use a BufferedReader and call reset() for each new operation. This should cause the reader to go back to byte 0 provided you didn't call mark() somewhere.
Read the file contents once and iterate over the lines in memory, i.e. put all lines into a List<String> and then start at each line.
Read the file once, parse each line and construct an apropriate data structure that contains the data you need. For example, you could use a TreeMap<Date, Map<Page, Map<IPAdress, List<Visit>>>>, i.e. you'd store the visits per ip address per page for each date. You could then select the appropriate submaps by date, page and ip address.
The reset method of BufferedReader that Thomas recommended would only work if the file size is smaller than the buffer size or if you called mark with a large enough read ahead limit.
I would recommend reading throught the file once and to update your maps and month array for each line. BTW, you don't need a Scanner just to read lines, BufferedReader has a readLine method itself.
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
}