Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.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/9/security/4.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_Out Of Memory - Fatal编程技术网

在Java中,有没有一种方法可以将太大而无法放入内存的文件随机化?

在Java中,有没有一种方法可以将太大而无法放入内存的文件随机化?,java,out-of-memory,Java,Out Of Memory,我想做的是洗牌行(从CSV读取),然后打印出第一个随机10000行到一个CSV,其余的到一个单独的CSV。使用较小的文件,我可以执行以下操作 java.util.Collections.shuffle(...) for (int i=0; i < 10000; i++) printcsv(...) for (int i=10000; i < data.length; i++) printcsv(...) java.util.Collections.shuffle(…) 对于(int

我想做的是洗牌行(从CSV读取),然后打印出第一个随机10000行到一个CSV,其余的到一个单独的CSV。使用较小的文件,我可以执行以下操作

java.util.Collections.shuffle(...)
for (int i=0; i < 10000; i++) printcsv(...)
for (int i=10000; i < data.length; i++) printcsv(...)
java.util.Collections.shuffle(…)
对于(int i=0;i<10000;i++)printcsv(…)
对于(int i=10000;i
但是,对于非常大的文件,我现在从内存错误中获取
信息

您可以:

  • 使用更多内存或内存

  • 洗牌不是实际的CSV行,而是一组行号,然后逐行读取输入文件(当然是缓冲的),并将该行写入所需的输出文件之一


    • 使用某种索引方案。对CSV文件进行一次分析,以获得行数(不要在内存中保留任何内容,只需对其进行分析),然后从该范围中随机选择10000个数字(确保避免重复,例如使用
      或更复杂的设置)。然后第二次解析CSV,再次为行保留一个计数器。如果行号对应于随机选择的数字之一,则将其输出到一个CSV文件。将编号不匹配的行输出到另一个文件

    • 首先,通过读取输入文件的内容(但不将其存储在内存中),计算输入文件中的行数。调用行数
      N
    • 编号
      1
      N
      ,大小为10000
    • 从头开始读取输入文件。对于每一行,如果行号在步骤2中绘制的样本中,则将该行写入
      file1
      ;否则,将其写入
      文件2

    • 步骤2可以在执行步骤1时通过使用来完成。

      以下是一种可能的算法:

    • 设MAX_line为可管理文件中的最大行数
    • 从输入文件中读取MAX_行,使用原始算法将其随机化,并将其写入临时文件
    • 重复2。直到输入文件中没有任何行
    • 设N是介于0和您编写的临时文件数之间的随机数;从第N个临时文件中读取下一行
    • 重复4次。直到您读取所有文件中的所有行;前10000次将每行写入第一个输出文件,将所有其他行写入另一个文件

    • 如果您知道文件中的行数,并且将整行随机化,则可以按行号随机化,然后读取选定的行。只需通过类选择一条随机线并存储随机数列表,这样就不会重复选择一条

      BufferedReader reader = new BufferedReader(new FileReader(new File("file.cvs")));
      BufferedWriter chosen = new BufferedWriter(new FileWriter(new File("chosen.cvs")));
      BufferedWriter notChosen = new BufferedWriter(new FileWriter(new File("notChosen.cvs")));
      
      int numChosenRows = 10000;
      long numLines = 1000000000; 
      
      Set<Long> chosenRows = new HashSet<Long>(numChosenRows+1, 1);
      for(int i = 0; i < numChosenRows; i++) {
          while(!chosenRows.add(nextLong(numLines))) {
              // add returns false if the value already exists in the Set
          }
      }
      
      String line;
      for(long lineNo = 0; (line = reader.readLine()) != null; lineNo++){
          if(chosenRows.contains(lineNo)){
              // Do nothing for the moment
          } else {
              notChosen.write(line);
          }
      }
      
      // Randomise the set of chosen rows
      
      // Use RandomAccessFile to write the rows in that order
      
      BufferedReader=new BufferedReader(new FileReader(新文件(“File.cvs”));
      BufferedWriter selected=new BufferedWriter(new FileWriter(新文件(“selected.cvs”));
      BufferedWriter NotSelected=新的BufferedWriter(新的FileWriter(新文件(“notSelected.cvs”));
      int numChosenRows=10000;
      长整数=100000000;
      Set chosenRows=newhashset(numChosenRows+1,1);
      for(int i=0;i
      有关nextLong方法的信息,请参见,该方法将生成一个按特定大小进行长比例缩放的随机值


      编辑:与大多数人一样,我忽略了以随机顺序书写随机选择的行的要求。我想这会有帮助的。只需随机化列表中选定的行,并按顺序访问它们。至于未关闭的代码,我编辑了上面的代码以忽略所选择的代码

      您可以内存映射文件并查找所有换行符,将它们存储在
      int
      long
      数组中。创建一个
      int
      索引数组,并将其洗牌。每行大约使用8-32字节。如果内存不足,您也可以为这些阵列使用内存映射文件。

      您可以对文件进行内存映射并读取部分文件。听起来您需要更多内存。:-)@托马斯:我不认为这是问题所在。海报需要将所有条目保存在内存中,如果他想在将它们写入文件之前将它们随机化。我假设您有很多,远远超过10000行,否则您不应该出现内存不足错误。这些行的长度究竟是多少?以某种压缩格式将它们保存在内存中可能会大大减少内存占用。当然,它不会无限期地扩展。这仍然会保持原来的顺序。@Nicolamasatti:哇,你说得对。忘了那个要求。在这种情况下,我认为他最好使用一些简单的数据库表来暂时保存数据。也许JavaDB可以让事情保持简单……这种方法可以保持原始的顺序。这一点很好。我以为任务只是从所有行中随机抽取一个样本。但是,如果您的假设是正确的,则可能会对输出文件进行后续的内存洗牌,因为它比原始文件小得多。有两个输出文件,如果他是正确的,那么如果他可以在内存中处理的行数远小于总行数,那么第二个文件也会有同样的问题。您正在保留原始顺序。如果将MAX_lines>因素考虑进去,我会看到步骤4中的问题在下一个N中读取同一文件的机会非常小。(如果最大线=总线,概率为100%)p=最大线/总线。从同一文件中读取下一行的机会是p。否则,您必须读取一个新文件,并平均跳过一半行。((1-p)*最大值