Java二进制文件读取优化问题:如何完整读取文件内容、避免额外空格并确保循环执行完毕
Hey there, let's work through the issues in your code and get it working properly. I see three main things to fix: the missing last card entry, ensuring clean file reading, and avoiding extra spaces in the formatted card number.
Why the last card isn't processed
Your current read logic has a classic "read-before-process" flaw:
- You first read a
longintodatabefore entering the loop - Inside the loop, you convert the existing
datato a string, then immediately read the nextlong - When you hit the end of the file, the
readLong()call throws an exception before you can process the lastdatavalue you already read. That's why your final test case never gets handled.
Fixing the loop & file handling
We'll rearrange the flow to process each value right after reading it, and use try-with-resources to safely manage your input streams (so you don't have to manually close them, which avoids resource leaks). We'll also catch EOFException specifically (this is what readLong() throws when it hits the end of the file) instead of a broad IOException—this lets us cleanly exit the loop when there's no more data, while still catching other real errors like missing files.
Ensuring no extra spaces
Your existing spacing logic is almost there, but we can tweak it to be more robust (it works for 16-digit cards, but this adjustment handles all lengths) and guarantee no trailing space at the end of the card number.
Fixed Code
import java.io.DataInputStream; import java.io.EOFException; import java.io.FileInputStream; import java.io.IOException; import java.util.Scanner; public class CardNumber { public static void main(String[] args) { Scanner keyboard = new Scanner(System.in); System.out.println("Enter a filename"); String input = keyboard.nextLine(); // Try-with-resources auto-closes streams when we're done try (FileInputStream basic = new FileInputStream(input); DataInputStream inputFile = new DataInputStream(basic)) { while (true) { long data; try { data = inputFile.readLong(); // Read first, then process the value } catch (EOFException e) { break; // Exit loop cleanly when end of file is reached } String cardNumber = String.valueOf(data); System.out.print("Credit card number: "); // Format with spaces every 4 digits, no trailing space for (int i = 0; i < cardNumber.length(); i++) { System.out.print(cardNumber.charAt(i)); // Add space only if we're at a 4-digit boundary AND not the last character if ((i + 1) % 4 == 0 && i != cardNumber.length() - 1) { System.out.print(" "); } } System.out.println(); // Calculate Luhn checksum int sum = 0; int len = cardNumber.length(); // Process every other digit starting from second last for (int i = len - 2; i >= 0; i -= 2) { int digit = (cardNumber.charAt(i) - '0') * 2; sum += digit % 10 + digit / 10; // Split two-digit values and add } // Process remaining digits for (int i = len - 1; i >= 0; i -= 2) { sum += cardNumber.charAt(i) - '0'; } System.out.println("Checksum: " + sum); System.out.print("Card status: "); System.out.println(sum % 10 == 0 ? "VALID" : "INVALID"); } } catch (IOException e) { System.err.println("Error reading file: " + e.getMessage()); } finally { keyboard.close(); } } }
Key Improvements:
- Read-then-process flow: We read a
long, then immediately process it. WhenEOFExceptionis thrown, we exit the loop—no unprocessed data left behind. - Try-with-resources: Automatically closes your input streams, so you don't have to remember to call
close()(which prevents resource leaks). - Clean spacing: The adjusted condition ensures we never add a trailing space after the last digit, regardless of the card number length.
- Targeted exception handling: Catching
EOFExceptionseparately lets us distinguish between "end of file" (expected) and other IO errors (like file not found, which we handle with an error message).
内容的提问来源于stack exchange,提问作者Trinidad James

