如何在Java中获取文本文件的随机行?

2022-09-01 15:03:40

假设有一个文件太大而无法放入内存。如何从中获取随机行?谢谢。

更新:我想要让每行相等的概率。


答案 1

如果您只想阅读整个文件,则只想要一行似乎有点过分。以下操作应该更有效:

  1. 使用 RandomAccessFile 查找文件中的随机字节位置。
  2. 向左和向右搜索下一行终止符。让L它们之间的线。
  3. 概率(MIN_LINE_LENGTH / L.length)返回L.否则,从步骤1重新开始。

这是剔除采样的一种变体。

行长度包括行终止符字符,因此MIN_LINE_LENGTH >= 1。(如果你知道一个更严格的线长度界限,那就更好了)。

值得注意的是,该算法的运行时不依赖于文件大小,仅取决于行长度,即它比读取整个文件要好得多。


答案 2

这里有一个解决方案。看看做真实事情的select()方法(main()方法反复练习opt(),以表明分布确实相当均匀)。

这个想法很简单:当你阅读第一行时,它有100%的机会被选为结果。当您阅读第二行时,它有50%的机会替换第一行作为结果。当你阅读第3行时,它有33%的机会成为结果。第四行有25%,依此类推。

import java.io.*;
import java.util.*;

public class B {

  public static void main(String[] args) throws FileNotFoundException {
     Map<String,Integer> map = new HashMap<String,Integer>();
     for(int i = 0; i < 1000; ++i)
     {
        String s = choose(new File("g:/temp/a.txt"));
        if(!map.containsKey(s))
           map.put(s, 0);
        map.put(s, map.get(s) + 1);
     }

     System.out.println(map);
  }

  public static String choose(File f) throws FileNotFoundException
  {
     String result = null;
     Random rand = new Random();
     int n = 0;
     for(Scanner sc = new Scanner(f); sc.hasNext(); )
     {
        ++n;
        String line = sc.nextLine();
        if(rand.nextInt(n) == 0)
           result = line;         
     }

     return result;      
  }
}