目前对这个文件的操作,我觉得得有专门的一个自己很熟练的工具来使用,目前为止,我觉得应该集多家的文件处理Util所长为自己所用
    apache.common 里面的工具,还有就是spring中的工具,还有就是自己本身的一些工具
    所有的这些工具都给自己

    1. <dependency>
    2. <groupId>org.quartz-scheduler</groupId>
    3. <artifactId>quartz</artifactId>
    4. <version>2.3.1</version>
    5. </dependency>

    1.创建文件
    2.文件内容添加
    3.文件迭代创建
    4.本机的文件加锁

    其中本机的文件锁其实必要性不是很大,因为通常情况下就直接采用分布式锁就可以了

    场景:
    1.单机多进程,竞争同一个资源

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONObject;
    3. import com.isyscore.isc.neo.NeoMap;
    4. import lombok.experimental.UtilityClass;
    5. import lombok.extern.slf4j.Slf4j;
    6. import org.apache.commons.lang3.StringUtils;
    7. import org.apache.commons.lang3.time.DateUtils;
    8. import org.quartz.*;
    9. import java.io.*;
    10. import java.lang.management.ManagementFactory;
    11. import java.net.HttpURLConnection;
    12. import java.net.URL;
    13. import java.nio.charset.Charset;
    14. import java.nio.charset.StandardCharsets;
    15. import java.nio.file.Files;
    16. import java.util.ArrayList;
    17. import java.util.Date;
    18. import java.util.List;
    19. import java.util.Objects;
    20. import java.util.stream.Stream;
    21. /**
    22. * @author shizi
    23. * @since 2019/12/3 11:48 上午
    24. */
    25. @Slf4j
    26. @UtilityClass
    27. public class FileUtil {
    28. private Charset CRYPTO_CHARSET = StandardCharsets.UTF_8;
    29. private static SchedulerFactory schedulerFactory = new org.quartz.impl.StdSchedulerFactory();
    30. private static Scheduler scheduler;
    31. static {
    32. try {
    33. scheduler = schedulerFactory.getScheduler();
    34. scheduler.start();
    35. } catch (SchedulerException e) {
    36. e.printStackTrace();
    37. }
    38. }
    39. /**
    40. * 获取文件
    41. */
    42. public File getFile(String fileName) throws IOException {
    43. File file = new File(fileName);
    44. if (!file.getParentFile().exists()) {
    45. file.getParentFile().mkdirs();
    46. }
    47. if (!file.exists()) {
    48. file.createNewFile();
    49. }
    50. file.setReadable(true);
    51. file.setWritable(true);
    52. return file;
    53. }
    54. /**
    55. * 获取文件夹类型的文件
    56. */
    57. public File getDirectFile(String fileName) {
    58. File file = new File(fileName);
    59. if (!file.getParentFile().exists()) {
    60. file.getParentFile().mkdirs();
    61. }
    62. if (!file.exists()) {
    63. file.mkdir();
    64. }
    65. file.setReadable(true);
    66. file.setWritable(true);
    67. return file;
    68. }
    69. @SuppressWarnings("all")
    70. public Boolean createFile(String fileName) throws IOException {
    71. File file = new File(fileName);
    72. if (!file.getParentFile().exists()) {
    73. file.getParentFile().mkdirs();
    74. }
    75. if (!file.exists() && file.createNewFile()) {
    76. return file.setReadable(true) && file.setWritable(true);
    77. }
    78. return false;
    79. }
    80. public Boolean exist(String fileFullPath){
    81. File file = new File(fileFullPath);
    82. return file.exists();
    83. }
    84. /**
    85. * 向文件中写入对应的文件
    86. */
    87. public void writeFile(File file, String content) throws IOException {
    88. try (FileOutputStream outputStream = new FileOutputStream(file)) {
    89. outputStream.write(content.getBytes(CRYPTO_CHARSET));
    90. outputStream.flush();
    91. }
    92. }
    93. public void writeFile(String file, String content) throws IOException {
    94. try (FileOutputStream outputStream = new FileOutputStream(new File(file))) {
    95. outputStream.write(content.getBytes(CRYPTO_CHARSET));
    96. outputStream.flush();
    97. }
    98. }
    99. public BufferedReader readFile(File file) throws IOException {
    100. return Files.newBufferedReader(file.toPath(), CRYPTO_CHARSET);
    101. }
    102. public String readFromFile(File file) throws IOException {
    103. StringBuilder stringBuilder = new StringBuilder();
    104. try (BufferedReader bufferedReader = readFile(file)) {
    105. String line;
    106. while ((line = bufferedReader.readLine()) != null) {
    107. stringBuilder.append(line).append("\n");
    108. }
    109. }
    110. return stringBuilder.toString();
    111. }
    112. /**
    113. * 读取资源文件中的内容
    114. * @param cls 类所在的位置
    115. * @param resourceFileName 资源文件中的位置比如:/script/base.groovy,其中前面一定要有"/"
    116. * @return 文件的字符数据
    117. */
    118. public String readFromResource(Class cls, String resourceFileName) throws IOException {
    119. StringBuilder stringBuilder = new StringBuilder();
    120. InputStream inputStream = cls.getResourceAsStream(resourceFileName);
    121. BufferedReader bufferedReader = null;
    122. try {
    123. bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    124. String line;
    125. while ((line = bufferedReader.readLine()) != null) {
    126. stringBuilder.append(line).append("\n");
    127. }
    128. } finally {
    129. inputStream.close();
    130. assert bufferedReader != null;
    131. bufferedReader.close();
    132. }
    133. return stringBuilder.toString();
    134. }
    135. /**
    136. * 通过文件的绝对路径读取文件信息
    137. */
    138. public String read(String filePath) throws IOException {
    139. FileReader fileReader;
    140. StringBuilder stringBuilder = new StringBuilder();
    141. fileReader = new FileReader(filePath);
    142. char[] cbuf = new char[32];
    143. int hasRead = 0;
    144. while ((hasRead = fileReader.read(cbuf)) > 0) {
    145. stringBuilder.append(cbuf, 0, hasRead);
    146. }
    147. return stringBuilder.toString();
    148. }
    149. public FileInputStream readToStream(String filePath) throws IOException {
    150. File file = new File(filePath);
    151. if (file.exists()) {
    152. return new FileInputStream(file);
    153. }
    154. return null;
    155. }
    156. /**
    157. * 向绝对路径中的文件写入对应的数据信息
    158. */
    159. public void write(String filePath, String content) throws IOException {
    160. writeFile(getFile(filePath), content);
    161. }
    162. public String readUrl(String FileName) throws IOException {
    163. String read;
    164. StringBuilder stringBuilder = new StringBuilder();
    165. try {
    166. URL url = new URL(FileName);
    167. HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();
    168. urlCon.setConnectTimeout(5000);
    169. urlCon.setReadTimeout(5000);
    170. BufferedReader br = new BufferedReader(new InputStreamReader(urlCon.getInputStream()));
    171. while ((read = br.readLine()) != null) {
    172. stringBuilder.append(read);
    173. }
    174. br.close();
    175. } catch (IOException e) {
    176. }
    177. return stringBuilder.toString();
    178. }
    179. public void appendFile(String filePath, List<String> content) {
    180. FileWriter fw = null;
    181. if (content == null || content.isEmpty()) {
    182. return;
    183. }
    184. try {
    185. //如果文件存在,则追加内容;如果文件不存在,则创建文件
    186. File file = getFile(filePath);
    187. if ((!file.exists()) &&
    188. (!file.createNewFile())) {
    189. throw new IOException("create file '" + filePath +
    190. "' failure.");
    191. }
    192. fw = new FileWriter(file, true);
    193. PrintWriter pw = new PrintWriter(fw);
    194. for (String str : content) {
    195. if(str != null && !"".equals(str)) {
    196. pw.println(str);
    197. }
    198. }
    199. pw.flush();
    200. fw.flush();
    201. pw.close();
    202. fw.close();
    203. } catch (IOException e) {
    204. e.printStackTrace();
    205. }
    206. }
    207. public void appendFile(String filePath, String content) {
    208. List<String> contents = new ArrayList<>();
    209. contents.add(content);
    210. appendFile(filePath, contents);
    211. }
    212. public boolean delete(String filePath) {
    213. return delete(new File(filePath));
    214. }
    215. public boolean delete(File file) {
    216. if (null == file || !file.exists()) {
    217. return false;
    218. }
    219. if (file.isFile()) {
    220. return file.delete();
    221. } else {
    222. File[] childFile = file.listFiles();
    223. if (null == childFile) {
    224. return false;
    225. }
    226. for (File fileMeta : childFile) {
    227. delete(fileMeta);
    228. }
    229. }
    230. return file.delete();
    231. }
    232. /**
    233. * 文件加锁
    234. * <p>
    235. * <ul>
    236. * <li>1.可重入</li>
    237. * <li>2.锁有过期时间</li>
    238. * <li>3.自动延长过期时间</li>
    239. * </ul>
    240. *
    241. * @param lockFile 加锁对应的文件的路径
    242. * @return true:加锁成功,false:加锁失败
    243. */
    244. public boolean lock(String lockFile) {
    245. try {
    246. File compressLock = new File(lockFile);
    247. if (compressLock.isDirectory()) {
    248. return false;
    249. }
    250. String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
    251. String tid = String.valueOf(Thread.currentThread().getId());
    252. if (!compressLock.exists() && null != getFile(lockFile)) {
    253. NeoMap dataMap = NeoMap.of();
    254. dataMap.put("time", DateUtils.addMinutes(new Date(), -1).getTime());
    255. dataMap.put("pid", pid);
    256. dataMap.put("tid", tid);
    257. writeFile(compressLock, JSON.toJSONString(dataMap));
    258. startDelayThread(lockFile);
    259. return true;
    260. } else {
    261. String lockData = readFromFile(compressLock);
    262. JSONObject dataMap = JSONObject.parseObject(lockData);
    263. if (null == dataMap) {
    264. return false;
    265. }
    266. // 锁可重入
    267. if (dataMap.containsKey("pid") && dataMap.containsKey("tid")) {
    268. String pidCache = dataMap.getString("pid");
    269. String tidCache = dataMap.getString("tid");
    270. if (!StringUtils.isEmpty(pidCache) && pidCache.equals(pid) && !StringUtils.isEmpty(tidCache) && tidCache.equals(tid)) {
    271. // 重入后,顺便更新下下次时间
    272. dataMap.put("time", getNextTime());
    273. writeFile(compressLock, JSON.toJSONString(dataMap));
    274. return true;
    275. }
    276. }
    277. if (dataMap.containsKey("time")) {
    278. Long timeLong = dataMap.getLong("time");
    279. if (timeLong < System.currentTimeMillis()) {
    280. // 锁过期,则重新占有
    281. if (createFile(lockFile + "_lock")) {
    282. dataMap.put("time", getNextTime());
    283. dataMap.put("pid", pid);
    284. dataMap.put("tid", tid);
    285. writeFile(compressLock, JSON.toJSONString(dataMap));
    286. delete(lockFile + "_lock");
    287. return true;
    288. }
    289. return false;
    290. }
    291. }
    292. }
    293. } catch (IOException e) {
    294. log.error("lock exception", e);
    295. return false;
    296. }
    297. return false;
    298. }
    299. /**
    300. * 启动延期保护线程,20秒执行一次,每次向后默认延长1分钟
    301. */
    302. private void startDelayThread(String filePath) {
    303. try {
    304. JobDetail job = JobBuilder.newJob(InnerJob.class).withIdentity(new JobKey(filePath)).usingJobData("filePath", filePath).build();
    305. Trigger trigger = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(30)).build();
    306. scheduler.scheduleJob(job, trigger);
    307. } catch (SchedulerException e) {
    308. e.printStackTrace();
    309. }
    310. }
    311. /**
    312. * 关闭延期保护线程
    313. */
    314. private void closeDelayThread(String filePath) {
    315. try {
    316. scheduler.deleteJob(new JobKey(filePath));
    317. } catch (SchedulerException e) {
    318. e.printStackTrace();
    319. }
    320. }
    321. private Long getNextTime() {
    322. return DateUtils.addMinutes(new Date(), 1).getTime();
    323. }
    324. public boolean unlock(String lockFile) {
    325. File compressLock = new File(lockFile);
    326. if (compressLock.isDirectory()) {
    327. return false;
    328. }
    329. String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
    330. String tid = String.valueOf(Thread.currentThread().getId());
    331. try {
    332. String lockData = readFromFile(compressLock);
    333. JSONObject dataMap = JSONObject.parseObject(lockData);
    334. if (null == dataMap) {
    335. return false;
    336. }
    337. if (dataMap.containsKey("pid") && dataMap.containsKey("tid")) {
    338. String pidCache = dataMap.getString("pid");
    339. String tidCache = dataMap.getString("tid");
    340. // 保证删除的是自己的
    341. if (!StringUtils.isEmpty(pidCache) && pidCache.equals(pid) && !StringUtils.isEmpty(tidCache) && tidCache.equals(tid)) {
    342. closeDelayThread(lockFile);
    343. return compressLock.delete();
    344. }
    345. }
    346. } catch (IOException e) {
    347. e.printStackTrace();
    348. }
    349. return false;
    350. }
    351. public class InnerJob implements Job {
    352. public InnerJob() {}
    353. @Override
    354. public void execute(JobExecutionContext context) {
    355. String filePath = context.getJobDetail().getJobDataMap().getString("filePath");
    356. try {
    357. if (!exist(filePath)) {
    358. return;
    359. }
    360. String content = read(filePath);
    361. JSONObject contentObject = JSONObject.parseObject(content);
    362. // 默认向后延长1分钟
    363. contentObject.put("time", getNextTime());
    364. write(filePath, contentObject.toJSONString());
    365. } catch (IOException e) {
    366. e.printStackTrace();
    367. }
    368. }
    369. }
    370. }