Java读取中间文本文件实现分组列数据求和及百分比计算的问题求助
Solution for Grouped Sum and Percentage Calculation in Java
I've run into this exact issue before with fixed-width formatted files converted to space-separated lines—those variable spaces are a real pain! Let's fix this step by step, starting with the parsing problem and then building out the grouped sum and percentage calculation.
Here's a complete, working solution that addresses your whitespace parsing issue, handles state-wise grouping, and computes the required percentages:
import java.io.*; import java.util.HashMap; import java.util.Map; import java.util.Scanner; // Custom class to hold aggregated data for each state class StateAggregate { int totalPopulation; int schoolAgeChildren; int povertyChildren; public StateAggregate() { this.totalPopulation = 0; this.schoolAgeChildren = 0; this.povertyChildren = 0; } public void add(int total, int schoolAge, int poverty) { this.totalPopulation += total; this.schoolAgeChildren += schoolAge; this.povertyChildren += poverty; } } public class StatePopulationAnalyzer { public static void main(String[] args) { // Map to hold aggregated data per state code Map<String, StateAggregate> stateDataMap = new HashMap<>(); try (BufferedReader reader = new BufferedReader(new FileReader("IntermediateSmallAreaIncomePovertyEstData.txt"))) { String line; while ((line = reader.readLine()) != null) { // Use Scanner to handle variable whitespace automatically Scanner lineScanner = new Scanner(line); String stateCode = lineScanner.next(); int totalPop = lineScanner.nextInt(); int schoolAge = lineScanner.nextInt(); int poverty = lineScanner.nextInt(); // Get or create the aggregate entry for this state StateAggregate aggregate = stateDataMap.getOrDefault(stateCode, new StateAggregate()); aggregate.add(totalPop, schoolAge, poverty); stateDataMap.put(stateCode, aggregate); } // Print formatted results System.out.printf("%-10s %-15s %-20s %-25s %-20s\n", "State Code", "Total Population", "School Age Children", "Poverty Children", "% Poverty (School Age)"); System.out.println("--------------------------------------------------------------------------------------------------------"); for (Map.Entry<String, StateAggregate> entry : stateDataMap.entrySet()) { String stateCode = entry.getKey(); StateAggregate data = entry.getValue(); // Calculate percentage, handle division by zero edge case double povertyPercentage = data.schoolAgeChildren == 0 ? 0.0 : (double) data.povertyChildren / data.schoolAgeChildren * 100; System.out.printf("%-10s %-15d %-20d %-25d %-20.2f%%\n", stateCode, data.totalPopulation, data.schoolAgeChildren, data.povertyChildren, povertyPercentage); } } catch (IOException e) { System.err.println("Error reading file: " + e.getMessage()); } catch (NumberFormatException e) { System.err.println("Error parsing numeric data: " + e.getMessage()); } } }
Key Fixes & Improvements:
Variable Whitespace Handling
- Instead of
split(" "), we useScannerwhich automatically splits on any whitespace (spaces, tabs, etc.)—this eliminates empty array elements from multiple spaces entirely. - If you prefer using
split, replace the Scanner logic with:String[] parts = line.trim().split("\\s+"); // \\s+ matches one or more whitespace characters String stateCode = parts[0]; int totalPop = Integer.parseInt(parts[1]); int schoolAge = Integer.parseInt(parts[2]); int poverty = Integer.parseInt(parts[3]); trim()removes leading/trailing whitespace to avoid unexpected empty elements at the start of the array.
- Instead of
State-Wise Grouped Aggregation
- A
HashMap<String, StateAggregate>stores summed values per state code. TheStateAggregateclass keeps track of the three totals in an organized, reusable way. getOrDefault()simplifies checking for existing state entries—if no entry exists, we create a newStateAggregateinstance.
- A
Percentage Calculation
- We cast values to
doublebefore division to avoid integer division (which would truncate results to 0 if poverty counts are smaller than school age counts). - Added a check for division by zero (in case a state has no school age children) to prevent runtime errors.
- We cast values to
Robust Resource Management
- Try-with-resources (
try (BufferedReader reader = ...)) ensures the file reader is automatically closed, even if an exception occurs.
- Try-with-resources (
Clean Formatted Output
printfaligns columns neatly, making the final results easy to read and interpret.
Why Your Original Test.java Failed:
- It summed all rows into a single
totalPopvariable instead of grouping by state code. split(" ")creates empty strings in the array when multiple spaces are present, sopopulation[1]wouldn't always point to the total population value (leading to parsing errors).
内容的提问来源于stack exchange,提问作者Billiejean711
相关产品推荐
相关产品推荐

