如何在Java中获取文本文件的随机行?
假设有一个文件太大,无法放入内存。我怎样才能从中得到一条随机线?谢谢 更新:如何在Java中获取文本文件的随机行?,java,file,random,Java,File,Random,假设有一个文件太大,无法放入内存。我怎样才能从中得到一条随机线?谢谢 更新: 我想计算使每一行相等的概率。使用BufferedReader并逐行读取。使用java.util.Random对象随机停止;) 要么你 读取文件两次—一次计算行数,第二次提取随机行,或 使用 这里有一个解决方案。看一下choose()方法,它做的是真正的事情(main()方法反复练习choose(),以表明分布确实相当均匀) 想法很简单:当你阅读第一行时,它有100%的机会被选为结果。当你阅读第二行时,有50%的几率替换
我想计算使每一行相等的概率。使用BufferedReader并逐行读取。使用java.util.Random对象随机停止;) 要么你
这里有一个解决方案。看一下choose()方法,它做的是真正的事情(main()方法反复练习choose(),以表明分布确实相当均匀) 想法很简单:当你阅读第一行时,它有100%的机会被选为结果。当你阅读第二行时,有50%的几率替换第一行。当你阅读第三行时,它有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;
}
}
import java.io.*;
导入java.util.*;
公共B级{
公共静态void main(字符串[]args)引发FileNotFoundException{
Map Map=newhashmap();
对于(int i=0;i<1000;++i)
{
字符串s=choose(新文件(“g:/temp/a.txt”);
如果(!map.containsKey)
地图放置(s,0);
map.put(s,map.get(s)+1;
}
系统输出打印项次(map);
}
公共静态字符串choose(文件f)引发FileNotFoundException
{
字符串结果=null;
Random rand=新的Random();
int n=0;
对于(扫描仪sc=新扫描仪(f);sc.hasNext();)
{
++n;
字符串行=sc.nextLine();
如果(随机数n)=0)
结果=直线;
}
返回结果;
}
}
如果只需要一行,那么读取整个文件似乎有点过分。以下措施应更有效:
值得注意的是,该算法的运行时间不取决于文件大小,只取决于行长度,即它的伸缩性比读取整个文件要好得多。查看Itay的答案,它看起来好像在对一行代码采样后,它读取了文件一千次,然而,真正的储层取样应仅通过“磁带”一次。我设计了一些代码,根据web上的各种描述,使用真实的水库采样对代码进行一次检查
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
public class reservoirSampling {
public static void main(String[] args) throws FileNotFoundException, IOException{
Sampler mySampler = new Sampler();
List<String> myList = mySampler.sampler(10);
for(int index = 0;index<myList.size();index++){
System.out.println(myList.get(index));
}
}
}
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
public class Sampler {
public Sampler(){}
public List<String> sampler (int reservoirSize) throws FileNotFoundException, IOException
{
String currentLine=null;
//reservoirList is where our selected lines stored
List <String> reservoirList= new ArrayList<String>(reservoirSize);
// we will use this counter to count the current line number while iterating
int count=0;
Random ra = new Random();
int randomNumber = 0;
Scanner sc = new Scanner(new File("Open_source.html")).useDelimiter("\n");
while (sc.hasNext())
{
currentLine = sc.next();
count ++;
if (count<=reservoirSize)
{
reservoirList.add(currentLine);
}
else if ((randomNumber = (int) ra.nextInt(count))<reservoirSize)
{
reservoirList.set(randomNumber, currentLine);
}
}
return reservoirList;
}
}
import java.io.FileNotFoundException;
导入java.io.IOException;
导入java.util.List;
公共类库采样{
公共静态void main(字符串[]args)抛出FileNotFoundException、IOException{
采样器mySampler=新采样器();
List myList=mySampler.sampler(10);
对于(int index=0;index使用RandomAccessFile:
构建一个随机访问文件,文件
通过调用file.length()
生成一个介于0和filelen之间的随机数,pos
调用file.seek(pos)搜索到随机位置
调用file.readLine()以到达当前行的末尾
再次调用file.readLine()读取下一行
使用这种方法,我从布朗语料库中随机抽取了几行样本,可以在几秒钟内轻松地从随机选取的文件中检索到1000个随机样本。如果我试图通过逐行阅读每个文件来进行同样的操作,我将花费更长的时间
同样的原则也可用于从列表中选择随机元素。如果生成一个介于0和列表长度之间的随机数,则可以直接索引到列表中,而不是通读列表并在随机位置停止。从java文件中读取随机行:
公共字符串GetRandomLineFromOffile(字符串filePathWithFileName)引发异常{
File file = new File(filePathWithFileName);
final RandomAccessFile f = new RandomAccessFile(file, "r");
final long randomLocation = (long) (Math.random() * f.length());
f.seek(randomLocation);
f.readLine();
String randomLine = f.readLine();
f.close();
return randomLine;
}
当我想停止时,我如何确保文件没有结束?例如,我如何知道一个文件的行数?另外,我希望每一行的概率相等。@Dinuk,因此如果文件比其他文件小,我会太频繁地得到最后一行,如果文件大-我会太少,那么你必须读两次文件或我如果所有行的长度都相等,您可以根据水库采样的文件sizeAn实现计算行数。从未听说过水库采样。如果我的文件是MBs,会怎么样?是否存在性能问题?如果是,是否有其他方法可以避免完整的文件扫描?我是否正确,并假设这是针对固定的n=1,而e n是“样本数”?是否有一种方法可以让choose一次选择多个?就目前情况而言,您可以多次“在磁带上循环”,或者至少尝试这样做似乎效率低下。太好了!如果文件将重复采样,请使用单次过程收集偏移量的列表
,然后可以通过Coll随机化sections.shuffle()
。这应该是最好的答案。我已经为您准备好了。