定时读取ubuntu文件,读取内容后移动到备份。

main
CHINAMI-V47SHQD\EDY 2025-11-18 11:18:29 +08:00
parent bf1929bbc7
commit 1e4e4ea586
4 changed files with 259 additions and 0 deletions

View File

@ -23,6 +23,7 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
@ -291,4 +292,56 @@ public class DateUtil {
int comparison = date1.compareTo(date2);
return comparison;
}
/**
* yyyyMMddTimestamp
* 00:00:00.0
*
* @param dateStr yyyyMMdd"20250704"
* @return Timestampnull
* @throws DateTimeParseException yyyyMMdd
*/
public static Timestamp stringToTimestamp(String dateStr) throws DateTimeParseException {
// 校验输入参数
if (dateStr == null || dateStr.trim().isEmpty()) {
throw new IllegalArgumentException("输入字符串不能为空");
}
// 定义日期格式严格匹配yyyyMMdd
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
try {
// 解析为LocalDate仅日期
LocalDate localDate = LocalDate.parse(dateStr.trim(), formatter);
// 补充时间为00:00:00转换为LocalDateTime
LocalDateTime localDateTime = localDate.atStartOfDay();
// 转换为Timestamp
return Timestamp.valueOf(localDateTime);
} catch (DateTimeParseException e) {
// 抛出格式不匹配异常,包含具体错误信息
throw new DateTimeParseException("字符串格式错误需符合yyyyMMdd如20250704错误内容" + dateStr, dateStr, e.getErrorIndex(), e);
}
}
/**
* yyyyMMddhhmmss 12
* 24 "yyyyMMddHHmmss"HH24
*
* @return 202511170345222025-11-17 03:45:22
*/
public static String getCurrentTimeAsString() {
// 1. 获取当前时间(包含日期和时间)
LocalDateTime now = LocalDateTime.now();
// 2. 定义格式化模板yyyyMMddhhmmss12小时制
// 说明:
// - yyyy四位年份如2025
// - MM两位月份01-12
// - dd两位日期01-31
// - hh12小时制小时01-12
// - mm两位分钟00-59
// - ss两位秒数00-59
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
// 3. 格式化当前时间并返回
return now.format(formatter);
}
}

View File

@ -0,0 +1,38 @@
package com.youchain.utils.readFilebak;
import com.youchain.base.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
@Entity
@Data
@Table(name = "read_file_data")
public class ReadFileData extends BaseEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "`id`")
@ApiModelProperty(value = "id")
private Long id;
@Column(name = "`big_item_code`")
@ApiModelProperty(value = "机型")
private String bigItemCode;
@Column(name = "`area_code`")
@ApiModelProperty(value = "库区")
private String areaCode;
@Column(name = "`working_station`")
@ApiModelProperty(value = "工位")
private String workingStation;
@Column(name = "`downline_date`")
@ApiModelProperty(value = "下线日期")
private String downlineDate;
@Column(name = "`make_line`")
@ApiModelProperty(value = "制造线")
private String makeLine;
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.youchain.utils.readFilebak;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
/**
* @website https://eladmin.vip
* @author HJL
* @date 2023-08-14
**/
public interface ReadFileDataRepository extends JpaRepository<ReadFileData, Long>, JpaSpecificationExecutor<ReadFileData> {
}

View File

@ -0,0 +1,138 @@
package com.youchain.utils.readFilebak;
import com.youchain.utils.DateUtil;
import com.youchain.utils.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
@Component
public class ReadUbuntuFiles {
private static final String SOURCE_DIR = "/home/test";
// bak文件夹测试路径E:\test\bak
private static final Path BAK_DIR = Paths.get(SOURCE_DIR).resolve("bak");
@Autowired
private ReadFileDataRepository readFileDataRepository;
public ReadUbuntuFiles () {
System.out.println("定时读取ubuntu文件");
}
// 定时任务执行器
private ScheduledExecutorService scheduler;
@PostConstruct
public void init() {
// 初始化定时任务延迟0秒开始每次执行完间隔3秒
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleWithFixedDelay(
this::read, // 执行的任务调用read方法
0, // 首次执行延迟时间0秒后立即开始
5, // 上一次任务结束到下一次任务开始的间隔3秒
TimeUnit.SECONDS // 时间单位
);
System.out.println("定时任务已启动每次执行完间隔3秒");
}
// 业务逻辑:读取文件并处理
public void read() {
Path directory = Paths.get(SOURCE_DIR);
// 检查目录有效性
if (!Files.exists(directory)) {
System.err.println("目录不存在:" + SOURCE_DIR);
return;
}
if (!Files.isDirectory(directory)) {
System.err.println("路径不是目录:" + SOURCE_DIR);
return;
}
// 解析结果集
List<ReadFileData> readFileDataList=new ArrayList<>();
// 遍历目录下的文件并处理每行内容
try (Stream<Path> pathStream = Files.list(directory)) {
pathStream.filter(Files::isRegularFile)
.forEach(file -> {
System.out.println("\n===== 处理文件:" + file + " =====");
try {
// 读取文件所有行UTF-8编码
List<String> lines = Files.readAllLines(file, StandardCharsets.UTF_8);
// 遍历每行并处理
for (String line : lines) {
// 1. 去除首尾空格2. 将连续空格1个以上替换为单个空格
String processedLine = line.trim().replaceAll("\\s+", " ");
// 输出处理后的行
System.out.println(processedLine);
String[] processed = processedLine.split(" ");
// 校验格式,并写入结果集
ReadFileData readFileData=new ReadFileData();
readFileData.setBigItemCode(processed[0]);
readFileData.setAreaCode(processed[1]);
readFileData.setWorkingStation(processed[2]);
readFileData.setDownlineDate(processed[3]);
readFileData.setMakeLine(processed[4]);
readFileDataList.add(readFileData);
}
// 关键修改将当前处理的文件file移动到bak文件夹而非目录directory
moveToBakWithoutSubDir(file, DateUtil.getCurrentTimeAsString());
} catch (IOException e) {
System.err.println("处理文件失败:" + file + ",原因:" + e.getMessage());
}
});
} catch (IOException e) {
System.err.println("遍历目录失败:" + e.getMessage());
}
readFileDataRepository.saveAll(readFileDataList);
}
/**
* bak
* @param sourceFile
* @throws IOException
*/
public static void moveToBakWithoutSubDir(Path sourceFile, String key) throws IOException {
// 1. 构建bak文件夹路径源文件同级目录下的bak即E:\test\bak
Path parentDir = sourceFile.getParent();
if (parentDir == null) {
throw new IllegalArgumentException("源文件路径无效,无法获取父目录:" + sourceFile);
}
Path bakDir = parentDir.resolve("bak");
// 2. 确保bak文件夹存在
if (!Files.exists(bakDir)) {
Files.createDirectory(bakDir);
System.out.println("已创建bak文件夹" + bakDir);
}
// 3. 生成目标文件名(原文件名 + 时间后缀)
String originalFileName = sourceFile.getFileName().toString();
String safeFileName = originalFileName.replaceAll("[\\\\/]", "_");
String targetFileName = key+"_"+safeFileName;
// 4. 构建目标文件路径
Path targetFile = bakDir.resolve(targetFileName);
// 5. 移动文件(覆盖已存在的同名文件)
Files.move(
sourceFile,
targetFile,
StandardCopyOption.REPLACE_EXISTING
);
System.out.println("文件已移动至:" + targetFile);
}
}