mirror of
https://gitee.com/dromara/hutool.git
synced 2025-06-28 13:34:09 +08:00
FileWriter
增加方法,可选是否追加换行符(issue#3858@Github)
This commit is contained in:
parent
dda0862c1c
commit
fcab6e6340
@ -564,7 +564,8 @@ public class FileUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算文件的总行数<br>
|
* 计算文件的总行数<br>
|
||||||
* 参考:https://stackoverflow.com/questions/453018/number-of-lines-in-a-file-in-java
|
* 参考:https://stackoverflow.com/questions/453018/number-of-lines-in-a-file-in-java<br>
|
||||||
|
* 最后一行如果末尾带有换行符,则被当作为新行
|
||||||
*
|
*
|
||||||
* @param file 文件
|
* @param file 文件
|
||||||
* @return 该文件总行数
|
* @return 该文件总行数
|
||||||
@ -576,7 +577,8 @@ public class FileUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算文件的总行数<br>
|
* 计算文件的总行数<br>
|
||||||
* 参考:https://stackoverflow.com/questions/453018/number-of-lines-in-a-file-in-java
|
* 参考:https://stackoverflow.com/questions/453018/number-of-lines-in-a-file-in-java<br>
|
||||||
|
* 最后一行如果末尾带有换行符,则被当作为新行
|
||||||
*
|
*
|
||||||
* @param file 文件
|
* @param file 文件
|
||||||
* @param bufferSize 缓存大小,小于1则使用默认的1024
|
* @param bufferSize 缓存大小,小于1则使用默认的1024
|
||||||
@ -584,8 +586,23 @@ public class FileUtil {
|
|||||||
* @since 5.8.28
|
* @since 5.8.28
|
||||||
*/
|
*/
|
||||||
public static int getTotalLines(final File file, final int bufferSize) {
|
public static int getTotalLines(final File file, final int bufferSize) {
|
||||||
|
return getTotalLines(file, bufferSize, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算文件的总行数<br>
|
||||||
|
* 参考:https://stackoverflow.com/questions/453018/number-of-lines-in-a-file-in-java
|
||||||
|
*
|
||||||
|
* @param file 文件
|
||||||
|
* @param bufferSize 缓存大小,小于1则使用默认的1024
|
||||||
|
* @param lastLineSeparatorAsNewLine 是否将最后一行分隔符作为新行,Linux下要求最后一行必须带有换行符,不算一行,此处用户选择
|
||||||
|
* @return 该文件总行数
|
||||||
|
* @since 5.8.28
|
||||||
|
*/
|
||||||
|
public static int getTotalLines(final File file, final int bufferSize, final boolean lastLineSeparatorAsNewLine) {
|
||||||
Assert.isTrue(isFile(file), ()-> new IORuntimeException("Input must be a File"));
|
Assert.isTrue(isFile(file), ()-> new IORuntimeException("Input must be a File"));
|
||||||
try (final LineCounter lineCounter = new LineCounter(getInputStream(file), bufferSize)) {
|
try (final LineCounter lineCounter = new LineCounter(getInputStream(file), bufferSize)) {
|
||||||
|
lineCounter.setLastLineSeparatorAsNewLine(lastLineSeparatorAsNewLine);
|
||||||
return lineCounter.getCount();
|
return lineCounter.getCount();
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
throw new IORuntimeException(e);
|
throw new IORuntimeException(e);
|
||||||
@ -2493,10 +2510,28 @@ public class FileUtil {
|
|||||||
* @return 目标文件
|
* @return 目标文件
|
||||||
* @throws IORuntimeException IO异常
|
* @throws IORuntimeException IO异常
|
||||||
*/
|
*/
|
||||||
public static <T> File writeLines(final Collection<T> list, final File file, final Charset charset, final boolean isAppend) throws IORuntimeException {
|
public static <T> File writeLines(final Collection<T> list, final File file, final Charset charset,
|
||||||
|
final boolean isAppend) throws IORuntimeException {
|
||||||
return FileWriter.of(file, charset).writeLines(list, isAppend);
|
return FileWriter.of(file, charset).writeLines(list, isAppend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将列表写入文件
|
||||||
|
*
|
||||||
|
* @param <T> 集合元素类型
|
||||||
|
* @param list 列表
|
||||||
|
* @param file 文件
|
||||||
|
* @param charset 字符集
|
||||||
|
* @param isAppend 是否追加
|
||||||
|
* @param appendLineSeparator 是否在末尾追加换行符
|
||||||
|
* @return 目标文件
|
||||||
|
* @throws IORuntimeException IO异常
|
||||||
|
*/
|
||||||
|
public static <T> File writeLines(final Collection<T> list, final File file, final Charset charset,
|
||||||
|
final boolean isAppend, final boolean appendLineSeparator) throws IORuntimeException {
|
||||||
|
return FileWriter.of(file, charset).writeLines(list, null, isAppend, appendLineSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将Map写入文件,每个键值对为一行,一行中键与值之间使用kvSeparator分隔
|
* 将Map写入文件,每个键值对为一行,一行中键与值之间使用kvSeparator分隔
|
||||||
*
|
*
|
||||||
|
@ -193,7 +193,7 @@ public class FileWriter extends FileWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将列表写入文件
|
* 将列表写入文件,最后一行末尾不追加换行符
|
||||||
*
|
*
|
||||||
* @param <T> 集合元素类型
|
* @param <T> 集合元素类型
|
||||||
* @param list 列表
|
* @param list 列表
|
||||||
@ -204,6 +204,22 @@ public class FileWriter extends FileWrapper {
|
|||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
*/
|
*/
|
||||||
public <T> File writeLines(final Iterable<T> list, final LineSeparator lineSeparator, final boolean isAppend) throws IORuntimeException {
|
public <T> File writeLines(final Iterable<T> list, final LineSeparator lineSeparator, final boolean isAppend) throws IORuntimeException {
|
||||||
|
return writeLines(list, lineSeparator, isAppend, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将列表写入文件
|
||||||
|
*
|
||||||
|
* @param <T> 集合元素类型
|
||||||
|
* @param list 列表
|
||||||
|
* @param lineSeparator 换行符枚举(Windows、Mac或Linux换行符)
|
||||||
|
* @param isAppend 是否追加
|
||||||
|
* @param appendLineSeparator 是否在最后一行末尾追加换行符,Linux下要求最后一行必须带有换行符
|
||||||
|
* @return 目标文件
|
||||||
|
* @throws IORuntimeException IO异常
|
||||||
|
* @since 3.1.0
|
||||||
|
*/
|
||||||
|
public <T> File writeLines(final Iterable<T> list, final LineSeparator lineSeparator, final boolean isAppend, final boolean appendLineSeparator) throws IORuntimeException {
|
||||||
try (final PrintWriter writer = getPrintWriter(isAppend)) {
|
try (final PrintWriter writer = getPrintWriter(isAppend)) {
|
||||||
boolean isFirst = true;
|
boolean isFirst = true;
|
||||||
for (final T t : list) {
|
for (final T t : list) {
|
||||||
@ -218,6 +234,9 @@ public class FileWriter extends FileWrapper {
|
|||||||
printNewLine(writer, lineSeparator);
|
printNewLine(writer, lineSeparator);
|
||||||
}
|
}
|
||||||
writer.print(t);
|
writer.print(t);
|
||||||
|
if(appendLineSeparator){
|
||||||
|
printNewLine(writer, lineSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
writer.flush();
|
writer.flush();
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,10 @@ public class LineCounter implements Closeable {
|
|||||||
private final InputStream is;
|
private final InputStream is;
|
||||||
private final int bufferSize;
|
private final int bufferSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否将最后一行分隔符作为新行,Linux下要求最后一行必须带有换行符,不算一行,此处用户选择
|
||||||
|
*/
|
||||||
|
private boolean lastLineSeparatorAsNewLine = true;
|
||||||
private int count = -1;
|
private int count = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,6 +50,17 @@ public class LineCounter implements Closeable {
|
|||||||
this.bufferSize = bufferSize < 1 ? 1024 : bufferSize;
|
this.bufferSize = bufferSize < 1 ? 1024 : bufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置是否将最后一行分隔符作为新行,Linux下要求最后一行必须带有换行符,不算一行,此处用户选择
|
||||||
|
*
|
||||||
|
* @param lastLineSeparatorAsNewLine 是否将最后一行分隔符作为新行
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public LineCounter setLastLineSeparatorAsNewLine(final boolean lastLineSeparatorAsNewLine) {
|
||||||
|
this.lastLineSeparatorAsNewLine = lastLineSeparatorAsNewLine;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取行数
|
* 获取行数
|
||||||
*
|
*
|
||||||
@ -108,9 +123,16 @@ public class LineCounter implements Closeable {
|
|||||||
readChars = is.read(buf);
|
readChars = is.read(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 最后一个字符为换行符,则单独计数行
|
if(lastLineSeparatorAsNewLine){
|
||||||
if(c == CharUtil.CR){
|
// 最后一个字符为\r,则单独计数行
|
||||||
++count;
|
if(c == CharUtil.CR){
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
// 最后一个字符为\n,则可选是否算作新行单独计数行
|
||||||
|
if(c == CharUtil.LF){
|
||||||
|
--count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -467,22 +467,31 @@ public class FileUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
public void getTotalLinesTest() {
|
public void getTotalLinesTest() {
|
||||||
// 此文件最后一行有换行符,则最后的空行算作一行
|
// 此文件最后一行有换行符,则最后的空行算作一行
|
||||||
final int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines.csv"));
|
int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines.csv"));
|
||||||
Assertions.assertEquals(8, totalLines);
|
Assertions.assertEquals(8, totalLines);
|
||||||
|
|
||||||
|
totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines.csv"), -1, false);
|
||||||
|
Assertions.assertEquals(7, totalLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getTotalLinesCrTest() {
|
public void getTotalLinesCrTest() {
|
||||||
// 此文件最后一行有换行符,则最后的空行算作一行
|
// 此文件最后一行有换行符,则最后的空行算作一行
|
||||||
final int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_cr.csv"));
|
int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_cr.csv"));
|
||||||
assertEquals(8, totalLines);
|
assertEquals(8, totalLines);
|
||||||
|
|
||||||
|
totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_cr.csv"), -1, false);
|
||||||
|
Assertions.assertEquals(7, totalLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getTotalLinesCrlfTest() {
|
public void getTotalLinesCrlfTest() {
|
||||||
// 此文件最后一行有换行符,则最后的空行算作一行
|
// 此文件最后一行有换行符,则最后的空行算作一行
|
||||||
final int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_crlf.csv"));
|
int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_crlf.csv"));
|
||||||
assertEquals(8, totalLines);
|
assertEquals(8, totalLines);
|
||||||
|
|
||||||
|
totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_crlf.csv"), -1, false);
|
||||||
|
Assertions.assertEquals(7, totalLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user