Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中获取文本文件的随机行?_Java_File_Random - Fatal编程技术网

如何在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)
    结果=直线;
    }
    返回结果;
    }
    }
    
    如果只需要一行,那么读取整个文件似乎有点过分。以下措施应更有效:

  • 用于查找文件中的随机字节位置
  • 向左和向右搜索下一行终止符。让我来划清他们之间的界线
  • 概率(最小线长度/L.LENGTH)返回L。否则,从步骤1重新开始
  • 这是一个变体

    行长度包括行终止符字符,因此最小行长度>=1。(如果您知道线长度的更紧界限,那就更好了)


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

    查看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()
    。这应该是最好的答案。我已经为您准备好了。