This is the program I need to make,
Make a class that represents a file. This class will have the ability to calculate the number of lines in that file and the ability to search through the file. The getNumLinesThatContain method will take a bit of text and determine how many lines contain that text. Make the comparison not care about case. Example: if the user is searching for hello and a line contains the text hello hello hello then this counts as one. Use the contains method defined on Strings to help with this. Class Name FileStats Fields
- filename : String Methods
- FileStats(filename : String)
- getNumLinesThatContain(key : String) : int
- getNumLines() : int
This is what I have so far,
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Objects;
import java.util.Scanner;
public class FileStats {
private String filename;
Scanner inputFile;
public FileStats(String f) {
filename = f;
}
public int getNumLines() throws FileNotFoundException {
//make a variable to hold the filename
File fileObj = new File(filename);
inputFile = new Scanner(fileObj);
//keep track of the number lines
int numLines = 0;
//while there's more stuff to read...
while (inputFile.hasNext()) {
//read a line
String line = inputFile.nextLine();
//keep track of that line
numLines ;
}
//close the file
inputFile.close();
//return the result
return numLines;
}
public int getNumLinesThatContain(String key){
// variable to keep track of file name
File fileObj = new File(filename);
inputFile = new Scanner(filename);
//keep track of the number lines
int numLines = 0;
//while there is more stuff to read
while (inputFile.hasNext()){
//read a line
String line = inputFile.nextLine();
//keep track of the line if word
//this is where I think the problem is
if(line.toUpperCase().contains(key.toUpperCase())) {
numLines ;
}
}
inputFile.close();
return numLines;
}
}
For the method getNumLinesThatContain I just get 1s and 0s when I run the file. I have tried changing the if statement to one that compares line and key, to one that sees if they are equal, and the one shown checks to see if the line contains the key. I can't seem to figure out how to get the counter to count the lines that contain the key correctly. Please help.
CodePudding user response:
Isn't this your problem?
inputFile = new Scanner(filename);
It should be
inputFile = new Scanner(fileObj);
You should read from the file object and not from the String filename. You have used it correctly for the first method where you count all the lines.
CodePudding user response:
BE SIMPLE!!!
public final class FileStats {
private final Path file;
public FileStats(String pathname) {
file = Paths.get(pathname);
}
public int getNumLines() throws IOException {
return Files.readAllLines(file).size();
}
public int getNumLinesThatContain(String key) throws IOException {
String lowerCaseKey = key.toLowerCase();
return (int)Files.readAllLines(file).stream()
.map(String::toLowerCase)
.filter(line -> line.contains(lowerCaseKey))
.count();
}
}
CodePudding user response:
If you do it like this, you can write ONE method that does BOTH: If the argument is null, all lines are counted. If the argument is a String (Case doesn't matter.), only lines are counted that contain that String.
final String keyLowerCase = key == null ? null : key.toLowerCase();
int amountOfLines = 0;
try (final BufferedReader br = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
String line;
while ((line = br.readLine()) != null) {
if (keyLowerCase == null || line.toLowerCase().contains(keyLowerCase)) {
amountOfLines ;
}
}
} catch (IOException e) {
e.printStackTrace();
}
CodePudding user response:
This uses a BufferedReader
to read in the lines as a stream. The mark
and reset
methods are used to essentially rewind the file for each method call.
public class FileStatsTest {
public static void main(String[] args) {
String searchString = "to";
String fileName = "some file";
FileStats fs = new FileStats(fileName);
System.out.println(fs.getNumLines());
System.out.println(fs.getNumLinesThatContain(searchString));
}
}
class FileStats {
private File file;
BufferedReader br;
public FileStats(String fileName) {
file = new File(fileName);
try {
br = new BufferedReader(new FileReader(file));
br.mark((int) file.length() 1); // just file.length() won't work
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public int getNumLines() {
try {
br.reset(); // effectively reset to start of file
} catch (IOException ioe) {
ioe.printStackTrace();
}
return (int) br.lines().count();
}
public int getNumLinesThatContain(String key) {
String keyLC = key.toLowerCase();
try {
br.reset(); // effectively reset to start of file
} catch (IOException ioe) {
ioe.printStackTrace();
}
return (int) br.lines().filter(str -> str.toLowerCase().contains(key))
.count();
}
}
Limitations
- This won't work for files larger than
Integer.MAX_VALUE-1
as mark only accepts an integer value. - the returned
count
is along
and cast to anint
. Not a problem since mark would fail long before the high order word of count is masked off from the cast.