【问题标题】:most efficient way to read huge file读取大文件的最有效方法
【发布时间】:2018-10-24 08:53:15
【问题描述】:

我不熟悉 JAVA NIO API。 我需要帮助才能获得常见面试问题的答案。 如果有一个包含 50 GB 数据的文件,我们可以从文件中读取数据并找到最常用的单词的最有效方法是什么。

BufferedReader.readLine() 是比扫描仪更好的 API。 除了创建多个线程使用 BufferedReader.readLine() API 批量读取此文件之外,我们还有其他方法吗?

【问题讨论】:

    标签: java nio


    【解决方案1】:

    参见 java.nio.channels.FileChannel javadocs:

    文件的一个区域可以直接映射到内存中;对于大文件,这通常比调用通常的读取或写入方法更有效。

    【讨论】:

      【解决方案2】:

      也许,使用下面的类,你可以获得最快的获取/读取输入的方式:

       import java.io.DataInputStream; 
       import java.io.FileInputStream; 
       import java.io.IOException; 
       import java.io.InputStreamReader; 
       import java.util.Scanner; 
       import java.util.StringTokenizer; 
      
      public class Main 
      { 
      static class Reader 
      { 
          final private int BUFFER_SIZE = 1 << 16; 
          private DataInputStream din; 
          private byte[] buffer; 
          private int bufferPointer, bytesRead; 
      
          public Reader() 
          { 
              din = new DataInputStream(System.in); 
              buffer = new byte[BUFFER_SIZE]; 
              bufferPointer = bytesRead = 0; 
          } 
      
          public Reader(String file_name) throws IOException 
          { 
              din = new DataInputStream(new FileInputStream(file_name)); 
              buffer = new byte[BUFFER_SIZE]; 
              bufferPointer = bytesRead = 0; 
          } 
      
          public String readLine() throws IOException 
          { 
              byte[] buf = new byte[64]; // line length 
              int cnt = 0, c; 
              while ((c = read()) != -1) 
              { 
                  if (c == '\n') 
                      break; 
                  buf[cnt++] = (byte) c; 
              } 
              return new String(buf, 0, cnt); 
          } 
      
          public int nextInt() throws IOException 
          { 
              int ret = 0; 
              byte c = read(); 
              while (c <= ' ') 
                  c = read(); 
              boolean neg = (c == '-'); 
              if (neg) 
                  c = read(); 
              do
              { 
                  ret = ret * 10 + c - '0'; 
              } while ((c = read()) >= '0' && c <= '9'); 
      
              if (neg) 
                  return -ret; 
              return ret; 
          } 
      
          public long nextLong() throws IOException 
          { 
              long ret = 0; 
              byte c = read(); 
              while (c <= ' ') 
                  c = read(); 
              boolean neg = (c == '-'); 
              if (neg) 
                  c = read(); 
              do { 
                  ret = ret * 10 + c - '0'; 
              } 
              while ((c = read()) >= '0' && c <= '9'); 
              if (neg) 
                  return -ret; 
              return ret; 
          } 
      
          public double nextDouble() throws IOException 
          { 
              double ret = 0, div = 1; 
              byte c = read(); 
              while (c <= ' ') 
                  c = read(); 
              boolean neg = (c == '-'); 
              if (neg) 
                  c = read(); 
      
              do { 
                  ret = ret * 10 + c - '0'; 
              } 
              while ((c = read()) >= '0' && c <= '9'); 
      
              if (c == '.') 
              { 
                  while ((c = read()) >= '0' && c <= '9') 
                  { 
                      ret += (c - '0') / (div *= 10); 
                  } 
              } 
      
              if (neg) 
                  return -ret; 
              return ret; 
          } 
      
          private void fillBuffer() throws IOException 
          { 
              bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE); 
              if (bytesRead == -1) 
                  buffer[0] = -1; 
          } 
      
          private byte read() throws IOException 
          { 
              if (bufferPointer == bytesRead) 
                  fillBuffer(); 
              return buffer[bufferPointer++]; 
          } 
      
          public void close() throws IOException 
          { 
              if (din == null) 
                  return; 
              din.close(); 
          } 
      } 
      
      public static void main(String[] args) throws IOException 
      { 
          Reader s=new Reader(); 
          int n = s.nextInt(); 
          int k = s.nextInt(); 
          int count=0; 
          while (n-- > 0) 
          { 
              int x = s.nextInt(); 
              if (x%k == 0) 
              count++; 
          } 
          System.out.println(count); 
      } 
      } 
      

      【讨论】:

      • 感谢分享上面的代码来清楚地解释场景。我几乎没有疑问。据我所知, din = new DataInputStream(new FileInputStream(file_name));上面的代码行是使用 API DataInputStream 来读取文件,但这也需要将数据读入 String 变量,这当然是昂贵的操作。还有其他方法可以改进吗?
      • 基本上,这里我们没有根据它们的类型读取任何类型的变量。我们只是在转换每个字母的 ASCII 值,无论它是 int、long、String 还是任何其他类型的变量。因此,不需要将变量显式存储为字符串!
      • 我还有 2 个顾虑 .a) 在每次读取操作中都会返回一个值 b) 在我的采访中,我被告知文件读取操作的成本很高,请您帮我解决以上几点。跨度>
      • stackoverflow.com/questions/44150483/… 我们可以看看这个来了解 FileChannel API ,stackoverflow.com/questions/44150483/…
      猜你喜欢
      • 1970-01-01
      • 2012-03-02
      • 1970-01-01
      • 1970-01-01
      • 2014-02-01
      • 2013-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多