近来项目用到文件拆分,本来以为有库直接调用下,结果没找到,找到另外一篇文章对于拆分的实现,链接如下:
https://blog.csdn.net/u013632755/article/details/80467324
我根据项目需求稍微改了下,加了下注释,记录下来。
public static void splitFileDropFirstLine(String filePath, int fileCount) throws IOException { FileInputStream fis = new FileInputStream(filePath); //FileInputStream fis = new FileInputStream(new File(filePath)); FileChannel inputChannel = fis.getChannel(); final long fileSize = inputChannel.size(); long average = fileSize / fileCount; //要拆分的子文件大小 long bufferSize = 128; //这个设置为文件中最大的一行就可以,因为读到换行符就break了 ByteBuffer byteBuffer = ByteBuffer.allocate(Integer.valueOf(bufferSize + "")); long startPosition = 0; //long endPosition = average < bufferSize ? 0 : average - bufferSize; long endPosition = 0; //设置为0的话,第一行就会被删除,不会包含在子文件中,这个是拆分文件的需求决定的,如果要包//含第一行,这个值可以按照原文设置 boolean notWrite = false; boolean endFlag = false; boolean endwhileFlag = false; for (int i = 0; i < fileCount + 1; i++) { if (endPosition < fileSize) { //没到文件尾,就继续处理 int read = inputChannel.read(byteBuffer, endPosition); //readW: while (read != -1) { byteBuffer.flip(); byte[] array = byteBuffer.array(); for (int j = 0; j < array.length; j++) { byte b = array[j]; if (b == 10 || b == 13) { //如果有换行符,就终止读取 if (endPosition == 0) { notWrite = true; //第一行的话,不写文件 } endPosition += j; //这个可以使得split文件是基于整行的 endwhileFlag = true; //既然已经读到一行了,就不需要继续while循环读取了 break; //break readW; } } if(endwhileFlag) { endwhileFlag = false; break; } endPosition += bufferSize; //个人觉得,如果buffersize肯定大于文件中最大行的size的话,这一行就走不到 byteBuffer.clear(); read = inputChannel.read(byteBuffer, endPosition); } }else{ endPosition = fileSize; endFlag =true; } if(notWrite) { //如果是第一行数据,就不写文件 notWrite = false; startPosition = endPosition + 1; if(startPosition > fileSize) { break; } endPosition += average; continue; } if(startPosition > fileSize || startPosition > endPosition) { //测试的时候,发现会有溢出的问题,导致transferTo抛出异常,所以加一个判断,你开始位置都比文件大了,就跳出来 break; } String[] tempFile = filePath.split("\\."); String newTempFile = tempFile[0] + "_" + String.valueOf(i) + "." + tempFile[1]; //i=0的情况,已经被跳过了,所以拆分的子文件,是从1开始的,初始文件是file.txt的话,子文件就是file_1.txt,file_2.txt.... FileOutputStream fos = new FileOutputStream(newTempFile); FileChannel outputChannel = fos.getChannel(); inputChannel.transferTo(startPosition, endPosition - startPosition, outputChannel); outputChannel.close(); fos.close(); if(endFlag) { //如果endposition已经是filesize了,就不需要继续split了 break; } startPosition = endPosition + 1; endPosition += average;
} inputChannel.close(); fis.close();
}
1. 代码还有点啰嗦,可以继续改进
2. 有库可以直接用来拆分文件么?
