代码没有做复杂文件的测试,如果有问题,望请见谅并留言
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));
}
}