From c3aabfcd1479b7dc9511c953c577468bf28f5fd5 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 12 Jun 2024 16:32:42 +0800 Subject: [PATCH] add LineCounter --- .../dromara/hutool/core/io/file/FileUtil.java | 43 +------- .../hutool/core/io/stream/LineCounter.java | 102 ++++++++++++++++++ 2 files changed, 107 insertions(+), 38 deletions(-) create mode 100644 hutool-core/src/main/java/org/dromara/hutool/core/io/stream/LineCounter.java diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java index 440110721..1a641adbc 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java @@ -23,6 +23,7 @@ import org.dromara.hutool.core.io.resource.FileResource; import org.dromara.hutool.core.io.resource.Resource; import org.dromara.hutool.core.io.resource.ResourceUtil; import org.dromara.hutool.core.io.stream.BOMInputStream; +import org.dromara.hutool.core.io.stream.LineCounter; import org.dromara.hutool.core.io.unit.DataSizeUtil; import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.lang.Console; @@ -551,7 +552,7 @@ public class FileUtil extends PathUtil { * @since 5.7.22 */ public static int getTotalLines(final File file) { - return getTotalLines(file, 1024); + return getTotalLines(file, -1); } /** @@ -563,46 +564,12 @@ public class FileUtil extends PathUtil { * @return 该文件总行数 * @since 5.8.28 */ - public static int getTotalLines(final File file, int bufferSize) { + public static int getTotalLines(final File file, final int bufferSize) { if (false == isFile(file)) { throw new IORuntimeException("Input must be a File"); } - if (bufferSize < 1) { - bufferSize = 1024; - } - try (final InputStream is = getInputStream(file)) { - final byte[] c = new byte[bufferSize]; - int readChars = is.read(c); - if (readChars == -1) { - // 空文件,返回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; + try (final LineCounter lineCounter = new LineCounter(getInputStream(file), bufferSize)) { + return lineCounter.getCount(); } catch (final IOException e) { throw new IORuntimeException(e); } 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 new file mode 100644 index 000000000..49b4b37d5 --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/LineCounter.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2024. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.io.stream; + +import org.dromara.hutool.core.io.IORuntimeException; +import org.dromara.hutool.core.text.CharUtil; + +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; + +/** + * 行数计数器 + * + * @since 6.0.0 + */ +public class LineCounter implements Closeable { + + private final InputStream is; + private final int bufferSize; + + private int count = -1; + + /** + * 构造 + * + * @param is 输入流 + * @param bufferSize 缓存大小,小于1则使用默认的1024 + */ + public LineCounter(final InputStream is, final int bufferSize) { + this.is = is; + this.bufferSize = bufferSize < 1 ? 1024 : bufferSize; + } + + /** + * 获取行数 + * + * @return 行数 + */ + public int getCount() { + if (this.count < 0) { + try { + this.count = count(); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + } + return this.count; + } + + @Override + public void close() throws IOException { + if (null != this.is) { + this.is.close(); + } + } + + private int count() throws IOException { + final byte[] c = new byte[bufferSize]; + int readChars = is.read(c); + if (readChars == -1) { + // 空文件,返回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; + } +}