Java printf打印类对象数组仅最后一个索引值可正常输出问题
问题根因
这个异常和printf方法本身无关,核心原因是读取文本文件时没有处理Windows系统的\r回车符,完全匹配你描述的故障表现:
- Windows环境下文本文件的换行标识为
\r\n(回车+换行双字符),你代码中用split("\n")拆分全量文件内容时,除了文件最后一行,其余所有行的末尾都会残留一个\r(ASCII码13,即回车符)。 - 按你的字段拆分逻辑,
description是每行最后一个被拆分出来的字段,因此除了数组最后一个InsuranceCompany对象,其余所有对象的description字段值都会携带这个多余的\r。 - 回车符
\r的输出效果是将光标直接移动到当前行的起始位置,不会触发换行。当你用printf输出带\r的内容时,前面已经打印的公司名、分隔线等内容,会在\r触发光标回退到行首后,被后续输出的内容直接覆盖,视觉上就像没有正常输出对应值;而你用println校验数据时,要么是输出整段内容后直接换行,\r的覆盖效果没有触发,要么是你没注意到内容覆盖的细节,所以误以为数据完全正常。 - 数组最后一个元素对应文件的最后一行,这一行末尾没有换行符,拆分出的
description字段不带\r,因此打印完全正常。
另外你的代码里还有个小问题:printf中使用的大写%S占位符会自动将传入的字符串转为全大写输出,如果不需要这个效果,应该使用小写%s占位符。
修复方案
- 修正文件内容拆分逻辑,兼容多系统换行格式,清除残留的
\r字符:
将原代码中拆分数据行的语句
替换为String[] data = loadDataFromFile(dataFile).split("\n");// 先移除所有\r回车符,再按换行拆分,兼容Windows、Linux、macOS的换行规则 String[] data = loadDataFromFile(dataFile).replace("\r", "").split("\n"); - (可选调整)如果不需要自动将打印内容转为全大写,把代码中所有
printf里的大写%S占位符替换为小写%s即可,例如:
打印险种类型的// 原语句 System.out.printf("| %-18S | %-28S |%n", selectedCompany.getCompanyName(), selectedCompany.getDescription()); // 修改为 System.out.printf("| %-18s | %-28s |%n", selectedCompany.getCompanyName(), selectedCompany.getDescription());%15S也对应修改为%15s即可。
修复完成后,传入0到length-2范围的索引调用打印方法,就不会再出现内容被覆盖、输出异常的问题。你之前注释掉的System.out.flush()语句不需要启用,printf遇到%n换行符时会自动刷新输出缓冲区,不存在缓冲区未刷新导致内容不打印的问题。
附问题复现代码:InsuranceCompany类:
package com.insurance.company; import java.util.List; /** * * @author Lenovo */ public class InsuranceCompany { private String companyName; private String telephone; private String webAddress; private double brokerPercentage; private String description; private List<String> insuranceTypes; public InsuranceCompany(){} public InsuranceCompany(String companyName, String telephone, String webAddress, double brokerPercentage, String description, List<String> insuranceTypes) { this.companyName = companyName; this.telephone = telephone; this.webAddress = webAddress; this.brokerPercentage = brokerPercentage; this.description = description; this.insuranceTypes = insuranceTypes; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(companyName); sb.append(" " + telephone); sb.append(" " + webAddress); for(int i = 0; i < insuranceTypes.size(); i++){ sb.append(" " + insuranceTypes.get(i)); } sb.append(" " + brokerPercentage); sb.append(" " + description); return sb.toString(); } public String getCompanyName() { return companyName; } public String getTelephone() { return telephone; } public String getWebAddress() { return webAddress; } public double getBrokerPercentage() { return brokerPercentage; } public String getDescription() { return description; } public List<String> getInsuranceTypes() { return insuranceTypes; } }
InsurancePortal主类:
package com.insurance.company; import java.io.File; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class InsurancePortal { //function to load data from file private static String loadDataFromFile(String path)throws Exception{ String data; data = new String(Files.readAllBytes(Paths.get(path))); return data; } //function to list all insurance companies private static void listInuranceCompanies(InsuranceCompany[] company){ System.out.println("------------------------------------------------------------------------------------------------------------------------------------------------"); System.out.printf("| %3s | %-20s | %-111s |%n", "ID", "Company Name", "Cover Types"); //System.out.flush(); System.out.println("------------------------------------------------------------------------------------------------------------------------------------------------"); for(int j = 0; j < company.length; j++){ System.out.printf("| %3d | %-20s |", j+1, company[j].getCompanyName()); for(int i = 0; i < 7; i++){ if(i < company[j].getInsuranceTypes().size()){ System.out.printf(" %15S", company[j].getInsuranceTypes().get(i)); }else{ System.out.printf(" %15s", " "); } } System.out.print(" |\n"); System.out.println("------------------------------------------------------------------------------------------------------------------------------------------------"); } } //function to search cover public static void listSingleCompanyDetails(InsuranceCompany selectedCompany){ System.out.println(selectedCompany.getCompanyName()+"\n--------------------------------------------------"); //System.out.flush(); System.out.printf("| %-18S | %-28S |%n", selectedCompany.getCompanyName(), selectedCompany.getDescription()); //System.out.flush(); System.out.println("--------------------------------------------------"); System.out.println("--------------------------------------------------"); System.out.println("--------------------------------------------------"); System.out.println("--------------------------------------------------"); System.out.println("--------------------------------------------------"); } public static void main(String arge[]) throws Exception{ String dataFile = System.getProperty("user.dir") + File.separator + "insurance-data.txt"; String[] data = loadDataFromFile(dataFile).split("\n"); /*for(String str: data){ System.out.println(str); }*/ int rows = data.length; InsuranceCompany[] company = new InsuranceCompany[rows]; //Initialising objects for every row of data in the file for(int j = 0; j < rows; j++){ String row = data[j]; //System.out.println(row); String companyName, telephone, webAddress, description; double brokerPercentage; List<String> insuranceTypes = new ArrayList<>(); //Splitting for Company Name String[] splittedArray = row.split(":", 2); companyName = splittedArray[0]; row = splittedArray[1]; //Splitting for telephone splittedArray = row.split(":", 2); telephone = splittedArray[0]; row = splittedArray[1]; //splitting for web address splittedArray = row.split(":", 2); webAddress = splittedArray[0]; row = splittedArray[1]; //splitiing for insurance types splittedArray = row.split(":", 2); String[] insuranceTypeList = splittedArray[0].split(","); for(String str : insuranceTypeList){ insuranceTypes.add(str); } row = splittedArray[1]; //splitting for broker percentage splittedArray = row.split(":", 2); brokerPercentage = Double.parseDouble(splittedArray[0]); row = splittedArray[1]; //splitting for description splittedArray = row.split(":", 2); description = splittedArray[0]; company[j] = new InsuranceCompany(companyName, telephone, webAddress, brokerPercentage, description, insuranceTypes); } boolean run = true; while(run){ int choice; Scanner sc = new Scanner(System.in); System.out.print("\nList insurance companies.......1\n" + "Select insurance company.......2\n" + "Search cover...................3\n" + "Exit...........................0\n" + "\nEnter choice:> "); choice = sc.nextInt(); switch(choice){ case 1 : listInuranceCompanies(company); break; case 2 : System.out.print("Enter company ID from list [1 - "+(company.length)+"] :> "); int selectedCompany; selectedCompany = sc.nextInt(); listSingleCompanyDetails(company[selectedCompany-1]); break; case 0 : System.exit(0); break; default: System.out.println("Invalid choice!, please try again."); } } } }
内容的提问来源于stack exchange,提问作者Lakshya Sengar
相关产品推荐
相关产品推荐

