java怎么做大文件包的读写?Java如何读取大文件?

在开发程序的过程中,经常会需要读写大文件,为了节省开发人员的时间,其实我们哟一个大文件包的读写就可以了,那java怎么做大文件包的读写?下面来我们就来给大家讲解一下这方面的内容。

代码如下:

package cn.gzu.readfile;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ReadWriteNio
{
    public static void main(String args[]) throws Exception
    {
        int bufSize = 100;
        File fin = new File("E:\\jiahui\\2014-09-01.dat");
        File fout = new File("E:\\jiahui\\res.txt");
        System.out.print("开始读取并重写文件,请等待...");
        FileChannel fcin = new RandomAccessFile(fin, "r")
            .getChannel();
        ByteBuffer rBuffer = ByteBuffer.allocate(bufSize);
        FileChannel fcout = new RandomAccessFile(fout, "rws")
            .getChannel();
        ByteBuffer wBuffer = ByteBuffer.allocateDirect(bufSize);
        readFileByLine(bufSize, fcin, rBuffer, fcout, wBuffer);
        System.out.print("读写完成!");
    }
    /*读文件同时写文件*/
    public static void readFileByLine(int bufSize, FileChannel fcin, ByteBuffer rBuffer
        , FileChannel fcout, ByteBuffer wBuffer)
    {
        String enterStr = "\n";
        try
        {
            byte[] bs = new byte[bufSize];
            int size = 0;
            StringBuffer strBuf = new StringBuffer("");
            while ((size = fcin.read(rBuffer)) != -1)
            {
                // while(fcin.read(rBuffer) != -1){
                if (size > 1 * 1024)
                {
                    break;
                }
                int rSize = rBuffer.position();
                rBuffer.rewind();
                rBuffer.get(bs);
                rBuffer.clear();
                String tempString = new String(bs, 0, rSize, "UTF-8");
                // System.out.println(size+": "+tempString);
                int fromIndex = 0;
                int endIndex = 0;
                while ((endIndex = tempString.indexOf(enterStr, fromIndex)) != -1)
                {
                    String line = tempString.substring(fromIndex, endIndex);
                    line = new String(strBuf.toString() + line + "\n");
                    System.out.println(size + ": " + line);
                    //System.out.print("");
                    //write to anthone file
                    writeFileByLine(fcout, wBuffer, line);
                    strBuf.delete(0, strBuf.length());
                    fromIndex = endIndex + 1;
                }
                if (rSize > tempString.length())
                {
                    strBuf.append(tempString.substring(fromIndex, tempString.length()));
                }
                else
                {
                    strBuf.append(tempString.substring(fromIndex, rSize));
                }
            }
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /*写文件*/
    public static void writeFileByLine(FileChannel fcout, ByteBuffer wBuffer, String line)
    {
        try
        {
            //write on file head
            //fcout.write(wBuffer.wrap(line.getBytes()));
            //wirte append file on foot
            fcout.write(wBuffer.wrap(line.getBytes()), fcout.size());
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Java如何读取大文件?

1、在内存中读取

读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法:

Files.readLines(new File(path), Charsets.UTF_8); FileUtils.readLines(new 
File(path));

这种方法带来的问题是文件的所有行都被存放在内存中,当文件足够大时很快就会导致程序抛出OutOfMemoryError 异常。

例如:读取一个大约1G的文件:

@Test
public void givenUsingGuava_whenIteratingAFile_thenWorks() throws IOException 
{ String path = ... Files.readLines(new File(path), Charsets.UTF_8); }

这种方式开始时只占用很少的内存:(大约消耗了0Mb内存)

[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 128 Mb 
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 116 Mb

然而,当文件全部读到内存中后,我们最后可以看到(大约消耗了2GB内存):

[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 2666 Mb 
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 490 Mb

这意味这一过程大约耗费了2.1GB的内存——原因很简单:现在文件的所有行都被存储在内存中。

把文件所有的内容都放在内存中很快会耗尽可用内存——不论实际可用内存有多大,这点是显而易见的。

此外,我们通常不需要把文件的所有行一次性地放入内存中——相反,我们只需要遍历文件的每一行,然后做相应的处理,处理完之后把它扔掉。所以,这正是我们将要做的——通过行迭代,而不是把所有行都放在内存中。

2、文件流

现在让我们看下这种解决方案——我们将使用java.util.Scanner类扫描文件的内容,一行一行连续地读取:

FileInputStream inputStream = null;
Scanner sc = null;
try
{
    inputStream = new FileInputStream(path);
    sc = new Scanner(inputStream, "UTF-8");
    while (sc.hasNextLine())
    {
        String line = sc.nextLine(); // System.out.println(line); } // note that Scanner suppresses exceptions if (sc.ioException() != null) { throw sc.ioException(); } } finally { if (inputStream != null) { inputStream.close(); } if (sc != null) { sc.close(); } }

这种方案将会遍历文件中的所有行——允许对每一行进行处理,而不保持对它的引用。总之没有把它们存放在内存中:(大约消耗了150MB内存)

[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 763 Mb 
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 605 Mb

3、Apache Commons IO流

同样也可以使用Commons IO库实现,利用该库提供的自定义LineIterator:

LineIterator it = FileUtils.lineIterator(theFile, "UTF-8");
try
{
    while (it.hasNext())
    {
        String line = it.nextLine();
        // do something with line } } finally { LineIterator.closeQuietly(it); }

由于整个文件不是全部存放在内存中,这也就导致相当保守的内存消耗:(大约消耗了150MB内存)

[main] INFO o.b.java.CoreJavaIoIntegrationTest - Total Memory: 752 Mb [main] 
INFO o.b.java.CoreJavaIoIntegrationTest - Free Memory: 564 Mb

Java读写大文件可以用以上几种方法去实现,对于开发人员的开发还是很有帮助的,希望能够帮助到大家!最后大家如果想要了解更多java实例知识,敬请关注奇Q工具网。

推荐阅读:

java开发项目经理面试题有哪些?实用的面试题

fastjson有哪些漏洞?fastjson使用的相关问题

elasticsearch怎么用?elasticsearch怎么理解?