读取和比较两个大文件

时间:2021-04-06 18:13:32

标签: java multithreading

我想阅读并比较两个文件的所有行,我解释说,我想为每个密码哈希器(来自我的 test.txt 文件)找到相同的哈希值(来自 password.txt 文件) )。问题是它应该足够快(我会说 10M 的 password.txt 和 1M 的最多 45 分钟 test.txt)。

我暂时有这个代码

private static void bufferedReaderFilePasswordFirst() {
    Path path = Paths.get("C:\\Users\\basil\\OneDrive - Haute Ecole Bruxelles Brabant (HE2B)\\Documents\\NetBeansProjects\\sha256\\passwords.txt");
    Path pathUser = Paths.get("C:\\Users\\basil\\OneDrive - Haute Ecole Bruxelles Brabant (HE2B)\\Documents\\NetBeansProjects\\sha256\\test.txt");
    int nbOfLine = 0;
    StringBuffer oui = new StringBuffer();

    try (BufferedReader readerPasswordGenerate = Files.newBufferedReader(path, Charset.forName("UTF-8"));) {

        String currentLineUser = null;
        String currentLinePassword = null;

        long start = System.nanoTime();

        while (((currentLinePassword = readerPasswordGenerate.readLine()) != null)) {
            BufferedReader readerPasswordUser = Files.newBufferedReader(pathUser, Charset.forName("UTF-8"));
            while ((currentLineUser = readerPasswordUser.readLine()) != null) {
                String firstWord = currentLinePassword.substring(0, currentLinePassword.indexOf(":"));
                if ((firstWord.charAt(0) == currentLineUser.charAt(0)) 
                    && (firstWord.charAt(14) == currentLineUser.charAt(14)) 
                    && (firstWord.charAt(31) == currentLineUser.charAt(31)) 
                    && (firstWord.charAt(63) == currentLineUser.charAt(63))
                ) {
                    if (firstWord.equals(currentLineUser)) {
                        String secondWord = currentLinePassword.substring(currentLinePassword.lastIndexOf(":") + 1);

                        oui.append(secondWord).append(System.lineSeparator());
                    }
                }
            }
            if (nbOfLine % 300 == 0) {
                System.out.println("We are at the " + nbOfLine);
                final long consumed = System.nanoTime() - start;
                final long totConsumed = TimeUnit.NANOSECONDS.toMillis(consumed);
                final double tot = (double) totConsumed;
                System.out.printf("Not done. Took %s seconds", (tot / 1000));
                System.out.println(oui + " oui");
            }
            nbOfLine++;
        }
        System.out.println(oui);
        final long consumed = System.nanoTime() - start;
        final long totConsumed = TimeUnit.NANOSECONDS.toMillis(consumed);
        final double tot = (double) totConsumed;
        System.out.printf("Done. Took %s seconds", (tot / 1000));
    } catch (IOException ex) {
        ex.printStackTrace(); //handle an exception here
    }
}

在这段代码中,我只是比较 test.txt 中的每个元素,如果密码哈希中的相应元素相同。

password.txt 包含所有元素:hash:passwordtest.txt 仅包含:hash

谢谢

1 个答案:

答案 0 :(得分:4)

<块引用>

在这段代码中,我只是比较我的 test.txt 中的每个元素,如果密码哈希中的相应元素相同。

如果您熟悉 Big-O 表示法,您可能会意识到这意味着您的算法在 O(n^2) 时间内运行。在您的特定情况下,对于 test.txt 中的 1,000,000 行中的每一行,您将进行 10,000,000 次比较,总共进行 10,000,000,000,000 次比较。为了实现在 45 分钟内运行它的目标,您需要每秒进行 37 亿次十亿 次比较。相比之下,我的笔记本电脑中的 i7 的最高运行频率为 3.9GHz(每秒十亿个周期),执行这些比较之一所需的时间远不止一个 CPU 周期。

首先将 password.txt 读入 HashMap(10,000,000 次操作),可以将时间复杂度降低到 O(n)。从那里开始,test.txt 中的任何单个检查只需要一次操作(总共 1,000,000 次),从而导致总共 11,000,000 次操作。这意味着您只需每秒执行约 4,000 次操作(减少 99.99989%)即可在 45 分钟内完成,这更加可行。

这里有一些伪代码来说明它的样子:

// I like Scanner over BufferedReader for reading files. Use whatever you like.
Scanner readPassword = new Scanner(new File("password.txt"));

// Load all password/hash pairings from password.txt into a HashMap for quick lookups
HashMap<String, List> passwords = new HashMap<>();
while (readPassword.hasNextLine()) {
  String line = readPassword.nextLine();
  String[] lineParts = line.split(":");
  String hash = lineParts[0];  
  String password = lineParts[1];
  
  // If we haven't seen the hash before, create a new list to store its associated passwords
  if (passwords.get(hash) == null) {
    passwords.put(hash, new LinkedList<>());
  }

  // Add the password to the list of all passwords that have this hash
  passwords.get(hash).add(password);  
}

// Perform all the lookups from test.txt
Scanner readTest = new Scanner(new File("test.txt"));
while (readTest.hasNextLine()) {
  String testHash = readTest.nextLine();
  List matchingPasswords = passwords.get(testHash);
  // Now do whatever you want with the list of associated passwords...
}

附注:

  • 查看您的代码,您似乎有一些我没有在此代码片段中考虑的额外要求(例如时间安排)。我相信您可以弄清楚如何整合这些额外的要求。
  • 这里的一些学术界人士可能会对我的 Big-O 描述/分析的某些部分提出异议。如果您感兴趣,我相信他们对这篇文章的评论会更详细地阐述该主题。
相关问题