省口腔同步逻辑修改

master
linjj 1 month ago
parent 7401fe1bee
commit 409dc0aa7b

@ -31,6 +31,8 @@
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId> <artifactId>springdoc-openapi-ui</artifactId>
@ -42,7 +44,7 @@
<dependency> <dependency>
<groupId>com.microsoft.sqlserver</groupId> <groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId> <artifactId>mssql-jdbc</artifactId>
<version>9.4.1.jre8</version> <version>6.4.0.jre8</version>
</dependency> </dependency>

@ -5,7 +5,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication @SpringBootApplication
@MapperScan("com.medical.record.mapper") // 扫描Mapper接口 @MapperScan("com.medical.record.dao") // 扫描Mapper接口
public class RecordSystemApplication { public class RecordSystemApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(RecordSystemApplication.class, args); SpringApplication.run(RecordSystemApplication.class, args);

@ -109,17 +109,6 @@ public class MedicalRecordHttpClient {
/* 把 XML 对象序列化成字符串 */ /* 把 XML 对象序列化成字符串 */
String xmlContent = xmlMapper.writeValueAsString(medicalRecordXml);
/* 保存到本地(可选,调试时打开) */
Path xmlPath = Paths.get("medicalRecord.xml"); // 可改成绝对路径
Files.write(xmlPath,
xmlContent.getBytes(StandardCharsets.UTF_8),
StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING);
//把 XML 对象序列化成字节数组,准备当“文件”传 */
byte[] xmlBytes = xmlMapper.writeValueAsBytes(medicalRecordXml); byte[] xmlBytes = xmlMapper.writeValueAsBytes(medicalRecordXml);
MultipartEntityBuilder builder = MultipartEntityBuilder.create(); MultipartEntityBuilder builder = MultipartEntityBuilder.create();
@ -131,32 +120,7 @@ public class MedicalRecordHttpClient {
ContentType.create("application/zip"), ContentType.create("application/zip"),
zipFile.getFileName().toString()); zipFile.getFileName().toString());
httpPost.setEntity(builder.build());
// 1. 先 build 实体
HttpEntity rawEntity = builder.build();
// 2. 包成可重复读实体,这样后面真正发请求时还能再用
BufferedHttpEntity bufferedEntity = new BufferedHttpEntity(rawEntity);
// 3. 输出到内存缓冲区
ByteArrayOutputStream buf = new ByteArrayOutputStream();
bufferedEntity.writeTo(buf); // 不会把流弄空
String multipartTxt = buf.toString(String.valueOf(StandardCharsets.UTF_8));
// 4. 用 log 打印slf4j 的 info 级别)
log.info("---------- multipart 原文本 ----------\n{}", multipartTxt);
// 5. 再放回请求,正常发
httpPost.setEntity(bufferedEntity);
// httpPost.setEntity(builder.build());
try (CloseableHttpResponse response = httpClient.execute(httpPost)) { try (CloseableHttpResponse response = httpClient.execute(httpPost)) {

@ -1,10 +1,13 @@
package com.medical.record.controller; package com.medical.record.controller;
import com.medical.record.client.MedicalRecordHttpClient; import com.medical.record.client.MedicalRecordHttpClient;
import com.medical.record.dao.CommomTableMapper;
import com.medical.record.dto.MedicalAttachmentFile; import com.medical.record.dto.MedicalAttachmentFile;
import com.medical.record.dto.MedicalRecordData; import com.medical.record.dto.MedicalRecordData;
import com.medical.record.dto.MedicalRecordException; import com.medical.record.dto.MedicalRecordException;
import com.medical.record.dto.MedicalRecordXml; import com.medical.record.dto.MedicalRecordXml;
import com.medical.record.entity.CommomTableVo;
import com.medical.record.entity.TscanAssort;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -18,6 +21,7 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.text.SimpleDateFormat;
@RestController @RestController
@RequestMapping("/api/record") @RequestMapping("/api/record")
@ -26,6 +30,11 @@ public class MedicalRecordController {
// 创建SLF4J Logger实例 // 创建SLF4J Logger实例
private static final Logger log = LoggerFactory.getLogger(MedicalRecordController.class); private static final Logger log = LoggerFactory.getLogger(MedicalRecordController.class);
@Autowired
private CommomTableMapper commomTableMapper;
// 定义格式化器
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/** /**
* *
@ -34,84 +43,122 @@ public class MedicalRecordController {
@PostMapping("/sync") @PostMapping("/sync")
@Operation(summary = "获取影像记录", description = "获取影像记录") @Operation(summary = "获取影像记录", description = "获取影像记录")
public String syncMedicalRecord(@RequestParam String accessKey) { public String syncMedicalRecord(@RequestParam String accessKey) {
Path zipFile = null;
try { try {
// 1. 初始化HTTP客户端 // 1. 初始化HTTP客户端
MedicalRecordHttpClient httpClient = new MedicalRecordHttpClient("http://172.16.1.133/emras"); MedicalRecordHttpClient httpClient = new MedicalRecordHttpClient("http://172.16.1.133/emras");
// 2. 获取SID
String sid = httpClient.getSid(accessKey); // 移除初始num查询直接初始化分页参数
log.info("sid:::::::::::::::::"+sid); int batchSize = 100;
// 3. 准备图像文件(实际业务中动态获取) int offset = 0;
int batch = 0;
// 无限循环,直到查询结果为空
while (true) {
List<CommomTableVo> commomTableVos = commomTableMapper.getPatientList(offset, batchSize);
// 无数据则终止循环
if (commomTableVos == null || commomTableVos.isEmpty()) {
log.info("无更多未同步患者数据,同步结束");
break;
}
batch++;
// 遍历处理当前批次数据
for (CommomTableVo vo : commomTableVos) {
try {
syncPatient(vo, httpClient, accessKey);
commomTableMapper.updateStaicByPatientId(vo.getPatientId(),"1");
} catch (Exception e) {
log.error("同步患者失败patientId: {}", vo.getPatientId(), e);
commomTableMapper.updateStaicByPatientId(vo.getPatientId(),"2");
}
}
log.info("第 {} 批处理完成,本批次 {} 条", batch, commomTableVos.size());
// 偏移量自增
offset += batchSize;
}
return "同步完成";
}catch (Exception e) {
log.error("未知异常: {}", e.getMessage(), e);
return "同步失败(未知异常): " + e.getMessage();
}
}
//同步患者逻辑
public void syncPatient(CommomTableVo CommomTableVo, MedicalRecordHttpClient httpClient,String accessKey) throws Exception {
Path zipFile = null;
// 2. 获取SID
String sid = httpClient.getSid(accessKey);
try {
// 查询患者文件信息
List<TscanAssort> tscanAssorts = commomTableMapper.getTscanAssort(CommomTableVo.getPatientId());
List<Path> imagePaths = new ArrayList<>(); List<Path> imagePaths = new ArrayList<>();
imagePaths.add(Paths.get("D:/test/image1.jpg"));
imagePaths.add(Paths.get("D:/test/image2.jpg")); // 添加图像路径到图像路径集合中
// 4. 打包成ZIP for (TscanAssort tscanAssort : tscanAssorts) {
imagePaths.add(Paths.get(CommomTableVo.getFilePath() + "\\" + tscanAssort.getScanPage()));
}
// 打包成ZIP
zipFile = Paths.get("D:/temp/upload_" + System.currentTimeMillis() + ".zip"); zipFile = Paths.get("D:/temp/upload_" + System.currentTimeMillis() + ".zip");
MedicalRecordHttpClient.packageImagesToZip(imagePaths, zipFile); MedicalRecordHttpClient.packageImagesToZip(imagePaths, zipFile);
// 5. 构建附件信息 // 构建附件信息
List<MedicalAttachmentFile> fileList = new ArrayList<>(); List<MedicalAttachmentFile> fileList = new ArrayList<>();
for (Path img : imagePaths) { for (int i = 0; i < imagePaths.size(); i++) {
MedicalAttachmentFile file = new MedicalAttachmentFile(); MedicalAttachmentFile file = new MedicalAttachmentFile();
file.setFileName(img.getFileName().toString()); file.setFileName(imagePaths.get(i).getFileName().toString());
file.setFileSize(Files.size(img)); file.setFileSize(Files.size(imagePaths.get(i)));
file.setFileSuffix(getExtension(img)); file.setFileSuffix(getExtension(imagePaths.get(i)));
file.setMd5(MedicalRecordHttpClient.calculateMD5(img)); file.setMd5(MedicalRecordHttpClient.calculateMD5(imagePaths.get(i)));
file.setCatalogue("病历首页"); file.setCatalogue(tscanAssorts.get(i).getAssortName());
file.setCatalogueId("C6A8308D842B450FB9FA0D21762237AB"); file.setCatalogueId(tscanAssorts.get(i).getAssortId());
file.setCode("CODE_" + System.currentTimeMillis()); file.setCode("CODE_" + System.currentTimeMillis());
file.setTimeStapPrice(String.valueOf(System.currentTimeMillis())); file.setTimeStapPrice(String.valueOf(System.currentTimeMillis()));
fileList.add(file); fileList.add(file);
} }
// 6. 构建病人信息 // 构建病人信息
MedicalRecordData data = new MedicalRecordData(); MedicalRecordData data = new MedicalRecordData();
data.setNumber("BA" + System.currentTimeMillis()); data.setNumber(CommomTableVo.getInpatientNo());
data.setSickName("测试患者"); data.setSickName(CommomTableVo.getName());
data.setSerialNumber("SN" + System.currentTimeMillis()); data.setSerialNumber(CommomTableVo.getPatientId());
data.setInHospitalNumber(1); data.setInHospitalNumber(CommomTableVo.getAdmissTimes());
data.setInSection("影像科"); data.setInSection("口腔颌面外科病房");
data.setInSectionId(" "); data.setInSectionId("668279670cda953360c1af33");
data.setOutSection("影像科"); data.setOutSection("口腔颌面外科病房");
data.setOutSectionId(" "); data.setOutSectionId("668279670cda953360c1af33");
data.setAttendingPhysician(" "); data.setAttendingPhysician(" ");
data.setAttendingPhysicianId(" "); data.setAttendingPhysicianId(" ");
data.setIdentityCard(" "); data.setIdentityCard(" ");
data.setInHospitalDate("2024-01-20 08:00:00"); if (CommomTableVo.getAdmissDate() == null || CommomTableVo.getAdmissDate().equals("")){
data.setOutHospitalDate("2024-01-20 10:30:00"); data.setInHospitalDate(" ");
} else {
// 如果是 Date 类型
data.setInHospitalDate(DATE_FORMAT.format(CommomTableVo.getAdmissDate()));
}
// 7. 构建XML对象 if (CommomTableVo.getDisDate() == null || CommomTableVo.getDisDate().equals("")){
MedicalRecordXml xml = data.setOutHospitalDate(" ");
new MedicalRecordXml(fileList, data); } else {
data.setOutHospitalDate(DATE_FORMAT.format(CommomTableVo.getDisDate()));
}
// 8. 上传第三方系统
String recordId = httpClient.uploadMedicalRecord(sid, xml, zipFile);
// 构建XML对象
MedicalRecordXml xml = new MedicalRecordXml(fileList, data);
// 9 清理临时文件 // 上传第三方系统
String recordId = httpClient.uploadMedicalRecord(sid, xml, zipFile);
Files.deleteIfExists(zipFile); Files.deleteIfExists(zipFile);
} finally {
return "同步成功病案ID: " + recordId; // 确保临时文件被清理(无论是否发生异常)
} catch (MedicalRecordException e) {
log.error("业务异常: {}", e.getMessage(), e);
return "同步失败(业务异常): " + e.getMessage();
} catch (IOException e) {
log.error("IO异常: {}", e.getMessage(), e);
return "同步失败IO异常: " + e.getMessage();
} catch (Exception e) {
log.error("未知异常: {}", e.getMessage(), e);
return "同步失败(未知异常): " + e.getMessage();
}
finally {
if (zipFile != null) { if (zipFile != null) {
try { try {
Files.deleteIfExists(zipFile); Files.deleteIfExists(zipFile);
log.debug("临时文件在finally中已清理"); log.debug("临时文件已清理: {}", zipFile);
} catch (IOException e) { } catch (Exception e) {
log.warn("清理临时文件失败: {}", e.getMessage()); log.warn("清理临时文件失败: {}", zipFile, e);
} }
} }
} }

@ -0,0 +1,46 @@
package com.medical.record.dao;
import com.medical.record.entity.CommomTableVo;
import com.medical.record.entity.TscanAssort;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @ClassName CommomTableMapper
* @Description
* @Author linjj
* @Date 2026/2/4 15:16
* @Version 1.0
*/
@Mapper
public interface CommomTableMapper {
/**
* @Author: linjj
* @Description:
* @DateTime: 2026/2/4 15:18
* @Return Integer
*/
Integer getNum();
/**
* @Author: linjj
* @Description:
* @DateTime: 2026/2/4 15:38
* @Params: [offset, limit]
* @Return java.util.List<com.medical.record.entity.CommomTableVo>
*/
List<CommomTableVo> getPatientList(@Param("offset") int offset, @Param("limit") int limit);
/**
* @Author: linjj
* @Description:
* @DateTime: 2026/2/4 15:39
* @Params: [PatientId]
* @Return java.util.List<com.medical.record.entity.TscanAssort>
*/
List<TscanAssort> getTscanAssort(String PatientId);
boolean updateStaicByPatientId(@Param("PatientId") String PatientId,@Param("flag") String flag);
}

@ -0,0 +1,35 @@
package com.medical.record.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* @ClassName commomtable
* @Description
* @Author linjj
* @Date 2026/2/4 15:03
* @Version 1.0
*/
@Data
@TableName("commontable")
public class CommomTableVo {
//流水号
private String patientId;
//住院号
private String inpatientNo;
//患者姓名
private String name;
//住院次数
private Integer admissTimes;
//出院时间
private Date disDate;
//入院时间
private Date admissDate;
//路径
private String filePath;
}

@ -0,0 +1,22 @@
package com.medical.record.entity;
import lombok.Data;
/**
* @ClassName TscanAssort
* @Description
* @Author linjj
* @Date 2026/2/4 15:37
* @Version 1.0
*/
@Data
public class TscanAssort {
//文件名称
private String scanPage;
//分段id
private String assortId;
//分段名称
private String assortName;
}

@ -1,19 +1,27 @@
server: server:
port: 8891 port: 8891
spring: spring:
datasource: datasource:
# 2008 R2 驱动类6.4.0驱动还是这个,无需改)
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
url: jdbc:sqlserver://localhost:1433;databaseName=medical_record_db;encrypt=true;trustServerCertificate=true; # 上面的最简URL替换IP/库名
username: SA url: jdbc:sqlserver://127.0.0.1:1433;databaseName=record;loginTimeout=30;sendStringParametersAsUnicode=false
password: YourStrong@Passw0rd username: sa
password: docus@702
hikari: hikari:
minimum-idle: 5 pool-name: HikariPool-medical
maximum-pool-size: 15 minimum-idle: 3 # 2008 R2不建议设太高3-5即可避免过多空闲连接
auto-commit: true maximum-pool-size: 10 # 最大连接数2008 R2性能有限建议10-20别超过30
connection-timeout: 30000 idle-timeout: 300000 # 空闲超时5分钟核心2008 R2默认空闲10分钟断开这里设5分钟提前剔除
idle-timeout: 300000 max-lifetime: 1200000 # 连接最大生命周期20分钟必须小于idle-timeout且小于数据库超时
max-lifetime: 1200000 connection-timeout: 30000 # 获取连接超时30秒
validation-timeout: 5000 # 连接校验超时5秒
test-on-borrow: true # 获取连接时校验2008 R2必须开兜底
test-while-idle: true # 空闲后台校验(核心,自动清失效连接)
time-between-eviction-runs-millis: 60000 # 后台校验间隔1分钟高频检查
connection-test-query: SELECT 1 # 2008 R2支持的最简校验语句高效无副作用
# MyBatis-Plus配置 # MyBatis-Plus配置
mybatis-plus: mybatis-plus:

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.medical.record.dao.CommomTableMapper">
<update id="updateStaicByPatientId">
UPDATE commomtable set static=#{flag} WHERE patient_id=#{PatientId}
</update>
<select id="getNum" resultType="java.lang.Integer">
SELECT COUNT(*) FROM commomtable WHERE static='0'
</select>
<select id="getPatientList" resultType="com.medical.record.entity.CommomTableVo">
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY patient_id) as row_num
FROM commomtable
WHERE static = '0'
) t
WHERE t.row_num BETWEEN (#{offset} + 1) AND (#{offset} + #{limit})
</select>
<select id="getTscanAssort" resultType="com.medical.record.entity.TscanAssort">
SELECT
t.scan_page,z.assort_id,z.assort_name
FROM
t_scan_assort t
LEFT JOIN zd_assort z ON z.assort_id=t.assort_id
WHERE
patient_id = #{patientId}
ORDER BY assort_sort
</select>
</mapper>

@ -1,13 +1,296 @@
package com.medical.record; package com.medical.record;
import org.apache.tomcat.jni.FileInfo;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
@SpringBootTest @SpringBootTest
class RecordSystemApplicationTests { class RecordSystemApplicationTests {
// 图片文件扩展名
private static final Set<String> IMAGE_EXTENSIONS = new HashSet<>(Arrays.asList(
"jpg", "jpeg", "tif", "tiff"
));
// 存储结果
private int jpgCount = 0;
private int tifCount = 0;
private int otherCount = 0;
private List<FileInfo> jpgFiles = new ArrayList<>();
private List<FileInfo> tifFiles = new ArrayList<>();
private List<FileInfo> otherFiles = new ArrayList<>();
// 文件信息类
static class FileInfo {
String path;
String detectedFormat;
String extension;
long size;
FileInfo(String path, String detectedFormat, String extension, long size) {
this.path = path;
this.detectedFormat = detectedFormat;
this.extension = extension;
this.size = size;
}
}
/**
*
*/
public void checkDirectory(String directoryPath) throws IOException {
Path startPath = Paths.get(directoryPath);
if (!Files.exists(startPath)) {
throw new IOException("目录不存在: " + directoryPath);
}
if (!Files.isDirectory(startPath)) {
throw new IOException("指定路径不是目录: " + directoryPath);
}
System.out.println("开始扫描目录: " + startPath.toAbsolutePath());
System.out.println("==========================================");
// 遍历目录
Files.walkFileTree(startPath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
String fileName = file.getFileName().toString().toLowerCase();
// 检查是否是图片文件(根据扩展名初步筛选)
String extension = getExtension(fileName);
if (IMAGE_EXTENSIONS.contains(extension)) {
analyzeImage(file.toFile(), extension);
}
return FileVisitResult.CONTINUE;
}
});
printSummary();
}
/**
*
*/
private String getExtension(String fileName) {
int lastDot = fileName.lastIndexOf('.');
return (lastDot > 0) ? fileName.substring(lastDot + 1) : "";
}
/**
*
*/
private void analyzeImage(File file, String extension) {
String detectedFormat = detectRealFormat(file);
long size = file.length();
String path = file.getAbsolutePath();
FileInfo info = new FileInfo(path, detectedFormat, extension, size);
// 根据检测到的真实格式分类
switch (detectedFormat.toUpperCase()) {
case "JPEG":
case "JPG":
jpgFiles.add(info);
jpgCount++;
break;
case "TIFF":
case "TIF":
tifFiles.add(info);
tifCount++;
break;
default:
otherFiles.add(info);
otherCount++;
break;
}
}
/**
* Magic Number
*/
private String detectRealFormat(File file) {
try (FileInputStream fis = new FileInputStream(file)) {
byte[] header = new byte[8];
int read = fis.read(header);
if (read < 4) return "UNKNOWN";
// 检查 JPEG: FF D8 FF
if ((header[0] & 0xFF) == 0xFF &&
(header[1] & 0xFF) == 0xD8 &&
(header[2] & 0xFF) == 0xFF) {
return "JPEG";
}
// 检查 TIFF: 49 49 2A 00 (小端) 或 4D 4D 00 2A (大端)
if (((header[0] & 0xFF) == 0x49 && (header[1] & 0xFF) == 0x49 &&
(header[2] & 0xFF) == 0x2A && (header[3] & 0xFF) == 0x00) ||
((header[0] & 0xFF) == 0x4D && (header[1] & 0xFF) == 0x4D &&
(header[2] & 0xFF) == 0x00 && (header[3] & 0xFF) == 0x2A)) {
return "TIFF";
}
// 检查 PNG: 89 50 4E 47
if ((header[0] & 0xFF) == 0x89 &&
(header[1] & 0xFF) == 0x50 &&
(header[2] & 0xFF) == 0x4E &&
(header[3] & 0xFF) == 0x47) {
return "PNG";
}
// 检查 GIF: 47 49 46 38
if ((header[0] & 0xFF) == 0x47 &&
(header[1] & 0xFF) == 0x49 &&
(header[2] & 0xFF) == 0x46 &&
(header[3] & 0xFF) == 0x38) {
return "GIF";
}
// 检查 BMP: 42 4D
if ((header[0] & 0xFF) == 0x42 &&
(header[1] & 0xFF) == 0x4D) {
return "BMP";
}
// 检查 WebP: 52 49 46 46 ... 57 45 42 50
if ((header[0] & 0xFF) == 0x52 &&
(header[1] & 0xFF) == 0x49 &&
(header[2] & 0xFF) == 0x46 &&
(header[3] & 0xFF) == 0x46) {
byte[] extra = new byte[4];
if (fis.skip(4) == 4 && fis.read(extra) == 4) {
if (extra[0] == 0x57 && extra[1] == 0x45 &&
extra[2] == 0x42 && extra[3] == 0x50) {
return "WEBP";
}
}
return "RIFF";
}
return "UNKNOWN";
} catch (IOException e) {
return "ERROR: " + e.getMessage();
}
}
/**
*
*/
private void printSummary() {
System.out.println("\n========== 扫描结果汇总 ==========");
System.out.printf("JPEG/JPG 文件: %d 个%n", jpgCount);
System.out.printf("TIFF/TIF 文件: %d 个%n", tifCount);
System.out.printf("其他格式文件: %d 个%n", otherCount);
System.out.printf("总计: %d 个文件%n", jpgCount + tifCount + otherCount);
System.out.println("==================================\n");
// 打印详细信息
if (!jpgFiles.isEmpty()) {
System.out.println("【JPEG/JPG 文件列表】");
printFileList(jpgFiles);
}
if (!tifFiles.isEmpty()) {
System.out.println("【TIFF/TIF 文件列表】");
printFileList(tifFiles);
}
if (!otherFiles.isEmpty()) {
System.out.println("【其他格式/异常文件列表】");
printFileList(otherFiles);
}
// 检查扩展名与实际格式不匹配的情况
checkMismatch();
}
/**
*
*/
private void printFileList(List<FileInfo> files) {
for (FileInfo info : files) {
System.out.printf(" %s%n", info.path);
System.out.printf(" 实际格式: %s | 扩展名: .%s | 大小: %s%n",
info.detectedFormat, info.extension, formatFileSize(info.size));
}
System.out.println();
}
/**
*
*/
private void checkMismatch() {
System.out.println("【扩展名与实际格式不匹配警告】");
boolean hasMismatch = false;
List<FileInfo> allFiles = new ArrayList<>();
allFiles.addAll(jpgFiles);
allFiles.addAll(tifFiles);
allFiles.addAll(otherFiles);
for (FileInfo info : allFiles) {
String ext = info.extension.toUpperCase();
String real = info.detectedFormat.toUpperCase();
boolean mismatch = false;
if (ext.equals("JPG") || ext.equals("JPEG")) {
if (!real.equals("JPEG") && !real.equals("JPG")) mismatch = true;
} else if (ext.equals("TIF") || ext.equals("TIFF")) {
if (!real.equals("TIFF") && !real.equals("TIF")) mismatch = true;
}
if (mismatch) {
System.out.printf(" ⚠️ %s%n", info.path);
System.out.printf(" 扩展名: .%s, 实际格式: %s%n", info.extension, info.detectedFormat);
hasMismatch = true;
}
}
if (!hasMismatch) {
System.out.println(" ✓ 未发现不匹配情况");
}
System.out.println();
}
/**
*
*/
private String formatFileSize(long size) {
if (size < 1024) return size + " B";
if (size < 1024 * 1024) return String.format("%.2f KB", size / 1024.0);
if (size < 1024 * 1024 * 1024) return String.format("%.2f MB", size / (1024.0 * 1024));
return String.format("%.2f GB", size / (1024.0 * 1024 * 1024));
}
@Test @Test
void contextLoads() { void contextLoads() {
try {
checkDirectory("E:\\tmp");
} catch (IOException e) {
System.err.println("错误: " + e.getMessage());
System.exit(1);
}
} }
} }

Loading…
Cancel
Save