修复FileUtil#getTotalLines在JDK9+结果错误问题

This commit is contained in:
Looly 2024-05-20 16:40:21 +08:00
parent 228785b1b2
commit 9d4e69d4ed
4 changed files with 79 additions and 32 deletions

View File

@ -44,6 +44,7 @@
* 【db 】 修复JndiDSFactory空指针问题 * 【db 】 修复JndiDSFactory空指针问题
* 【core 】 修复BiMap.put错误的返回值pr#1218@Gitee * 【core 】 修复BiMap.put错误的返回值pr#1218@Gitee
* 【core 】 修复BooleanUtil.andOfWrap针对null错误问题issue#3587@Github * 【core 】 修复BooleanUtil.andOfWrap针对null错误问题issue#3587@Github
* 【core 】 修复FileUtil#getTotalLines在JDK9+结果错误问题issue#3591@Github
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
# 5.8.27(2024-03-29) # 5.8.27(2024-03-29)

View File

@ -14,6 +14,7 @@ import cn.hutool.core.io.resource.Resource;
import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.io.unit.DataSizeUtil; import cn.hutool.core.io.unit.DataSizeUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Console;
import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.CharUtil;
@ -24,20 +25,7 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil; import cn.hutool.core.util.URLUtil;
import cn.hutool.core.util.ZipUtil; import cn.hutool.core.util.ZipUtil;
import java.io.BufferedInputStream; import java.io.*;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
@ -580,24 +568,65 @@ public class FileUtil extends PathUtil {
/** /**
* 计算文件的总行数<br> * 计算文件的总行数<br>
* 读取文件采用系统默认编码一般乱码不会造成行数错误 * 参考https://stackoverflow.com/questions/453018/number-of-lines-in-a-file-in-java
* *
* @param file 文件 * @param file 文件
* @return 该文件总行数 * @return 该文件总行数
* @since 5.7.22 * @since 5.7.22
*/ */
public static int getTotalLines(File file) { public static int getTotalLines(File file) {
return getTotalLines(file, 1024);
}
/**
* 计算文件的总行数<br>
* 参考https://stackoverflow.com/questions/453018/number-of-lines-in-a-file-in-java
*
* @param file 文件
* @param bufferSize 缓存大小小于1则使用默认的1024
* @return 该文件总行数
* @since 5.8.28
*/
public static int getTotalLines(File file, int bufferSize) {
if (false == isFile(file)) { if (false == isFile(file)) {
throw new IORuntimeException("Input must be a File"); throw new IORuntimeException("Input must be a File");
} }
try (final LineNumberReader lineNumberReader = new LineNumberReader(new java.io.FileReader(file))) { if (bufferSize < 1) {
// 设置起始为1 bufferSize = 1024;
lineNumberReader.setLineNumber(1); }
// 跳过文件中内容 try (InputStream is = getInputStream(file)) {
//noinspection ResultOfMethodCallIgnored byte[] c = new byte[bufferSize];
lineNumberReader.skip(Long.MAX_VALUE); int readChars = is.read(c);
// 获取当前行号 if (readChars == -1) {
return lineNumberReader.getLineNumber(); // 空文件返回0
return 0;
}
// 起始行为1
// 如果只有一行无换行符则读取结束后返回1
// 如果多行最后一行无换行符最后一行需要单独计数
// 如果多行最后一行有换行符则空行算作一行
int count = 1;
while (readChars == bufferSize) {
for (int i = 0; i < bufferSize; i++) {
if (c[i] == CharUtil.LF) {
++count;
}
}
readChars = is.read(c);
}
// count remaining characters
while (readChars != -1) {
for (int i = 0; i < readChars; i++) {
if (c[i] == CharUtil.LF) {
++count;
}
}
readChars = is.read(c);
}
return count;
} catch (IOException e) { } catch (IOException e) {
throw new IORuntimeException(e); throw new IORuntimeException(e);
} }
@ -3510,7 +3539,7 @@ public class FileUtil extends PathUtil {
* @since 4.1.15 * @since 4.1.15
*/ */
public static String getMimeType(String filePath) { public static String getMimeType(String filePath) {
if(StrUtil.isBlank(filePath)){ if (StrUtil.isBlank(filePath)) {
return null; return null;
} }

View File

@ -523,11 +523,17 @@ public class FileUtilTest {
} }
@Test @Test
@Ignore
public void getTotalLinesTest() { public void getTotalLinesTest() {
// 千万行秒级内返回 // 此文件最后一行有换行符则最后的空行算作一行
final int totalLines = FileUtil.getTotalLines(FileUtil.file("")); final int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines.csv"));
Assert.assertEquals(10000000, totalLines); Assert.assertEquals(8, totalLines);
}
@Test
public void issue3591Test() {
// 此文件最后一行末尾无换行符
final int totalLines = FileUtil.getTotalLines(FileUtil.file("1_psi_index_0.txt"));
Assert.assertEquals(11, totalLines);
} }
@Test @Test

View File

@ -0,0 +1,11 @@
0
1
2
3
4
5
6
7
8
9
10