Java nio按行处理文件(兼容Linux与Windows)

代码没有做复杂文件的测试,如果有问题,望请见谅并留言

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;

/**
 * Description:
 * Created by IntelliJ IDEA.
 * Created by on
 * User: 
 * Date: 
 * Time: 
 */
public class HandleFileWithLine {

    private static final int BUFFER_LENGTH = 1024;                      //缓冲区数组长度
    private static final byte CR = 13;                                  //回车符
    private static final byte LF = 10;                                  //换行符
    private static final Charset CHARSET = Charset.forName("UTF-8");    //编码字符集

    public void handleFile(File handleFile) throws IOException {
        FileChannel inc = new RandomAccessFile(handleFile, "r").getChannel();

        ByteBuffer inBuffer = ByteBuffer.allocate(BUFFER_LENGTH);

        //实际中每行的开始位置在数组中的下标
        int lineStartPosition;
        //由于是按固定字节读取,在一次读取中,第一行和最后一行经常是不完整的行,因此定义此变量来存储上次的最后一行和这次的第一行的内容
        byte[] tempByte = new byte[0];
        while (inc.read(inBuffer) != -1) {
            lineStartPosition = 0;
            inBuffer.flip();

            //按行处理文件的方法
            tempByte = readLine(inBuffer, lineStartPosition, tempByte);
            inBuffer.clear();
        }

        //处理最后一行数据
        handleLine(tempByte);

        if (inc.isOpen()) inc.close();
    }

    /**
     * 按行处理文件的方法
     * @param inBuffer 每次获取的缓冲数据
     * @param lineStartPosition 实际中每行的开始位置在数组中的下标
     * @param tempByte 由于是按固定字节读取,在一次读取中,第一行和最后一行经常是不完整的行,因此定义此变量来存储上次的最后一行和这次的第一行的内容
     * @return
     */
    private byte[] readLine(ByteBuffer inBuffer, int lineStartPosition, byte[] tempByte) {
        //上一次剩余的不足一行的数据长度
        int tempByteLength, lineStartOffset, lineEndOffset;
        //lineByte 每行的完整数据
        //oneByte 一次获取的缓冲区的数据,与inBuffer中的实际有效数据相同
        byte[] lineByte, oneByte;

        oneByte = new byte[inBuffer.limit()];
        inBuffer.get(oneByte, inBuffer.position(), inBuffer.limit());
        for (int i = 0, count = oneByte.length; i < count; i++) {
            //判断是否为回车符(每行的开始标志)
            if (oneByte[i] == LF) {
                lineStartOffset = i + 1 < count && oneByte[i + 1] == CR ? 2 : 1;
                //处理多个空白行的情况
                if (oneByte[lineStartPosition] == LF) {
                    //兼容Linux与window系统,Linux系统文件没有CR(13)回车符
                    lineStartPosition = i + lineStartOffset;
                    System.out.println("---------blank lines");
                    continue;
                }

                lineByte = new byte[i - lineStartPosition + (tempByteLength = tempByte.length) - (lineEndOffset = oneByte[i - 1] == CR ? 1 : 0)];
                if (tempByteLength > 0) {
                    System.arraycopy(tempByte, 0, lineByte, 0, tempByteLength);
                    tempByte = new byte[0];
                }
                System.arraycopy(oneByte, lineStartPosition, lineByte, tempByteLength, i - lineStartPosition - lineEndOffset);
                //处理一行数据
                handleLine(lineByte);

                //兼容Linux与window系统,Linux系统文件没有CR(13)回车符
                lineStartPosition = i + lineStartOffset;
            }
        }

        //处理一行超长数据,一个tempByte数组长度存不下一行数据
        if (tempByte.length > 0) {
            int oldTempByteLen = tempByte.length;
            byte[] newTempByte = new byte[oldTempByteLen + inBuffer.limit() - lineStartPosition];
            System.arraycopy(tempByte, 0, newTempByte, 0, oldTempByteLen);
            tempByte = newTempByte;
            System.arraycopy(oneByte, lineStartPosition, tempByte, oldTempByteLen, inBuffer.limit() - lineStartPosition);
        } else {
            //处理上一次获取的剩余最后一行不完整数据
            tempByte = new byte[inBuffer.limit() - lineStartPosition];
            System.arraycopy(oneByte, lineStartPosition, tempByte, 0, inBuffer.limit() - lineStartPosition);
        }

        return tempByte;
    }

    /**
     * 处理方法(自己按需编写)
     * @param lineBytes 存储一行数据的数组
     */
    private void handleLine(byte[] lineBytes) {
        System.out.println(new String(lineBytes, CHARSET));
    }
}

 

转载于:https://my.oschina.net/u/2316420/blog/826478

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值