定时读取ubuntu文件,读取内容后移动到备份。
parent
bf1929bbc7
commit
1e4e4ea586
|
|
@ -23,6 +23,7 @@ import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
@ -291,4 +292,56 @@ public class DateUtil {
|
||||||
int comparison = date1.compareTo(date2);
|
int comparison = date1.compareTo(date2);
|
||||||
return comparison;
|
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