Comment pouvez-vous rechercher dans un fichier txt une chaîne que l'utilisateur a saisie, puis renvoyer cette chaîne à la console. J'ai écrit du code qui ne fonctionne pas ci-dessous, mais j'espère qu'il pourra illustrer mon propos ...
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));
}
}
Le fichier "leaders.txt" contient une liste de noms.
Vous pouvez créer une Scanner
distincte pour lire le fichier ligne par ligne et faire une correspondance de cette façon ...
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;
}
}
Pour savoir si vous devez utiliser une Scanner
ou une BufferedReader
pour lire le fichier, lisez ceci answer .
Le scanner est beaucoup trop lent. Exécutez le code suivant et voyez les différences. Recherche dans un fichier de 750 Mo et BufferedReader est 10 fois plus rapide que Scanner en moyenne.
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;
}
}
La solution Java 7+ suivante présente un avantage principal.
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);
}
}
}
Ce n'est pas plus court que le code de cette answer . Le point essentiel est que, lorsque nous ouvrons une File
, nous avons une ressource ouverte et nous devons nous préoccuper de la fermer. Sinon, cela pourrait causer une fuite de ressources.
A partir de Java 7, l'instruction try-with-resources gère la fermeture des ressources. Donc, ouvrir une Scanner
sauvegardée par un fichier ressemblerait à ça:
try (Scanner scanner = new Scanner("leaders.txt")) {
// using scanner
}
En utilisant Files.readAllLines
nous n'avons pas besoin de nous soucier de fermer le fichier puisque cette méthode ( JavaDoc )
garantit que le fichier est fermé lorsque tous les octets ont été lus ou qu'une erreur d'E/S , ou une autre exception d'exécution, est levée.
Si la première occurrence d'une String
n'est requise que, le code Java 8+ suivant fait le travail en quelques lignes:
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();
}
}
Il retourne une Optional
indiquant qu'il peut y avoir un résultat vide. Nous l'utilisons comme suit:
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);
}