本文目录导读:

我来为您提供几个Java实现数据归档的实用案例。
基础文件归档案例(使用ZIP压缩)
import java.io.*;
import java.nio.file.*;
import java.util.zip.*;
public class FileArchiveDemo {
/**
* 将文件夹压缩成ZIP归档文件
*/
public static void archiveToZip(String sourceDirPath, String zipFilePath)
throws IOException {
Path sourceDir = Paths.get(sourceDirPath);
Path zipFile = Paths.get(zipFilePath);
try (ZipOutputStream zos = new ZipOutputStream(
new FileOutputStream(zipFile.toFile()))) {
Files.walk(sourceDir)
.filter(path -> !Files.isDirectory(path))
.forEach(path -> {
ZipEntry zipEntry = new ZipEntry(
sourceDir.relativize(path).toString());
try {
zos.putNextEntry(zipEntry);
Files.copy(path, zos);
zos.closeEntry();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
}
}
/**
* 解压ZIP归档文件
*/
public static void extractFromZip(String zipFilePath, String destDirPath)
throws IOException {
Path destDir = Paths.get(destDirPath);
Files.createDirectories(destDir);
try (ZipInputStream zis = new ZipInputStream(
new FileInputStream(zipFilePath))) {
ZipEntry zipEntry;
while ((zipEntry = zis.getNextEntry()) != null) {
Path newFilePath = destDir.resolve(zipEntry.getName());
if (zipEntry.isDirectory()) {
Files.createDirectories(newFilePath);
} else {
Files.createDirectories(newFilePath.getParent());
Files.copy(zis, newFilePath,
StandardCopyOption.REPLACE_EXISTING);
}
zis.closeEntry();
}
}
}
public static void main(String[] args) {
try {
// 归档示例
archiveToZip("/data/source", "/backup/data_2024_01_01.zip");
System.out.println("归档成功");
// 解压示例
extractFromZip("/backup/data_2024_01_01.zip", "/data/restore");
System.out.println("解压成功");
} catch (IOException e) {
e.printStackTrace();
}
}
}
数据库数据归档案例
import java.sql.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
public class DatabaseArchiveDemo {
private Connection sourceConn;
private Connection archiveConn;
public DatabaseArchiveDemo(Connection source, Connection archive) {
this.sourceConn = source;
this.archiveConn = archive;
}
/**
* 归档旧数据
*/
public int archiveOldData(String tableName, int daysOld) throws SQLException {
String selectSQL = String.format(
"SELECT * FROM %s WHERE create_date < ?", tableName);
String insertSQL = String.format(
"INSERT INTO %s_archive SELECT * FROM %s WHERE create_date < ?",
tableName, tableName);
String deleteSQL = String.format(
"DELETE FROM %s WHERE create_date < ?", tableName);
LocalDateTime cutoffDate = LocalDateTime.now().minusDays(daysOld);
try {
sourceConn.setAutoCommit(false);
// 复制到归档表
try (PreparedStatement insertStmt =
archiveConn.prepareStatement(insertSQL)) {
insertStmt.setObject(1, cutoffDate);
int archivedCount = insertStmt.executeUpdate();
// 从源表删除
try (PreparedStatement deleteStmt =
sourceConn.prepareStatement(deleteSQL)) {
deleteStmt.setObject(1, cutoffDate);
deleteStmt.executeUpdate();
}
sourceConn.commit();
return archivedCount;
}
} catch (SQLException e) {
sourceConn.rollback();
throw e;
} finally {
sourceConn.setAutoCommit(true);
}
}
/**
* 按批次归档大数据量
*/
public int batchArchive(String tableName, int daysOld, int batchSize)
throws SQLException {
int totalArchived = 0;
boolean hasMore = true;
while (hasMore) {
// 查询需要归档的数据ID
String selectIdsSQL = String.format(
"SELECT id FROM %s WHERE create_date < ? LIMIT ?", tableName);
List<Long> idsToArchive = new ArrayList<>();
try (PreparedStatement selectStmt =
sourceConn.prepareStatement(selectIdsSQL)) {
selectStmt.setObject(1,
LocalDateTime.now().minusDays(daysOld));
selectStmt.setInt(2, batchSize);
ResultSet rs = selectStmt.executeQuery();
while (rs.next()) {
idsToArchive.add(rs.getLong("id"));
}
}
if (idsToArchive.isEmpty()) {
hasMore = false;
break;
}
// 批量归档
archiveBatch(tableName, idsToArchive);
totalArchived += idsToArchive.size();
System.out.printf("已归档 %d 条记录,总计 %d 条%n",
idsToArchive.size(), totalArchived);
}
return totalArchived;
}
private void archiveBatch(String tableName, List<Long> ids)
throws SQLException {
String placeholders = String.join(",",
ids.stream().map(id -> "?").toArray(String[]::new));
String copySQL = String.format(
"INSERT INTO %s_archive SELECT * FROM %s WHERE id IN (%s)",
tableName, tableName, placeholders);
String deleteSQL = String.format(
"DELETE FROM %s WHERE id IN (%s)", tableName, placeholders);
try {
sourceConn.setAutoCommit(false);
// 复制到归档表
try (PreparedStatement copyStmt =
archiveConn.prepareStatement(copySQL)) {
for (int i = 0; i < ids.size(); i++) {
copyStmt.setLong(i + 1, ids.get(i));
}
copyStmt.executeUpdate();
}
// 删除源数据
try (PreparedStatement deleteStmt =
sourceConn.prepareStatement(deleteSQL)) {
for (int i = 0; i < ids.size(); i++) {
deleteStmt.setLong(i + 1, ids.get(i));
}
deleteStmt.executeUpdate();
}
sourceConn.commit();
} catch (SQLException e) {
sourceConn.rollback();
throw e;
} finally {
sourceConn.setAutoCommit(true);
}
}
}
日志文件轮转归档案例
import java.io.*;
import java.nio.file.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.stream.Stream;
public class LogRotateArchiveDemo {
private final Path logDir;
private final DateTimeFormatter dateFormatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
public LogRotateArchiveDemo(String logDirPath) {
this.logDir = Paths.get(logDirPath);
}
/**
* 轮转当前日志文件
*/
public void rotateLogFile(String logFileName, long maxSize)
throws IOException {
Path logFile = logDir.resolve(logFileName);
if (!Files.exists(logFile)) {
return;
}
long fileSize = Files.size(logFile);
if (fileSize < maxSize) {
return;
}
// 生成带日期的归档文件名
String dateStr = LocalDate.now().format(dateFormatter);
String archivedName = logFileName + "." + dateStr;
Path archivedFile = logDir.resolve(archivedName);
// 重命名当前日志文件
Files.move(logFile, archivedFile,
StandardCopyOption.REPLACE_EXISTING);
// 创建新的空日志文件
Files.createFile(logFile);
// 对归档文件进行压缩
compressOldLog(archivedFile);
System.out.printf("日志轮转完成: %s -> %s.gz%n",
logFileName, archivedName);
}
/**
* 压缩旧的日志文件
*/
private void compressOldLog(Path logFile) throws IOException {
Path gzFile = Paths.get(logFile.toString() + ".gz");
try (GZIPOutputStream gzos = new GZIPOutputStream(
new FileOutputStream(gzFile.toFile()));
FileInputStream fis = new FileInputStream(logFile.toFile())) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
gzos.write(buffer, 0, bytesRead);
}
}
// 压缩后删除原文件
Files.delete(logFile);
}
/**
* 清理过期归档文件
*/
public void cleanOldArchives(int maxKeepDays) throws IOException {
LocalDate cutoffDate = LocalDate.now().minusDays(maxKeepDays);
try (DirectoryStream<Path> stream =
Files.newDirectoryStream(logDir, "*.gz")) {
for (Path file : stream) {
String fileName = file.getFileName().toString();
// 从文件名提取日期
String dateStr = extractDateFromFileName(fileName);
if (dateStr != null) {
LocalDate fileDate = LocalDate.parse(dateStr,
dateFormatter);
if (fileDate.isBefore(cutoffDate)) {
Files.delete(file);
System.out.printf("删除过期归档: %s%n", fileName);
}
}
}
}
}
private String extractDateFromFileName(String fileName) {
// 从文件名中提取日期部分
String[] parts = fileName.split("\\.");
if (parts.length >= 3) {
return parts[1]; // 格式: logname.2024-01-01.gz
}
return null;
}
}
综合归档管理类
import java.io.*;
import java.nio.file.*;
import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ArchiveManager {
private final FileArchiveDemo fileArchiver = new FileArchiveDemo();
private final DatabaseArchiveDemo dbArchiver;
private final LogRotateArchiveDemo logRotater;
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(2);
public ArchiveManager(Connection source, Connection archive,
String logDirPath) {
this.dbArchiver = new DatabaseArchiveDemo(source, archive);
this.logRotater = new LogRotateArchiveDemo(logDirPath);
}
/**
* 启动定时归档任务
*/
public void startScheduledArchiving() {
// 每天凌晨2点执行数据库归档
scheduler.scheduleAtFixedRate(() -> {
try {
System.out.println("开始数据库归档...");
int count = dbArchiver.archiveOldData("orders", 90);
System.out.printf("数据库归档完成,归档 %d 条记录%n", count);
} catch (Exception e) {
System.err.println("数据库归档失败: " + e.getMessage());
}
}, 0, 24, TimeUnit.HOURS);
// 每6小时检查日志文件大小
scheduler.scheduleAtFixedRate(() -> {
try {
logRotater.rotateLogFile("application.log",
100 * 1024 * 1024); // 100MB
// 每月清理一次过期归档
if (LocalDateTime.now().getDayOfMonth() == 1) {
logRotater.cleanOldArchives(90); // 保留90天
}
} catch (Exception e) {
System.err.println("日志轮转失败: " + e.getMessage());
}
}, 0, 6, TimeUnit.HOURS);
}
/**
* 手动执行完整归档
*/
public void performFullArchive() throws Exception {
System.out.println("开始完整归档流程...");
// 1. 文件归档
fileArchiver.archiveToZip(
"/data/old_files",
"/archive/data_" + LocalDateTime.now().toString() + ".zip"
);
// 2. 数据库归档
dbArchiver.batchArchive("transactions", 365, 1000);
// 3. 日志归档
logRotater.rotateLogFile("application.log", 50 * 1024 * 1024);
System.out.println("完整归档完成");
}
public void shutdown() {
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
}
}
}
使用建议
-
性能优化:
- 使用批量处理而不是逐条处理
- 归档大文件时使用缓冲流
- 考虑使用多线程并行归档
-
错误处理:
- 实现重试机制
- 记录详细的归档日志
- 实现事务回滚
-
监控与告警:
- 记录归档进度和状态
- 归档失败时发送告警
- 监控归档磁盘空间
-
安全性:
- 归档文件加密
- 权限控制
- 数据完整性验证
这些案例覆盖了文件、数据库和日志三种常见的数据归档场景,您可以根据实际需求进行调整和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播