net.lulihu.ObjectKit.FileKit Maven / Gradle / Ivy
package net.lulihu.ObjectKit;
import lombok.extern.slf4j.Slf4j;
import net.lulihu.Assert0;
import net.lulihu.exception.ToolBoxException;
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
/**
* 文件工具类
*/
@Slf4j
public class FileKit {
/**
* 文件读写默认字节码
*/
private static final int FILE_BYTE_CODE = 1024;
/**
* 获取临时目录
*/
public static String getTempPath() {
return System.getProperty("java.io.tmpdir");
}
/**
* 随机产生一个临时文件路径
*
* @param suffix 文件后缀
*/
public static String tmpFilePath(String suffix) {
String tmpFile = getTempPath() + "tmp_files" + File.separator +
IDGeneratorKit.get() + "." + suffix;
if (new File(tmpFile).exists()) return tmpFilePath(suffix);
return tmpFile;
}
/**
* 流写入文件
*/
public static void writeFile(InputStream is, File file) throws IOException {
BufferedInputStream in = null;
BufferedOutputStream out = null;
try {
in = new BufferedInputStream(is);
out = new BufferedOutputStream(new FileOutputStream(file));
int len;
byte[] b = new byte[FILE_BYTE_CODE];
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
} finally {
closeInputStream(in);
closeOutputStream(out);
}
}
/**
* 集合写入文件
*
* @param list 集合
* @param filePath 文件地址
*/
public static Path ArrayWriteFile(Iterable extends CharSequence> list, String filePath) throws IOException {
return ArrayWriteFile(list, fileIsNullCreate(filePath));
}
public static Path ArrayWriteFile(Iterable extends CharSequence> list, Path path) throws IOException {
return Files.write(path, list, Charset.forName("utf-8"));
}
/**
* 文件拷贝
*
* @param source 源文件地址
* @param target 目标文件地址
* @return 拷贝成功返回true 反之false
*/
public static boolean copy(String source, String target) throws IOException {
return copy(new File(source), new File(target));
}
public static boolean copy(File source, File target) throws IOException {
return source.exists() && copy(new FileInputStream(source), target);
}
public static boolean copy(FileInputStream inputStream, File target) throws IOException {
FileChannel input = null;
FileChannel output = null;
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(target);
input = inputStream.getChannel();
output = outputStream.getChannel();
output.transferFrom(input, 0, input.size());
} catch (IOException e) {
throw new IOException("文件拷贝错误" + target, e);
} finally {
closeChannel(input);
closeChannel(output);
closeInputStream(inputStream);
closeOutputStream(outputStream);
}
return true;
}
/**
* 文件夹类文件名称排序 只限文件名称为整数类型
*
* @param dirPath 文件夹路径
* @return 文件数组
*/
public static File[] fileSort(String dirPath) {
File file = new File(dirPath);
String[] list = file.list();
if (list == null || list.length == 0)
return null;
List files = Arrays.asList(list);
if (files.size() != 1) {
files.sort((o1, o2) -> {
Integer i1 = Integer.valueOf(o1.substring(0, o1.lastIndexOf(".")));
Integer i2 = Integer.valueOf(o2.substring(0, o2.lastIndexOf(".")));
if (i1 > i2)
return 1;
else if (i1 < i2)
return -1;
else
return 0;
});
}
String path = file.getPath() + File.separator;
int n = files.size();
File[] fs = new File[n];
for (int i = 0; i < n; i++) {
fs[i] = new File(path + files.get(i));
}
return fs;
}
public static void delete(final String dirPath) {
delete(new File(dirPath), true);
}
/**
* 删除此文件或文件夹及其下的所有文件及子文件夹,并删除文件夹本身.
*
* @param dir 待删除的文件(夹)
*/
public static void delete(final File dir) {
delete(dir, true);
}
/**
* 删除文件(夹),选项:是否包括本身
*
* @param dir 待删除的文件(夹)
* @param self 若dir是文件夹,self表示是否删除文件夹本身
*/
public static void delete(final File dir, final boolean self) {
if (!dir.exists()) {
return;
}
if (!dir.isDirectory()) {
dir.delete();
return;
}
final String[] list = dir.list();
if (list != null) {
for (final String element : list) {
final File child = new File(dir, element);
delete(child);
}
}
if (self) {
dir.delete();
}
}
/**
* 合并文件
*
* @param fpaths 文件数组
* @param resultPath 合并文件保存路径
*/
public static void mergeFiles(File[] fpaths, String resultPath) throws IOException {
if (fpaths == null || fpaths.length < 1) return;
for (File fpath : fpaths) {
if (!fpath.exists() || !fpath.isFile()) {
throw new ToolBoxException("{}不存在或者不是普通文件...", fpath.getPath());
}
}
File resultFile = FileKit.createFile(resultPath);
FileOutputStream fs = new FileOutputStream(resultFile, true);
FileChannel resultFileChannel = fs.getChannel();
FileInputStream tfs = null;
for (File fpath : fpaths) {
FileChannel blk = null;
try {
tfs = new FileInputStream(fpath);
blk = tfs.getChannel();
resultFileChannel.transferFrom(blk, resultFileChannel.size(), blk.size());
} finally {
closeInputStream(tfs);
closeChannel(blk);
}
}
closeOutputStream(fs);
closeChannel(resultFileChannel);
}
/**
* 文件是否存在
*
* @param filePath 文件路径
* @return 不存在返回true 反之false
*/
public static boolean isEmpty(String filePath) {
return !isNotEmpty(filePath);
}
/**
* 文件是否存在
*
* @param filePath 文件路径
* @return 存在返回true 反之false
*/
public static boolean isNotEmpty(String filePath) {
return Files.exists(Paths.get(filePath));
}
/**
* 文件不存在,创建
*
* @param indexPath 文件路径
* @return Path
*/
public static Path fileIsNullCreate(String indexPath) throws IOException {
createFile(indexPath);
return Paths.get(indexPath);
}
/**
* 读取文件流转成字符串输出
* 如果文件不存在,则返回null
*
* @param filepath 文件路径
* @return 字符串
*/
public static String readFileToString(String filepath) throws IOException {
File file = new File(filepath);
if (!file.exists()) return null;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(file));
String s;
StringBuilder builder = new StringBuilder();
while ((s = br.readLine()) != null) {
builder.append(s);
}
return builder.toString();
} finally {
closeReader(br);
}
}
/**
* 创建文件,可以包括创建多级文件目录 。
*
* 根据抽象字串文件名新建文件,若文件的上级目录不存在,则先创建目录,再创建文件,返回新文件. 若文件存在,直接返回.
*
*
* @param filename 待创建的文件的抽象文件名称,若为null返回null;若此名称的文件已存在,则直接返回该文件.
* @return File 创建的文件
* @throws IOException
*/
public static File createFile(final String filename) throws IOException {
Assert0.toolBox().notNull(filename, "文件路径不可以为空...");
return createFile(new File(filename));
}
/**
* 创建文件,可以包括创建多级文件目录
*
* 由文件对象创建文件,若文件的上级目录不存在,则先创建目录,再创建文件,返回新文件. 若文件存在,直接返回.
*
*
* @param file 待创建的文件
* @return File 创建的文件
* @throws IOException
*/
public static File createFile(final File file) throws IOException {
if (!file.exists()) {
createDirectoryRecursively(file.getParent());
file.createNewFile();
}
return file;
}
/**
* 创建文件目录(包括子目录) 支持创建多级文件目录,如“d:/aaa/bbb/ccc”
*
* @param directory 待创建的文件(夹),支持多级路径. 若为文件或null返回false; 若目录已存在则返回true;
* @return boolean
*/
public static boolean createDirectoryRecursively(String directory) {
if (directory == null) {
return false;
}
File pathname = new File(directory);
if (pathname.exists()) {
return !pathname.isFile();
} else if (!pathname.isAbsolute()) {
pathname = new File(pathname.getAbsolutePath());
}
final String parent = pathname.getParent();
if (!createDirectoryRecursively(parent)) {
return false;
}
pathname.mkdir();
return pathname.exists();
}
/**
* 关闭文件通道
*
* @param channel channel
*/
private static void closeChannel(FileChannel channel) {
if (channel != null) {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 关闭输入流。
*
* @param is 输入流,可以是null。
*/
private static void closeInputStream(InputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 关闭输出流
*
* @param fos 文件输出;流可以为null
*/
private static void closeOutputStream(OutputStream fos) {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 关闭Reader
*
* @param reader reader
*/
private static void closeReader(Reader reader) {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
log.error("关闭Reader对象异常", e);
}
}
}