如何将目录日志文本转换为对象并写入ArrayList?
First, let's break down your scenario: you're traversing directories to read log files with your pathFiles method, and you want to parse those log lines into structured objects and collect them in an ArrayList. Here's a step-by-step solution to make that happen:
Step 1: Define a Model Class for Your Transaction Logs
First, create a class to represent each transaction entry from the logs. Based on your sample data, we'll include fields for all relevant data points:
import java.util.List; public class TransactionLog { private String timestamp; private String host; private String transactionId; private Integer assetId; private List<String> capturedTransactions; private String logTime; // Basic constructor for initial transaction line public TransactionLog(String timestamp, String host, String transactionId) { this.timestamp = timestamp; this.host = host; this.transactionId = transactionId; } // Getters and setters for all fields public void setAssetId(Integer assetId) { this.assetId = assetId; } public void setCapturedTransactions(List<String> capturedTransactions) { this.capturedTransactions = capturedTransactions; } public void setLogTime(String logTime) { this.logTime = logTime; } // Optional: toString() for debugging/printing @Override public String toString() { return "TransactionLog{" + "timestamp='" + timestamp + '\'' + ", host='" + host + '\'' + ", transactionId='" + transactionId + '\'' + ", assetId=" + assetId + ", capturedTransactions=" + capturedTransactions + ", logTime='" + logTime + '\'' + '}'; } }
Step 2: Modify Your File Traversal to Parse Logs
Update your directory traversal logic to parse each line, build TransactionLog objects, and collect them in an ArrayList. We'll use regex to extract data and track the current transaction being built (since logs span multiple lines):
import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class LogParser { // Regex patterns to match different log line formats private static final Pattern BASE_LINE = Pattern.compile("(\\w+ \\d+ \\d+:\\d+:\\d+) (\\S+) (transaction\\d+): (.+)"); private static final Pattern ASSET_ID = Pattern.compile("Asset id: (\\d+)"); private static final Pattern CAPTURED_TX = Pattern.compile("Captured transactions: (.*)"); private static final Pattern LOG_TIME = Pattern.compile("Log time: (.+)"); public static List<TransactionLog> parseAllLogs(File rootFolder) throws IOException { List<TransactionLog> allLogs = new ArrayList<>(); TransactionLog currentTx = null; File[] folderEntries = rootFolder.listFiles(); if (folderEntries == null) return allLogs; // Handle empty/inaccessible folder for (File entry : folderEntries) { if (entry.isDirectory()) { allLogs.addAll(parseAllLogs(entry)); // Merge logs from subdirectories continue; } // Process each line in the current file Files.lines(Paths.get(entry.getPath())).forEach(line -> { Matcher baseMatcher = BASE_LINE.matcher(line); if (baseMatcher.matches()) { // Finalize previous transaction if exists if (currentTx != null) { allLogs.add(currentTx); } // Create new transaction object from base line String timestamp = baseMatcher.group(1); String host = baseMatcher.group(2); String txId = baseMatcher.group(3); currentTx = new TransactionLog(timestamp, host, txId); // Handle initial transaction list line (like O365-1033,O365-104) String content = baseMatcher.group(4); if (!content.startsWith("Asset id") && !content.startsWith("Captured transactions") && !content.startsWith("Log time")) { currentTx.setCapturedTransactions(Arrays.asList(content.split(","))); } } else if (currentTx != null) { // Populate additional fields for current transaction Matcher assetMatcher = ASSET_ID.matcher(line); if (assetMatcher.matches()) { currentTx.setAssetId(Integer.parseInt(assetMatcher.group(1))); } Matcher txMatcher = CAPTURED_TX.matcher(line); if (txMatcher.matches()) { String txList = txMatcher.group(1); if (!txList.isEmpty()) { currentTx.setCapturedTransactions(Arrays.asList(txList.split(","))); } } Matcher timeMatcher = LOG_TIME.matcher(line); if (timeMatcher.matches()) { currentTx.setLogTime(timeMatcher.group(1)); } } }); // Add the last transaction in the file if (currentTx != null) { allLogs.add(currentTx); currentTx = null; } } return allLogs; } // Example usage public static void main(String[] args) throws IOException { File logFolder = new File("/path/to/your/log/directory"); List<TransactionLog> logs = parseAllLogs(logFolder); logs.forEach(System.out::println); } }
Key Details:
- Regex Parsing: The regex patterns extract structured data from each log line. Adjust them if your log format has variations.
- State Tracking: We keep track of the
currentTxbeing built since each transaction spans multiple lines. When a new transaction line is found, we add the previous one to the list. - Recursive Collection: The method merges results from subdirectories using
addAll, so you get a single list of all logs. - Edge Cases: Added checks for empty folders and incomplete transaction entries.
To use this, call parseAllLogs with your root log directory, and it will return an ArrayList of fully populated TransactionLog objects.
内容的提问来源于stack exchange,提问作者Igor

