2013-03-20 8 views
6

変更点Java7 nio2チュートリアルのWatching a Directoryは、コードサンプルWatchDir.javaを使用してディレクトリの内容全体を再帰的に監視します。Java 7 WatchService - プロセスが別のプロセスで使用されているため、ファイルにアクセスできません。

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

// 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のように可能ですか?私はそれを(正しい方法で)修正することができますか?

答えて

14

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

while(!sourceFile.renameTo(sourceFile)) { 
     // Cannot read from file, windows still working on it. 
     Thread.sleep(10); 
    } 
+0

それは回避策です:) –

+1

ニースのトリック!それは私を助けた! –

1

私は同様の問題がありました。しかし、私のファイルはコピーされているときにロックされていません。私がイベントを作成した直後にそれを読もうとしていたら、それは空でした。

あなたのケースでは、必要なトリックはなく、単にエラーを処理でき、エラーが発生した場合はスリープを実行してからやり直してください。しかし、私のためにそれは私にとっては適切ではありません。私は間違いがない。だから私はあなたの独り言を試してみました。私は読書以外の権利がないので、私にも受け入れられないと理解しました。だから私は自分の「トリック」を提案することができます。私は、クラスjava.io.RandomAccessFileを使用しています:

List<String> lines = null; 

while(true){ 
    try(RandomAccessFile raf = new RandomAccessFile(fileFullPath.toFile() , "r")){ 
     lines = Files.readAllLines(fileFullPath , Charset.forName(ENCODING)); 
     break; 
    }catch(FileNotFoundException ex){ 
     LOG.warn("File isn't yet completed: {}",ex.getMessage()); 
     LOG.info("Waiting {} for next attempt to read it" , SLEEP_INTERVAL_READING); 
     try { 
      Thread.sleep(SLEEP_INTERVAL_READING); 
     } catch (InterruptedException e) { 
      LOG.error("Waiting was interrupted",e); 
     } 
    }catch(Exception ex){ 
     LOG.error("Error in reading file ",ex); 
     clear(); 
     return false; 
    } 
} 
0

イベントのタイプがあるENTRY_MODIFYは、現在のスレッドが数秒間スリープ状態にできるようにしてください。なぜこれが起こっているのか正確にはわかりませんが、複数のENTRY_MODIFYイベントがログに記録されています。あなたのファイルサイズに依存して、スリープ時間を設定してください。

if(kind == StandardWatchEventKinds.ENTRY_MODIFY){ 
try { 
    Thread.sleep(1000); 
} catch (InterruptedException e) { 
    e.printStackTrace(); 
} 
//toDo - something 
} 
関連する問題