ユーザーが入力した文字列をtxtファイルで検索し、その文字列をコンソールに返すにはどうすればよいですか。以下で機能しないコードをいくつか作成しましたが、それが私のポイントを説明できることを願っています...
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));
}
}
「leaders.txt」ファイルには、名前のリストが含まれています。
別のScanner
を作成して、ファイルを1行ずつ読み取り、その方法で照合を行うことができます...
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;
}
}
ファイルの読み取りにScanner
またはBufferedReader
のどちらを使用する必要があるかについては、これを読んでください answer 。
スキャナーが遅すぎます。次のコードを実行して、違いを確認してください。 750 MBのファイルで検索され、BufferedReaderは平均してScannerよりも10倍高速です。
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;
}
}
次のJava 7+ソリューションには主な利点があります。
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);
}
}
}
これからのコードよりも短くはありません answer 。重要な点は、File
を開くと、開いているリソースがあり、それを閉じることに注意する必要があるということです。そうしないと、リソースリークが発生する可能性があります。
Java 7の時点で try-with-resourcesステートメント はリソースのクローズを処理します。したがって、ファイルに裏打ちされたScanner
を開くと次のようになります。
try (Scanner scanner = new Scanner("leaders.txt")) {
// using scanner
}
Files.readAllLines
を使用すると、このメソッド( JavaDoc )なので、ファイルを閉じる必要はありません。
すべてのバイトが読み取られたとき、I/Oエラー、またはその他のランタイム例外がスローされたときにファイルが閉じられるようにします。
String
の最初の出現のみが必要な場合、次のJava 8+コードが数行で機能します。
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();
}
}
空の結果がある可能性があることを示すOptional
を返します。私たちはそれを次のように使用します:
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);
}