使用for循环与PrintWriter生成多份随机命名文件的问题排查
问题分析与解决方案
嘿,我一眼就揪出问题所在啦——你输入大于1的数值后只生成一个文件,核心原因是生成随机文件名和类名的代码被放在了for循环外面,导致整个循环过程中都在复用同一个文件名,每次循环都会覆盖之前创建的文件,最后自然只剩最后一次写入的那个文件咯。
具体问题点
你看这段代码:
String printername = (rangen.getnumlet(length) + ".java"); String name = (printername.substring(0 , printername.indexOf('.')).trim());
这两行是在main方法中、for循环执行前就运行的,只会生成一次随机文件名和类名。后面的for循环每次创建PrintWriter时,都用的是同一个printername,相当于反复往同一个文件里写内容(而且每次创建PrintWriter时会清空文件原有内容),最终就只会留下最后一次写入的文件。
修正后的代码
只需要把生成文件名和类名的代码移到for循环内部,让每次循环都生成新的随机名称就行。另外我还加了几个实用优化:用try-with-resources自动关闭流,避免手动关闭可能出现的资源泄漏;同时把生成的类名首字母转成大写,符合Java类名规范,避免编译错误。
import java.util.Scanner; import java.io.PrintWriter; import java.io.FileNotFoundException; public class rangen { static String getnumlet(int n) { String numlet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; StringBuilder sb = new StringBuilder(n); for (int i = 0 ; i < n ; i++) { int index = (int)(numlet.length() * Math.random()); sb.append(numlet.charAt(index)); } return sb.toString(); } public static void main(String[] args) { final int length = 10; int amount = 0; Scanner input = new Scanner(System.in); System.out.print("Enter the amount of files you want to create: "); amount = input.nextInt(); for (int i = 1 ; i <= amount ; i++) { // 把生成文件名和类名的代码移到循环内部,每次循环生成新名称 String printername = (rangen.getnumlet(length) + ".java"); // 处理类名:首字母大写,符合Java规范 String rawName = printername.substring(0, printername.indexOf('.')).trim(); String name = rawName.substring(0, 1).toUpperCase() + rawName.substring(1); // 使用try-with-resources自动关闭PrintWriter,更安全 try (PrintWriter tofile = new PrintWriter(printername)) { tofile.print("// Creator: Unknown...\n"); tofile.print("// Date Created: 9-28-2019\n"); tofile.print("// Last Modified: 9-28-2019\n"); tofile.print("// Description: This file was \n" + "// randomly generated.\n"); tofile.print("public class " + name + " {\n"); tofile.print(" public static void main(String[] args) {\n"); tofile.print(" private static final double inf = \n" + " Double.POSITIVE_INFINITY;\n"); tofile.print(" for (int x = 1 ; x <= inf ; x++) {\n"); // 变量名改为x,避免和外部循环的i冲突 tofile.print(" System.out.print(\"yeet \" + x);\n"); tofile.print(" }\n"); tofile.print(" }\n"); tofile.print("}\n"); for (int x = 0 ; x <= 5; x++ ) { tofile.print("// LOL " + x + "\n"); } System.out.println("Successfully created: " + printername); } catch (FileNotFoundException e) { System.out.println("couldn't create " + printername); } // 无需手动关闭tofile,try-with-resources会自动处理 } input.close(); } }
额外说明
- 我把内部循环的变量名从
i改成了x,避免和外部for循环的i重名,虽然Java语法允许,但这样代码可读性更好。 - 新增了成功创建文件的提示,方便你直观确认每个文件都正常生成。
- 处理类名首字母大写是因为Java要求类名必须以大写字母开头,否则编译会报错哦。
内容的提问来源于stack exchange,提问作者Chgearft




