Java 在没有任何数据格式的情况下,以特定行写入文件

Java 在没有任何数据格式的情况下,以特定行写入文件,java,Java,我试图做的是,当用户想要编辑他的个人资料,然后按save changes(保存更改)时,我想要从所有JTextFields中获取文本,并将其写入文件中特定行中。然而,经过3天的尝试,没有运气。我已经看过了这里所有关于读写文件的帖子,但是没有任何运气,好的,所有的方法都在下面,我会解释它们 public void save() throws IOException{ String changes = name.getText() + "" + dob.getText() + ""

我试图做的是,当用户想要编辑他的个人资料,然后按save changes(保存更改)时,我想要从所有JTextFields中获取文本,并将其写入文件中特定行中。然而,经过3天的尝试,没有运气。我已经看过了这里所有关于读写文件的帖子,但是没有任何运气,好的,所有的方法都在下面,我会解释它们

public void save() throws IOException{
    String changes = name.getText() + "" + dob.getText() + "" 
            + "" + address.getText() + "" + town.getText() 
            + "" + number.getText();
    String whichLine = this.staff_no.getText();
    this.name.setEditable(false);
    this.dob.setEditable(false);
    this.address.setEditable(false);
    this.town.setEditable(false);
    this.number.setEditable(false);
    users.saveChanges(changes,whichLine);
}
在这里,我创建了一个字符串,其中JTextFields中的所有文本都设置为false,并调用saveChanges方法(假定“替换”这个新字符串的方法)

现在,我得到了用户的Staffno,并通过我的ArrayLists用户来查找它的索引,比如说它的0。然后我在之前打开的扫描器中循环,试图找到哪一行我可以覆盖那一行。然而,我遇到了异常错误,比如流关闭或NoSuchalementException,或者根本没有错误,但是我没有写我的行或保存它

下面是我打开文件的方法

public void open(){
    try {
        URL path = Users.class.getResource("records.txt");
        File f = new File(path.getFile());
        reader = new BufferedReader(new FileReader(f));
        scan = new Scanner(reader);
    } catch (FileNotFoundException e) {
        System.out.println("File not found");
    }
}
我不关闭扫描仪的原因是因为我会继续使用它做其他事情


我意识到这是一个特定的场景,而不是一个简单的读/写场景,因此非常感谢您的帮助。

如果您的文件不大,您可以执行以下操作:

// File file = ...
// int yourLineNumber = ...
List<String> lines = FileUtils.readLines(new FileReader(file));
lines.add(yourLineNumber, "Line to add");
FileUtils.writeLines(file, lines);
//文件=。。。
//int yourLineNumber=。。。
列表行=FileUtils.readLines(新文件阅读器(文件));
行。添加(您的行号,“要添加的行”);
FileUtils.writeLines(文件,行);

我在这个代码中使用库。

你要做的事情——在文件中间重写数据——只有当你写的字节数与你正在替换的字节相同时才能完成。也就是说,不能用不同的行覆盖文件中的行,除非它们的字节数完全相同(不一定是相同的字符数,具体取决于字符编码)

您还为您正在积极写入的文件打开了一个扫描器,该文件只是请求缓冲相关问题

解决问题最简单的方法是按照Coolgay的建议,将所有行读入内存,根据需要替换或添加行,然后全部写回

但是,如果您不能或不想将整个文件缓存在内存中,您可以逐行读取文件,然后在更改相关行后将它们写回另一个文件,最后用新文件替换旧文件

public static void writeChanges(String changes, int whichLine) throws IOException {
    // The files we're working with
    final File database = new File("database.txt");
    final File newDatabase = new File("database.new.txt");
    try(BufferedReader reader = new Bufferedreader(
            new InputStreamReader(new FileInputStream(database)));
            PrintWriter writer = new PrintWriter(newDatabase)) {
        int line = 0;
        String line;
        // Keep reading lines from the source file until we've read them all
        while((line = reader.readLine()) != null) {
            if(line == whichLine) {
                // Write the modified line
                writer.println(changes);
            } else {
                // Write the original line
                writer.println(line);
            }
            line++;
        }
    }
    // Replace the old database with the new
    Files.move(newDatabase.toPath(), database.toPath(), StandardCopyOption.REPLACE_EXISTING);
}

您不能写入文件的中间部分(当然可以,但这相当棘手)。你必须重写整个文件,更改您想要的行。我正在尝试做的是,当我阅读文件时,如果我找到我想要的行,我将覆盖它…如果有那么困难,我愿意接受建议:)您是否想过使用数据库而不是txt文件?我们不允许使用数据库…只允许使用txt文件来模拟数据库关于您的示例的快速问题…说我正确地实现这一点,它就会工作…我的txt文件将被重命名为database.new.txt?我提出这个问题的原因是,用户可以修改文件任意次数,而不是一次。感谢您,我们正在阅读
database.txt
并将更改写入
database.new.txt
,我们正在将
database.txt
替换为
database.new.txt
,以便
database.txt
再次成为当前数据库。顺便说一句,这会迫使您关闭并重新创建扫描仪,因为它现在指向了错误的文件。我在代码中添加了它应该扫描的位置。关闭…..我不能用那种方法关闭它,因为我在另一种方法中使用它来将值传递给用户属性。为什么混合使用NIO api和
文件
api-这非常可怕?只需使用
Stream
API在几行中完成此操作……因为
File.renameTo
不会引发任何异常。请随意使用streams编写您自己的答案。不过,我保留这一点是因为我更熟悉“旧”IO类和
文件。move
优于
File。renameTo
当此功能可用时,为什么推荐commons IO库?此外,commons IO库使用了古老而垃圾的
文件
API,而不是
路径
API。我真的希望人们从2010年起停止在互联网上传播这些可怕的例子…@Boristeider你几乎可以对任何图书馆说同样的话。此外,我认为您不应该关心API
commons io使用什么。它可以使用
路径
来获得相同的结果。另外,我不是说你应该在你的新代码中使用
文件。没有理由将最近一次更新是在2012年的库包含到新代码中,因为库创建的代码比JDK提供的实用程序更详细、更健壮。这个例子和那些在将泛型添加到JDK之前发布Java 1.4中Java集合示例的人一样没有帮助。欢迎您使用
Path
API发布答案,我很乐意对其进行比较:)但我相信您不能用更少的代码来实现它。但如果您不需要任何其他
commons io
功能,那么它可能是一个更好的解决方案。
public static void writeChanges(String changes, int whichLine) throws IOException {
    // The files we're working with
    final File database = new File("database.txt");
    final File newDatabase = new File("database.new.txt");
    try(BufferedReader reader = new Bufferedreader(
            new InputStreamReader(new FileInputStream(database)));
            PrintWriter writer = new PrintWriter(newDatabase)) {
        int line = 0;
        String line;
        // Keep reading lines from the source file until we've read them all
        while((line = reader.readLine()) != null) {
            if(line == whichLine) {
                // Write the modified line
                writer.println(changes);
            } else {
                // Write the original line
                writer.println(line);
            }
            line++;
        }
    }
    // Replace the old database with the new
    Files.move(newDatabase.toPath(), database.toPath(), StandardCopyOption.REPLACE_EXISTING);
}