1

与 Linux 相比,我在理解 Windows 如何处理文件时遇到了一些麻烦。我正在尝试删除我用作“数据库”的文件中的条目(它只是一个常规文件)。不幸的是,Java 没有提供这样做的方法,所以我必须将除我要删除的条目之外的所有条目复制到临时文件中,删除旧数据库,创建一个新的空数据库文件,将临时文件的内容复制到新的数据库文件,并通过删除临时文件来完成。

这是我的功能的代码:

private void removeSelectedItem(String entryToRemove) {

    //original database file
    File database = new File("catalog");

    //all entries except selected will be written here first
    File temp = new File("temp");

    boolean endOfFileFlag = false;
    String line = "";

    try {

        //used for reading original database file
        BufferedReader databaseReader =
            new BufferedReader(new FileReader(database));

        //used for writing to newly-created temp file
        BufferedWriter tempWriter =
            new BufferedWriter(new FileWriter(temp, true));

        /*
         * Read original database line by line and test to see if the line
         * has the course prefix and id. If it does, it won't be written to
         * the temp file.
         */
        while (endOfFileFlag == false) {

            line = databaseReader.readLine();

            /*
             * This code is ugly. If possible, this check needs to be
             * made in the conditions of the while loop.
             */
            if (line == null) {

                endOfFileFlag = true;
                break;

            }

            //tests to see if the line is to be removed
            if ( !line.contains(entryToRemove))
                tempWriter.write(line + "\r\n");

        }

        endOfFileFlag = false; //reset this for the next loop
        databaseReader.close(); //database will be deleted
        tempWriter.close(); //temp file is written
        database.delete(); //delete this to create a new updated one below

        database.createNewFile();

        //writes to the new database
        BufferedWriter databaseWriter =
                new BufferedWriter(new FileWriter(database, true));

        //reads from the temp file
        BufferedReader tempReader =
            new BufferedReader(new FileReader(temp));

        //read temp line by line and add each line to a new catalog file
        while (endOfFileFlag == false) {

            line = tempReader.readLine();

            /*
             * This code is ugly. If possible, this check needs to be made
             * in the conditions of the while loop. Attempts thus far have
             */
            if(line == null){

                endOfFileFlag = true;
                break;

            }

            databaseWriter.write(line + "\r\n");

        }

        tempReader.close(); //temp will be deleted
        databaseWriter.close(); //new database has been written
        temp.delete(); //temp file no longer needed

        setUpInfo(); //update the lists with the new catalog info

    }catch(IOException e){

        System.out.println("removeSelectedItem()");
        e.printStackTrace();

    }

}

这段代码(“\r\n”除外,在 Linux 中只有“\n”)在 Linux 下完美执行,但在 Windows 中,我发现当我激活事件处理程序以删除条目时,程序只会添加额外的条目。调试后我发现调用database.delete()实际上并没有删除数据库文件,而调用temp.delete()是删除临时文件(就像它应该的那样)。我发现这很奇怪,所以我检查了文件的权限并将它们设置为“读/写”。我尝试了在互联网上找到的以下修复:

endOfFileFlag = false; //reset this for the next loop
databaseReader.close(); //database will be deleted
tempWriter.close(); //temp file is written
database.delete(); //delete this to create a new updated one below
//new code
database = null;
System.gc();

但它没有用。我想不出还有什么可能发生的。

4

2 回答 2

2

AFAIK,没有操作系统支持删除文件的一部分(除了结尾)

您无法删除已打开的文件,因此您必须确保在所有地方都将其关闭,但您可以创建一个临时文件并将其重命名为原始文件。(不需要复制回来)

这是我可能写的方式

public static void removeLine(String filename, String line) {
    File from = new File(filename);
    File tmp = new File(filename + ".tmp");
    PrintWriter pw = null;
    BufferedReader br = null;
    try {
        pw = new PrintWriter(tmp);
        br = new BufferedReader(new FileReader(from));
        boolean found = false;
        for (String line2; (line2 = br.readLine()) != null; )
            if (line2.equals(line))
                found = true;
            else
                pw.println(line2);
        pw.close();
        br.close();
        if (found) {
            from.delete();
            tmp.renameTo(from);
        } else {
            tmp.delete();
        }
    } catch (IOException e) {
        // log error.
        try { if (br != null) br.close(); } catch (IOException ignored) { }
        if (pw != null) pw.close();
    }
}
于 2013-05-13T17:09:21.247 回答
2

至于您的\r\nvs\n问题,请使用System.getProperty("line.separator")(或 Java 7's System.lineSeparator())来确定您的行尾字符序列。

确保您已在任何地方关闭该文件。尝试使用Path该类来读取文件。我不知道为什么你目前不能删除它,但也许这会解决问题。

此外,您应该为while循环使用以下结构(以避免使用break):

while (endOfFileFlag == false) {

    line = databaseReader.readLine();

    if (line == null)
        endOfFileFlag = true;
    else if ( !line.contains(entryToRemove))
        tempWriter.write(line + "\r\n");

}
于 2013-05-13T17:13:07.230 回答