How can you search through a txt file for a String that the user inputs and then return that String to the console. I've written some code that doesn't work below, but I hope it can illustrate my point...
public static void main(String[] args) {
searchforName();
}
private static void searchForName() throws FileNotFoundException {
File file = new File("leaders.txt");
Scanner kb = new Scanner(System.in);
Scanner input = new Scanner(file);
System.out.println("Please enter the name you would like to search for: ");
String name = kb.nextLine();
while(input.hasNextLine()) {
System.out.println(input.next(name));
}
}
The "leaders.txt" file contains a list of names.
You should read (create a function) words from the file. And by words I mean array of non-whitespace characters surrounded by whitespaces such as blank space (but don't record the white spaces in the words list). Then search through the word list (or through the words on the fly) to look for the required word.
To find a word in the string, we are using indexOf() and contains() methods of String class. The indexOf() method is used to find an index of the specified substring in the present string. It returns a positive integer as an index if substring found else returns -1.
You can create a seperate Scanner
to read the file line by line and do a match that way...
final Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
final String lineFromFile = scanner.nextLine();
if(lineFromFile.contains(name)) {
// a match!
System.out.println("I found " +name+ " in file " +file.getName());
break;
}
}
With regards to whether you should use a Scanner
or a BufferedReader
to read the file, read this answer.
Scanner is way too slow. Run the following code, and see the differences. Searched in 750 MB file, and BufferedReader is 10 times faster than Scanner on average.
package uk.co.planetbeyond.service.test;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Date;
import java.util.HashSet;
import java.util.Scanner;
public class SearchTextInFile
{
public static void main(String[] args) throws IOException
{
// First write a file, with large number of entries
writeFile("/home/aqeel/temp/subscribers_files.csv");
long scannerSearchMillis = 0;
long brSearchMillis = 0;
int iterations = 5;
// Now search random strings five times, and see the time taken
for (int i = 0; i < iterations; i++)
{
String msisdn = String.valueOf(923000000000l + ((long) (Math.random() * 40000000)));
System.out.println("ITERATION " + i);
System.out.print("Search " + msisdn + " using scanner");
Date d1 = new Date();
searchUsingScanner("/home/aqeel/temp/subscribers_files.csv", msisdn);
Date d2 = new Date();
long millis = (d2.getTime() - d1.getTime());
scannerSearchMillis += millis;
System.out.println(" | " + (millis / 1000) + " Seconds");
System.out.println("==================================================================");
System.out.print("Search " + msisdn + " using buffered reader");
d1 = new Date();
searchUsingBufferedReader("/home/aqeel/temp/subscribers_files.csv", msisdn);
d2 = new Date();
millis = d2.getTime() - d1.getTime();
brSearchMillis += millis;
System.out.println(" | " + (millis / 1000) + " Seconds");
System.out.println("==================================================================");
System.out.println("==================================================================");
System.out.println("==================================================================");
System.out.println("==================================================================");
}
System.out.println("Average Search time using Scanner " + (scannerSearchMillis / (iterations * 1000.0)) + " Seconds");
System.out.println("Average Search time using BufferedReader " + (brSearchMillis / (iterations * 1000.0)) + " Seconds");
}
public static void writeFile(String path)
{
BufferedWriter csvWriter = null;
HashSet<Integer> additions = new HashSet<Integer>();
try
{
csvWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path)));
for (int i = 0; i < 40000000; i++)
{
int addition = (int) (Math.random() * 40000000);
additions.add(addition);
if (i % 20000 == 0)
{
System.out.println("Entries written : " + i + " ------ Unique Entries: " + additions.size());
csvWriter.flush();
}
long msisdn = 923000000000l + addition;
csvWriter.write(String.valueOf(msisdn) + "|" + String.valueOf((int) (Math.random() * 131)) + "\r\n");
}
csvWriter.flush();
System.out.println("Unique Entries written : " + additions.size());
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
if (csvWriter != null)
{
try
{
csvWriter.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static String searchUsingScanner(String filePath, String searchQuery) throws FileNotFoundException
{
searchQuery = searchQuery.trim();
Scanner scanner = null;
try
{
scanner = new Scanner(new File(filePath));
while (scanner.hasNextLine())
{
String line = scanner.nextLine();
if (line.contains(searchQuery))
{
return line;
}
else
{
}
}
}
finally
{
try
{
if (scanner != null)
scanner.close();
}
catch (Exception e)
{
System.err.println("Exception while closing scanner " + e.toString());
}
}
return null;
}
public static String searchUsingBufferedReader(String filePath, String searchQuery) throws IOException
{
searchQuery = searchQuery.trim();
BufferedReader br = null;
try
{
br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));
String line;
while ((line = br.readLine()) != null)
{
if (line.contains(searchQuery))
{
return line;
}
else
{
}
}
}
finally
{
try
{
if (br != null)
br.close();
}
catch (Exception e)
{
System.err.println("Exception while closing bufferedreader " + e.toString());
}
}
return null;
}
}
The following Java 7+ solution has a main advantage.
private static void searchForName() throws IOException {
System.out.println("Please enter the name you would like to search for: ");
Scanner kb = new Scanner(System.in);
String name = kb.nextLine();
List<String> lines = Files.readAllLines(Paths.get("leaders.txt"));
for (String line : lines) {
if (line.contains(name)) {
System.out.println(line);
}
}
}
It's not shorter than the the code from this answer. The main point is, when we open a File
we have an open resource and we have to care about closing it. Otherwise it might pose a resource leak.
As of Java 7 the try-with-resources statement handles closing of resources. So opening a Scanner
backed by a file would look like that:
try (Scanner scanner = new Scanner("leaders.txt")) {
// using scanner
}
Using Files.readAllLines
we don't need to care about closing the file since this method (JavaDoc)
ensures that the file is closed when all bytes have been read or an I/O error, or other runtime exception, is thrown.
If the first occourance of a String
is needed only, the following Java 8+ code does the job in few lines:
protected static Optional<String> searchForName(String name) throws IOException {
try (Stream<String> lines = Files.lines(Paths.get("leaders.txt"))) {
return lines.filter(line -> line.contains(name)).findFirst();
}
}
It returns an Optional
indicating that there might be an empty result. We use it i.e. as follows:
private static void searchForName() throws IOException {
System.out.println("Please enter the name you would like to search for: ");
Scanner kb = new Scanner(System.in);
String name = kb.nextLine();
Optional<String> result = searchForName(name);
result.ifPresent(System.out::println);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With