Java读写大文本文件(2GB以上)

来源:互联网 发布:淘宝排版布局 编辑:程序博客网 时间:2024/05/16 11:03

Java读写大文本文件(2GB以上)

如下的程序,将一个行数为fileLines的文本文件平均分为splitNum个小文本文件,其中换行符'r'是linux上的,windows的java换行符是'\r\n':

复制代码
package kddcup2012.task2.FileSystem;    import java.io.BufferedInputStream;  import java.io.BufferedReader;  import java.io.File;  import java.io.FileInputStream;  import java.io.FileWriter;  import java.io.IOException;  import java.io.InputStreamReader;    public class FileSplit  {         public static void main(String[] args) throws IOException      {          long timer = System.currentTimeMillis();          int bufferSize = 20 * 1024 * 1024;//设读取文件的缓存为20MB                     //建立缓冲文本输入流           File file = new File("/media/Data/毕业设计/kdd cup/数据/userid_profile.txt");          FileInputStream fileInputStream = new FileInputStream(file);          BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);          InputStreamReader inputStreamReader = new InputStreamReader(bufferedInputStream);          BufferedReader input = new BufferedReader(inputStreamReader, bufferSize);                    int splitNum = 112-1;//要分割的块数减一           int fileLines = 23669283;//输入文件的行数           long perSplitLines = fileLines / splitNum;//每个块的行数           for (int i = 0; i <= splitNum; ++i)          {              //分割               //每个块建立一个输出               FileWriter output = new FileWriter("/home/haoqiong/part" + i + ".txt");              String line = null;              //逐行读取,逐行输出               for (long lineCounter = 0; lineCounter < perSplitLines && (line = input.readLine()) != null; ++lineCounter)              {                  output.append(line + "\r");              }              output.flush();              output.close();              output = null;          }          input.close();          timer = System.currentTimeMillis() - timer;          System.out.println("处理时间:" + timer);      }  }  
复制代码

 

以上程序处理大文本文件只需要30MB左右的内存空间(这和所设的读取缓冲大小有关),但是速度不是很快,在磁盘没有其他程序占用的情况下,将200MB文件分割为112份需要20秒(机器配置:Centrino2 P7450 CPU,2GB DDR3内存,Ubuntu 11.10系统,硬盘最大读写速度大约60MB/S)。

另外,对于几百兆到2GB大小的文件,使用内存映射文件的话,速度会块一些,但是内存映射由于映射的文件长度不能超过java中int类型的最大值,所以只能处理2GB以下的文件。

 

java 读取一个巨大的文本文件既能保证内存不溢出又能保证性能  
 
复制代码
package helloword.helloword;import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.RandomAccessFile;import java.nio.ByteBuffer;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;public class ReadBig {    public static String fff = "C:\\mq\\read\\from.xml";    public static void main1(String[] args) throws Exception {        final int BUFFER_SIZE = 0x300000;// 缓冲区大小为3M        File f = new File(fff);        MappedByteBuffer inputBuffer = new RandomAccessFile(f, "r").getChannel().map(FileChannel.MapMode.READ_ONLY,                f.length() / 2, f.length() / 2);        byte[] dst = new byte[BUFFER_SIZE];// 每次读出3M的内容        long start = System.currentTimeMillis();        for (int offset = 0; offset < inputBuffer.capacity(); offset += BUFFER_SIZE) {            if (inputBuffer.capacity() - offset >= BUFFER_SIZE) {                for (int i = 0; i < BUFFER_SIZE; i++)                    dst[i] = inputBuffer.get(offset + i);            } else {                for (int i = 0; i < inputBuffer.capacity() - offset; i++)                    dst[i] = inputBuffer.get(offset + i);            }            int length = (inputBuffer.capacity() % BUFFER_SIZE == 0) ? BUFFER_SIZE                    : inputBuffer.capacity() % BUFFER_SIZE;            System.out.println(new String(dst, 0, length));// new            // String(dst,0,length)这样可以取出缓存保存的字符串,可以对其进行操作        }        long end = System.currentTimeMillis();        System.out.println("读取文件文件一半内容花费:" + (end - start) + "毫秒");    }    public static void main2(String[] args) throws Exception {        int bufSize = 1024;        byte[] bs = new byte[bufSize];        ByteBuffer byteBuf = ByteBuffer.allocate(1024);        FileChannel channel = new RandomAccessFile(fff, "r").getChannel();        while (channel.read(byteBuf) != -1) {            int size = byteBuf.position();            byteBuf.rewind();            byteBuf.get(bs); // 把文件当字符串处理,直接打印做为一个例子。            System.out.print(new String(bs, 0, size));            byteBuf.clear();        }    }    public static void main3(String[] args) throws Exception {        BufferedReader br = new BufferedReader(new FileReader(fff));        String line = null;        while ((line = br.readLine()) != null) {            System.out.println(line);        }    }    public static void main(String[] args) throws Exception {        int bufSize = 1024;        byte[] bs = new byte[bufSize];        ByteBuffer byteBuf = ByteBuffer.allocate(1024);        FileChannel channel = new RandomAccessFile("d:\\filename", "r").getChannel();        while (channel.read(byteBuf) != -1) {            int size = byteBuf.position();            byteBuf.rewind();            byteBuf.get(bs);            // 把文件当字符串处理,直接打印做为一个例子。            System.out.print(new String(bs, 0, size));            byteBuf.clear();        }    }}
复制代码

 

java 读取大容量文件,内存溢出?怎么按几行读取,读取多次。 最佳答案
复制代码
package helloword.helloword;import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.RandomAccessFile;import java.util.Scanner;public class TestPrint {    public static void main(String[] args) throws IOException {        String path = "你要读的文件的路径";        RandomAccessFile br = new RandomAccessFile(path, "rw");// 这里rw看你了。要是之都就只写r        String str = null, app = null;        int i = 0;        while ((str = br.readLine()) != null) {            i++;            app = app + str;            if (i >= 100) {// 假设读取100行                i = 0;                // 这里你先对这100行操作,然后继续读                app = null;            }        }        br.close();    }    // 当逐行读写大于2G的文本文件时推荐使用以下代码    void largeFileIO(String inputFile, String outputFile) {        try {            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(inputFile)));            BufferedReader in = new BufferedReader(new InputStreamReader(bis, "utf-8"), 10 * 1024 * 1024);// 10M缓存            FileWriter fw = new FileWriter(outputFile);            while (in.ready()) {                String line = in.readLine();                fw.append(line + " ");            }            in.close();            fw.flush();            fw.close();        } catch (IOException ex) {            ex.printStackTrace();        }    }}
复制代码
jdk本身就支持超大文件的读写。
 
网上的文章基本分为两大类:
一类是使用BufferedReader类读写超大文件;
另一类是使用RandomAccessFile类读取,经过比较,最后使用了前一种方式进行超大文件的读取,下面是相关代码,其实很简单
-------------------------------------------------------------------
复制代码
File file = new File(filepath);   BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));    BufferedReader reader = new BufferedReader(new InputStreamReader(fis,"utf-8"),5*1024*1024);// 用5M的缓冲读取文本文件    String line = "";while((line = reader.readLine()) != null){   //TODO: write your business}
复制代码
---------------------------------------------------------------------
 
注意代码,在实例化BufferedReader时,增加一个分配缓存的参数即可