定时读取ubuntu文件,读取内容后移动到备份。
parent
bf1929bbc7
commit
1e4e4ea586
|
|
@ -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;
|
||||
}
|
||||
/**
|
||||
* 将yyyyMMdd格式的字符串转换为Timestamp
|
||||
* 转换后时间默认为00:00:00.0
|
||||
*
|
||||
* @param dateStr 输入字符串,格式必须为yyyyMMdd(如"20250704")
|
||||
* @return 转换后的Timestamp,若解析失败返回null
|
||||
* @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"(HH表示24小时制)
|
||||
*
|
||||
* @return 格式化后的时间字符串(如20251117034522,对应2025-11-17 03:45:22)
|
||||
*/
|
||||
public static String getCurrentTimeAsString() {
|
||||
// 1. 获取当前时间(包含日期和时间)
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
// 2. 定义格式化模板:yyyyMMddhhmmss(12小时制)
|
||||
// 说明:
|
||||
// - yyyy:四位年份(如2025)
|
||||
// - MM:两位月份(01-12)
|
||||
// - dd:两位日期(01-31)
|
||||
// - hh:12小时制小时(01-12)
|
||||
// - mm:两位分钟(00-59)
|
||||
// - ss:两位秒数(00-59)
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
||||
|
||||
// 3. 格式化当前时间并返回
|
||||
return now.format(formatter);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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> {
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue