From 54c858b8f1b375269ce0e2c3aad369da62369fa6 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 29 Aug 2024 09:49:54 +0800 Subject: [PATCH] =?UTF-8?q?FileUtil.getTotalLines()=E6=94=AF=E6=8C=81CR?= =?UTF-8?q?=E6=8D=A2=E8=A1=8C=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hutool/core/io/stream/LineCounter.java | 24 ++++++++++++++----- .../hutool/core/io/file/FileUtilTest.java | 16 +++++++++++++ .../src/test/resources/test_lines_cr.csv | 1 + .../src/test/resources/test_lines_crlf.csv | 7 ++++++ 4 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 hutool-core/src/test/resources/test_lines_cr.csv create mode 100644 hutool-core/src/test/resources/test_lines_crlf.csv diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/LineCounter.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/LineCounter.java index bb99cb2e9..ca7c4b199 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/LineCounter.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/LineCounter.java @@ -70,8 +70,8 @@ public class LineCounter implements Closeable { } private int count() throws IOException { - final byte[] c = new byte[bufferSize]; - int readChars = is.read(c); + final byte[] buf = new byte[bufferSize]; + int readChars = is.read(buf); if (readChars == -1) { // 空文件,返回0 return 0; @@ -82,23 +82,35 @@ public class LineCounter implements Closeable { // 如果多行,最后一行无换行符,最后一行需要单独计数 // 如果多行,最后一行有换行符,则空行算作一行 int count = 1; + byte pre; + byte c = 0; while (readChars == bufferSize) { for (int i = 0; i < bufferSize; i++) { - if (c[i] == CharUtil.LF) { + pre = c; + c = buf[i]; + // 换行符兼容MAC + if (c == CharUtil.LF || pre == CharUtil.CR) { ++count; } } - readChars = is.read(c); + readChars = is.read(buf); } // count remaining characters while (readChars != -1) { for (int i = 0; i < readChars; i++) { - if (c[i] == CharUtil.LF) { + pre = c; + c = buf[i]; + if (c == CharUtil.LF || pre == CharUtil.CR) { ++count; } } - readChars = is.read(c); + readChars = is.read(buf); + } + + // 最后一个字符为换行符,则单独计数行 + if(c == CharUtil.CR){ + ++count; } return count; diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/io/file/FileUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/io/file/FileUtilTest.java index 22ffc0b85..5a8fe18fd 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/io/file/FileUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/io/file/FileUtilTest.java @@ -27,6 +27,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; +import static org.junit.jupiter.api.Assertions.assertEquals; + /** * {@link FileUtil} 单元测试类 * @@ -501,6 +503,20 @@ public class FileUtilTest { Assertions.assertEquals(8, totalLines); } + @Test + public void getTotalLinesCrTest() { + // 此文件最后一行有换行符,则最后的空行算作一行 + final int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_cr.csv")); + assertEquals(8, totalLines); + } + + @Test + public void getTotalLinesCrlfTest() { + // 此文件最后一行有换行符,则最后的空行算作一行 + final int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_crlf.csv")); + assertEquals(8, totalLines); + } + @Test public void issue3591Test() { // 此文件最后一行末尾无换行符 diff --git a/hutool-core/src/test/resources/test_lines_cr.csv b/hutool-core/src/test/resources/test_lines_cr.csv new file mode 100644 index 000000000..4e9622be3 --- /dev/null +++ b/hutool-core/src/test/resources/test_lines_cr.csv @@ -0,0 +1 @@ +# 这是一行注释,读取时应忽略 a,b,c,d 1,2,3,4 # 这是一行注释,读取时应忽略 q,w,e,r,"我是一段 带换行的内容" a,s,d,f \ No newline at end of file diff --git a/hutool-core/src/test/resources/test_lines_crlf.csv b/hutool-core/src/test/resources/test_lines_crlf.csv new file mode 100644 index 000000000..32daf5460 --- /dev/null +++ b/hutool-core/src/test/resources/test_lines_crlf.csv @@ -0,0 +1,7 @@ +# 这是一行注释,读取时应忽略 +a,b,c,d +1,2,3,4 +# 这是一行注释,读取时应忽略 +q,w,e,r,"我是一段 +带换行的内容" +a,s,d,f