8

Watching a Directory for Changes Java7 nio2 チュートリアルに従って、コード サンプル WatchDir.java を使用してディレクトリの内容全体を再帰的に監視しました。

コードは次のようになります。

// Get list of events for the watch key.
for (WatchEvent<?> event : key.pollEvents()) {
// This key is registered only for ENTRY_CREATE events, but an OVERFLOW event 
// can occur regardless if events are lost or discarded.
if (event.kind() == OVERFLOW) {
    continue;
}

// Context for directory entry event is the file name of entry.
@SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>)event;
Path fileName = ev.context();
Path fullPath = dir.resolve(fileName);

try {
    // Print out event.
    System.out.print("Processing file: " + fileName);

    processed = fileProcessor.processFile(fullPath);

    System.out.println("Processed = " + processed);

    if (processed) {
        // Print out event.
        System.out.println(" - Done!");
    }
} 
catch (FileNotFoundException e) {
    System.err.println("Error message: " + e.getMessage());
}
catch (IOException e) {
    System.err.println("Error processing file: " + fileName.toString());
    System.err.println("Error message: " + e.getMessage());
}

わかりましたので、問題(私は何か愚かなことをしていると確信しています)はここにあります:

processed = fileProcessor.processFile(fullPath);

そして、それは次のようなものです:

public synchronized boolean processFile(Path fullPath) throws IOException {
String line;
String[] tokens;
String fileName = fullPath.getFileName().toString();
String fullPathFileName = fullPath.toString();

// Create the file.
File sourceFile = new File(fullPath.toString());

// If the file does not exist, print out an error message and return.
if (sourceFile.exists() == false) {
    System.err.println("ERROR: " + fullPathFileName + ": No such file");
    return false;
}

// Check file extension.
if (!getFileExtension(fullPathFileName).equalsIgnoreCase("dat")) {
    System.out.println(" - Ignored.");
    return false;
}

// Process source file.
try (BufferedReader bReader = new BufferedReader(new FileReader(sourceFile))) {
    int type;

    // Process each line of the file.
    while (bReader.ready()) {

        // Get a single line.
        line = bReader.readLine();

        // Get line tokens.
        tokens = line.split(delimiter);

        // Get type.
        type = Integer.parseInt(tokens[0]);

        switch (type) {
        // Type 1 = Salesman.
        case 1:
            -> Call static method to process tokes.
            break;
        // Type 2 = Customer.
        case 2:
            -> Call static method to process tokes.
            break;
        // Type 3 = Sales.
        case 3:
            -> Call static method to process tokes.
            break;
        // Other types are unknown!
        default:
            System.err.println("Unknown type: " + type);
            break;
        }
    }

    PrintStream ps = null;
    try {

        // Write output file.
        // Doesn't matter. 

    } 
    finally {               
        if (ps != null) {
            ps.close();
        }
    }
    return true;
}
}

イベントを初めて処理するときは、すべて正常に動作します。処理するファイルが複数ある場合でも。しかし、連続して次のエラーメッセージが表示されます。

ファイルが別のプロセスによって使用されているため、プロセスはファイルにアクセスできません

ここで何が間違っていますか?連続したファイルを正常に処理するにはどうすればよいですか?

私が言及するのを忘れた2つの重要な注意:

  1. Windows 7 を使用しています。
  2. アプリケーションをデバッグ モードで実行すると、動作します。

編集:ファイルを使用する前にスリープを追加すると、機能します:

Thread.sleep(500);

// Process source file.
try (BufferedReader bReader = new BufferedReader(new FileReader(sourceFile))) {

では、ファイルのロックを時間内に解除していない Windows である可能性はありますか? どうすれば(適切な方法で)修正できますか?

4

4 に答える 4

18

わかりました、解決策を見つけました。これが最善の方法かどうかはわかりませんが、うまくいきます。残念ながら、ファイルがまだ Windows によってロックされている場合でも、file.canRead() と file.canWrite() は両方とも true を返します。そのため、同じ名前で「名前を変更」しようとすると、Windowsが動作しているかどうかがわかることを発見しました。だからこれは私がやったことです:

    while(!sourceFile.renameTo(sourceFile)) {
        // Cannot read from file, windows still working on it.
        Thread.sleep(10);
    }
于 2013-03-20T20:43:32.663 に答える