簡體   English   中英

Java臨時文件測試在OSX上通過,在Windows上失敗

[英]Java Temporary File test passes on OSX, fails on Windows

我已經進行了一個JUnit測試,該測試測試了我一直在使用臨時文件執行某些功能的一段代碼。 出於某種原因,該測試在OSX上通過,但在Windows 7上失敗。為簡化起見,我將測試復制到了一個新文件中,並將其簡化為盡可能簡單,同時仍然顯示了錯誤。

基本上,我通過將逗號分隔的鍵/值對寫入臨時文件來初始化臨時文件(然后斷言它確實存在)。 然后,我嘗試根據鍵替換該行的值。 updateValueForKey()具有布爾值“ checkOldVal”,如果為true,則要求傳入的oldVal與文件中的oldVal相匹配。 此測試在Windows上失敗,並且在OSX上通過,無論這是對還是錯

Windows Java版本:1.6.0_45

OSX Java版本:1.6.0_65

代碼如下:

public class SimpleTempFileTest {

ReadWriteLock _fileLock = null;
File _file = null;

public SimpleTempFileTest() {
}

@Test
public void simpleTempFileTest() throws Exception {
    _file = File.createTempFile("testCsv", null);
    _file.deleteOnExit();
    _fileLock = new ReentrantReadWriteLock();
    BufferedWriter writer = null;
    try {
        _fileLock.writeLock().lock();
        writer = new BufferedWriter(new FileWriter(_file, true));
        writer.append("foo,bar");
        writer.newLine();
    } finally {
        if (writer != null) {
            writer.close();
        }
        _fileLock.writeLock().unlock();
    }

    BufferedReader br = new BufferedReader(new FileReader(_file));
    String line = br.readLine();
    assertTrue("Unexpected value. Line=" + line, line.equals("foo,bar"));
    assertTrue("Unexpected value. Line=" + line, br.readLine() == null);
    br.close();

    //Fails whether checkOldVal is true or false
    updateValueForKey("foo", "bar", "baz", true);
    br = new BufferedReader(new FileReader(_file));
    line = br.readLine();
    //Everything up to this point passes, but the following assertion fails
    assertTrue("Unexpected value. Line=" + line, line.equals("foo,baz"));
    assertTrue("Unexpected value. Line=" + line, br.readLine() == null);
    br.close();
}

String updateValueForKey(String key, String oldVal, String newVal, boolean checkOldVal) throws FileNotFoundException, IOException {
    BufferedReader br = null;
    BufferedWriter writer = null;
    File temp = null;
    try {
        _fileLock.writeLock().lock();
        br = new BufferedReader(new FileReader(_file));
        temp = File.createTempFile("csvTmp", ".tmp");
        writer = new BufferedWriter(new FileWriter(temp, true));
        boolean seek = true;
        String line;
        while ((line = br.readLine()) != null) {
            if (seek) {
                String[] nvp = line.split(",");
                System.out.println("nvp[0]=" + nvp[0] + ", nvp[1]=" + nvp[1]);
                if (nvp[0].equalsIgnoreCase(key)) {
                    if (nvp[1].equals(oldVal) || !checkOldVal) {
                        String lineToWrite = key + "," + newVal;
                        System.out.println("Writing " + lineToWrite);
                        writer.write(lineToWrite);
                        writer.newLine();
                        seek = false;
                        continue;
                    } else {
                        System.out.println("Failed for " + key + ". Val incorrect.");
                        return "Password incorrect";
                    }
                }
            }
            writer.write(line);
            writer.newLine();
        }
        _file.delete();
        temp.renameTo(_file);
        return null;
    } finally {
        if (br != null) {
            br.close();
        }
        if (writer != null) {
            writer.close();
        }
        if (temp != null) {
            temp.delete();
        }
        _fileLock.writeLock().unlock();
    }
}
}

有想法嗎? 謝謝。

該問題與Windows和Unix處理文件鎖定的方式之間的差異有關。 在Unix上,一個進程可以寫入文件,而另一個可以打開該文件以讀取它。 Windows不允許這樣做。

完全公開:我希望Java如果無法在文件上執行IO類型的操作,則將引發IOException,從而短暫地忘記了其中許多操作都返回布爾值,指定該操作是否成功。

長話短說,在updateValueForKey()的結尾處,我刪除_file,並將tmp重命名為_file,temp仍然針對它打開FileWriter,_file仍然針對它打開BufferedReader。 基本上,我必須將_file.delete和temp.renameTo()移動到finally塊下方。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM