【问题标题】:Search a file for a String and return that String if found在文件中搜索字符串,如果找到则返回该字符串
【发布时间】:2013-03-22 18:44:37
【问题描述】:

如何在 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”文件包含一个名称列表。

【问题讨论】:

  • 您需要遍历文件中的每一行(当它有任何行时)并在每一行中检查您的字符串。
  • 您在寻找这一行的一些特殊数据吗?您可以将文件读取为单个字符串(如果它不是太大) - 例如,使用 apache common fileutils。

标签: java io java.util.scanner


【解决方案1】:

您可以创建一个单独的Scanner 来逐行读取文件并以这种方式进行匹配...

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

【讨论】:

  • 你为什么要把这些“最终”?我知道 final 将使它们在未来保持不变,但我想知道这是否有必要或只是我应该习惯做的事情。
【解决方案2】:

扫描仪太慢了。运行下面的代码,看看有什么不同。在 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;
    }
}

【讨论】:

    【解决方案3】:

    以下 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 statement 处理资源的关闭。所以打开一个由文件支持的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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 2011-09-28
      • 2010-12-24
      • 2012-03-05
      相关资源
      最近更新 更多