目前对这个文件的操作,我觉得得有专门的一个自己很熟练的工具来使用,目前为止,我觉得应该集多家的文件处理Util所长为自己所用
apache.common 里面的工具,还有就是spring中的工具,还有就是自己本身的一些工具
所有的这些工具都给自己
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.1</version>
</dependency>
1.创建文件
2.文件内容添加
3.文件迭代创建
4.本机的文件加锁
其中本机的文件锁其实必要性不是很大,因为通常情况下就直接采用分布式锁就可以了
场景:
1.单机多进程,竞争同一个资源
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.isyscore.isc.neo.NeoMap;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.quartz.*;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
/**
* @author shizi
* @since 2019/12/3 11:48 上午
*/
@Slf4j
@UtilityClass
public class FileUtil {
private Charset CRYPTO_CHARSET = StandardCharsets.UTF_8;
private static SchedulerFactory schedulerFactory = new org.quartz.impl.StdSchedulerFactory();
private static Scheduler scheduler;
static {
try {
scheduler = schedulerFactory.getScheduler();
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 获取文件
*/
public File getFile(String fileName) throws IOException {
File file = new File(fileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
if (!file.exists()) {
file.createNewFile();
}
file.setReadable(true);
file.setWritable(true);
return file;
}
/**
* 获取文件夹类型的文件
*/
public File getDirectFile(String fileName) {
File file = new File(fileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
if (!file.exists()) {
file.mkdir();
}
file.setReadable(true);
file.setWritable(true);
return file;
}
@SuppressWarnings("all")
public Boolean createFile(String fileName) throws IOException {
File file = new File(fileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
if (!file.exists() && file.createNewFile()) {
return file.setReadable(true) && file.setWritable(true);
}
return false;
}
public Boolean exist(String fileFullPath){
File file = new File(fileFullPath);
return file.exists();
}
/**
* 向文件中写入对应的文件
*/
public void writeFile(File file, String content) throws IOException {
try (FileOutputStream outputStream = new FileOutputStream(file)) {
outputStream.write(content.getBytes(CRYPTO_CHARSET));
outputStream.flush();
}
}
public void writeFile(String file, String content) throws IOException {
try (FileOutputStream outputStream = new FileOutputStream(new File(file))) {
outputStream.write(content.getBytes(CRYPTO_CHARSET));
outputStream.flush();
}
}
public BufferedReader readFile(File file) throws IOException {
return Files.newBufferedReader(file.toPath(), CRYPTO_CHARSET);
}
public String readFromFile(File file) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader bufferedReader = readFile(file)) {
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
}
return stringBuilder.toString();
}
/**
* 读取资源文件中的内容
* @param cls 类所在的位置
* @param resourceFileName 资源文件中的位置比如:/script/base.groovy,其中前面一定要有"/"
* @return 文件的字符数据
*/
public String readFromResource(Class cls, String resourceFileName) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
InputStream inputStream = cls.getResourceAsStream(resourceFileName);
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
} finally {
inputStream.close();
assert bufferedReader != null;
bufferedReader.close();
}
return stringBuilder.toString();
}
/**
* 通过文件的绝对路径读取文件信息
*/
public String read(String filePath) throws IOException {
FileReader fileReader;
StringBuilder stringBuilder = new StringBuilder();
fileReader = new FileReader(filePath);
char[] cbuf = new char[32];
int hasRead = 0;
while ((hasRead = fileReader.read(cbuf)) > 0) {
stringBuilder.append(cbuf, 0, hasRead);
}
return stringBuilder.toString();
}
public FileInputStream readToStream(String filePath) throws IOException {
File file = new File(filePath);
if (file.exists()) {
return new FileInputStream(file);
}
return null;
}
/**
* 向绝对路径中的文件写入对应的数据信息
*/
public void write(String filePath, String content) throws IOException {
writeFile(getFile(filePath), content);
}
public String readUrl(String FileName) throws IOException {
String read;
StringBuilder stringBuilder = new StringBuilder();
try {
URL url = new URL(FileName);
HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();
urlCon.setConnectTimeout(5000);
urlCon.setReadTimeout(5000);
BufferedReader br = new BufferedReader(new InputStreamReader(urlCon.getInputStream()));
while ((read = br.readLine()) != null) {
stringBuilder.append(read);
}
br.close();
} catch (IOException e) {
}
return stringBuilder.toString();
}
public void appendFile(String filePath, List<String> content) {
FileWriter fw = null;
if (content == null || content.isEmpty()) {
return;
}
try {
//如果文件存在,则追加内容;如果文件不存在,则创建文件
File file = getFile(filePath);
if ((!file.exists()) &&
(!file.createNewFile())) {
throw new IOException("create file '" + filePath +
"' failure.");
}
fw = new FileWriter(file, true);
PrintWriter pw = new PrintWriter(fw);
for (String str : content) {
if(str != null && !"".equals(str)) {
pw.println(str);
}
}
pw.flush();
fw.flush();
pw.close();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void appendFile(String filePath, String content) {
List<String> contents = new ArrayList<>();
contents.add(content);
appendFile(filePath, contents);
}
public boolean delete(String filePath) {
return delete(new File(filePath));
}
public boolean delete(File file) {
if (null == file || !file.exists()) {
return false;
}
if (file.isFile()) {
return file.delete();
} else {
File[] childFile = file.listFiles();
if (null == childFile) {
return false;
}
for (File fileMeta : childFile) {
delete(fileMeta);
}
}
return file.delete();
}
/**
* 文件加锁
* <p>
* <ul>
* <li>1.可重入</li>
* <li>2.锁有过期时间</li>
* <li>3.自动延长过期时间</li>
* </ul>
*
* @param lockFile 加锁对应的文件的路径
* @return true:加锁成功,false:加锁失败
*/
public boolean lock(String lockFile) {
try {
File compressLock = new File(lockFile);
if (compressLock.isDirectory()) {
return false;
}
String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
String tid = String.valueOf(Thread.currentThread().getId());
if (!compressLock.exists() && null != getFile(lockFile)) {
NeoMap dataMap = NeoMap.of();
dataMap.put("time", DateUtils.addMinutes(new Date(), -1).getTime());
dataMap.put("pid", pid);
dataMap.put("tid", tid);
writeFile(compressLock, JSON.toJSONString(dataMap));
startDelayThread(lockFile);
return true;
} else {
String lockData = readFromFile(compressLock);
JSONObject dataMap = JSONObject.parseObject(lockData);
if (null == dataMap) {
return false;
}
// 锁可重入
if (dataMap.containsKey("pid") && dataMap.containsKey("tid")) {
String pidCache = dataMap.getString("pid");
String tidCache = dataMap.getString("tid");
if (!StringUtils.isEmpty(pidCache) && pidCache.equals(pid) && !StringUtils.isEmpty(tidCache) && tidCache.equals(tid)) {
// 重入后,顺便更新下下次时间
dataMap.put("time", getNextTime());
writeFile(compressLock, JSON.toJSONString(dataMap));
return true;
}
}
if (dataMap.containsKey("time")) {
Long timeLong = dataMap.getLong("time");
if (timeLong < System.currentTimeMillis()) {
// 锁过期,则重新占有
if (createFile(lockFile + "_lock")) {
dataMap.put("time", getNextTime());
dataMap.put("pid", pid);
dataMap.put("tid", tid);
writeFile(compressLock, JSON.toJSONString(dataMap));
delete(lockFile + "_lock");
return true;
}
return false;
}
}
}
} catch (IOException e) {
log.error("lock exception", e);
return false;
}
return false;
}
/**
* 启动延期保护线程,20秒执行一次,每次向后默认延长1分钟
*/
private void startDelayThread(String filePath) {
try {
JobDetail job = JobBuilder.newJob(InnerJob.class).withIdentity(new JobKey(filePath)).usingJobData("filePath", filePath).build();
Trigger trigger = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(30)).build();
scheduler.scheduleJob(job, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 关闭延期保护线程
*/
private void closeDelayThread(String filePath) {
try {
scheduler.deleteJob(new JobKey(filePath));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
private Long getNextTime() {
return DateUtils.addMinutes(new Date(), 1).getTime();
}
public boolean unlock(String lockFile) {
File compressLock = new File(lockFile);
if (compressLock.isDirectory()) {
return false;
}
String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
String tid = String.valueOf(Thread.currentThread().getId());
try {
String lockData = readFromFile(compressLock);
JSONObject dataMap = JSONObject.parseObject(lockData);
if (null == dataMap) {
return false;
}
if (dataMap.containsKey("pid") && dataMap.containsKey("tid")) {
String pidCache = dataMap.getString("pid");
String tidCache = dataMap.getString("tid");
// 保证删除的是自己的
if (!StringUtils.isEmpty(pidCache) && pidCache.equals(pid) && !StringUtils.isEmpty(tidCache) && tidCache.equals(tid)) {
closeDelayThread(lockFile);
return compressLock.delete();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public class InnerJob implements Job {
public InnerJob() {}
@Override
public void execute(JobExecutionContext context) {
String filePath = context.getJobDetail().getJobDataMap().getString("filePath");
try {
if (!exist(filePath)) {
return;
}
String content = read(filePath);
JSONObject contentObject = JSONObject.parseObject(content);
// 默认向后延长1分钟
contentObject.put("time", getNextTime());
write(filePath, contentObject.toJSONString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}