正文
日志的转储和压缩是非常关键的,它不仅可以减少硬盘空间占用,主要还可以在发生故障时根据日志定位出故障原因。下面来看看golang和java的文件转储实现。
go语言:
用到了filepath包下的Walk方法,具体说明可以参看历史文章:)
package main
import (
"fmt"
"os"
"io"
"archive/zip"
"path/filepath"
"time"
"log"
)
func main() {
logFile := "D:/tmp/successLog/logs/root.log"
backFile := "D:/tmp/successLog/logs/root_" + time.Now().Format("20060102150405") + ".zip"
err := zipFile(logFile, backFile)
if err != nil {
log.Println(fmt.Sprintf("zip file %s to %s error : %v", logFile, backFile, err))
return
} else {
os.Remove(logFile)
}
}
func zipFile(source, target string) error {
zipFile, err := os.OpenFile(target, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0440)
if err != nil {
log.Println(err)
return err
}
defer zipFile.Close()
archive := zip.NewWriter(zipFile)
defer archive.Close()
return filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
if !info.IsDir() {
header.Method = zip.Deflate
}
header.SetModTime(time.Now().UTC())
header.Name = path
writer, err := archive.CreateHeader(header)
if err != nil {
return err
}
if info.IsDir() {
return nil
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
return err
})
}
java版:
说明见注释。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipFile {
private static final Logger LOGGER = LoggerFactory.getLogger(ZipFile.class);
private static final String AUDIT_LOG_FORMAT = "yyyyMMddHHmmssSSS";
private static final String AUDIT_FILE_ZIP_SUFFIX = ".zip";
private static final String AUDIT_FILE_EXT = ".log";
private static final int ZIP_BUFFER = 4096;
private static final String rootPath = "";
public static void main(String[] args) throws IOException {
System.out.println();
new ZipFile().zipAuditLogFile("D:/tmp/successLog/logs/root.log");
}
private void zipAuditLogFile(String waitZipFile) throws IOException {
File oldFile = new File(waitZipFile);
if (!oldFile.exists()) {
LOGGER.error("zipAuditLogFile name is {} not exist", waitZipFile);
return;
}
DateFormat dataFormat = new SimpleDateFormat(AUDIT_LOG_FORMAT);
String formatTime = dataFormat.format(oldFile.lastModified());
int end = waitZipFile.length() - AUDIT_FILE_EXT.length();
String zipFileName = waitZipFile.subSequence(0, end) + "_" + formatTime + AUDIT_FILE_ZIP_SUFFIX;
File zipFile = new File(zipFileName);
FileOutputStream zipfos = null;
ZipOutputStream zipOs = null;
CheckedOutputStream cos = null;
try {
zipfos = new FileOutputStream(zipFile);
cos = new CheckedOutputStream(zipfos, new CRC32());
zipOs = new ZipOutputStream(cos);
compress(oldFile, zipOs, rootPath);
if (zipFile.exists()) {
try {
Runtime.getRuntime().exec("chmod 400 -R " + zipFile);
boolean isDelete = oldFile.delete();
if (isDelete) {
oldFile.createNewFile();
}
} catch (IOException e) {
LOGGER.error("set archive file:{} permision catch an error: {}", zipFile, e);
}
}
} finally {
if (null != zipOs) {
zipOs.close();
}
if (null != cos) {
cos.close();
}
if (null != zipfos) {
zipfos.close();
}
}
}
private void compress(File oldFile, ZipOutputStream zipOut, String baseDir) throws IOException {
if (oldFile.isDirectory()) {
compressDirectory(oldFile, zipOut, baseDir);
} else {
compressFile(oldFile, zipOut, baseDir);
}
}
private void compressDirectory(File dir, ZipOutputStream zipOut, String baseDir) throws IOException {
File[] files = dir.listFiles();
for (File file : files) {
compress(file, zipOut, baseDir + dir.getName() + File.separator);
}
}
private void compressFile(File oldFile, ZipOutputStream zipOut, String baseDir) throws IOException {
if (!oldFile.exists()) {
LOGGER.error("zipAuditLogFile name is {} not exist", oldFile);
return;
}
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(new FileInputStream(oldFile));
ZipEntry zipEntry = new ZipEntry(baseDir + oldFile.getName());
zipOut.putNextEntry(zipEntry);
int count;
byte data[] = new byte[ZIP_BUFFER];
while ((count = bis.read(data, 0, ZIP_BUFFER)) != -1) {
zipOut.write(data, 0, count);
}
} finally {
if (null != bis) {
bis.close();
}
}
}
}
修改权限也可以利用Java7中NIO.2对元数据文件操作的支持,具体可以查看NIO包的使用,其相关教程见文末说明。
代码如下:
package com.website.common;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Set;
public class PathUtil {
private static final boolean ISPOSIX = FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
private static final int PERM_LEN_THREE = 3;
private static final int PERM_LEN_NINE = 9;
public static boolean setFilePermision(Path file, String perm) throws IOException {
if (!ISPOSIX) {
return true;
}
if (perm.length() == PERM_LEN_THREE) {
perm = trans2StrPerm(perm);
}
if (perm.length() != PERM_LEN_NINE) {
return false;
}
Set<PosixFilePermission> perms = PosixFilePermissions.fromString(perm);
Files.setPosixFilePermissions(file, perms);
return true;
}
private static String trans2StrPerm(String digitPerm) {
StringBuilder builder = new StringBuilder(9);
builder.append(toStringPerm(digitPerm.charAt(0)));
builder.append(toStringPerm(digitPerm.charAt(1)));
builder.append(toStringPerm(digitPerm.charAt(2)));
return builder.toString();
}
private static String toStringPerm(char ch) {
switch (ch - '0') {
case 7:
return "rwx";
case 6:
return "rw-";
case 5:
return "r-x";
case 4:
return "r--";
case 3:
return "-wx";
case 2:
return "-w-";
case 1:
return "--x";
case 0:
return "---";
default:
return "";
}
}
}
原作者:小碗汤