63405
javaでCSVファイル出力処理にて時々以下のエラーが発生しています。（週に1回ぐらいペースで）

なぜ時々だけ `java.io.FileNotFoundException` エラーが発生しているのでしょうか？  
対策方法があれば教えていただけないでしょうか？

**エラーメッセージ**

```

    java.io.FileNotFoundException: \\d\output\test.csv
     (プロセスはファイルにアクセスできません。別のプロセスが使用中です。)
    
```

**ソース** (※下記処理がサンプルコードでfor文の中で繰り返して処理を行っています）

```

        public int execute(String... args) throws Exception {
    
            // ////////////
            // 初期処理 //
            // ////////////
    
            // プロパティファイル取得
            batchProperty = getBatchProp();
    
            // ログ出力用
            Logger logger = getLogger();
    
            // バッチ開始ログ出力
            logger.log(INFO, batchProperty.getProperty("I001"));
    
            try {
    
                        // CSVのファイル名
                        String fileName = "test.csv";
                        // CSV出力先ディレクトリ取得
                        String csvDir = "D:\\batch\\output\\";
                        File csvDirectory = new File(csvDir);
    
                        // CSVディレクトリ存在チェック
                        if (!csvDirectory.exists()) {
                            // 指定されたディレクトリがない場合、エラー
                            logger.log(ERROR, MessageFormat.format(
                                    "E001", "指定されたディレクトリ(" + csvDir +")が存在しません。"));
                            // バッチ終了ログ出力
                            return 9;
                        }
    
                        // /////////////////////////
                        // 物件件数リスト取得処理 //
                        // /////////////////////////
    
                        // 物件件数リスト格納用リスト
                        List<BukkenCntCsvInfo> targetList = new ArrayList<BukkenCntCsvInfo>();
    
                        // 物件件数リストの取得
                        targetList = outputBukkenCntCsvService.selectBukkenCntList("city", "1");
    
                        // ////////////////////
                        // CSVファイル作成処理 //
                        // ////////////////////
    
                        // CSVファイルヘッダ行設定処理
                        createCsvHeader(csvDir + fileName, "city");
    
                        // CSV作成件数リセット
                        csvCount = 0;
    
                        // 取得した処理対象を1行ずつ処理
                        for (BukkenCntCsvInfo elements : targetList) {
                            // CSV作成件数カウント
                            csvCount++;
    
                            // CSVファイル作成処理
                            createCsv(elements, csvDir + fileName, "1");
                        }
    
            } catch (IOException e) {
                e.printStackTrace();
                            return 9;
    
            } catch (Exception e) {
                e.printStackTrace();
                return 9;
    
            }
            return 1;
        }
    
        /**
         * CSVファイルヘッダ行設定処理
         *
         * @throws IOException
         */
        private void createCsvHeader(String createFile, String listSb)
                throws IOException {
    
            // 出力内容の設定
            PrintWriter bukkenCntInfo = new PrintWriter(new BufferedWriter(
                    new OutputStreamWriter(new FileOutputStream(createFile, false),
                            "SJIS")));
            bukkenCntInfo.print("\"");
            bukkenCntInfo.print("都道府県名");
            bukkenCntInfo.print("\"");
            bukkenCntInfo.print(",");
            bukkenCntInfo.print("\"");
            bukkenCntInfo.print("物件件数");
            bukkenCntInfo.print("\"");
            bukkenCntInfo.println();
            bukkenCntInfo.close();
        }
    
        /**
         * CSVファイルデータ設定処理
         *
         * @throws IOException
         */
        private void createCsv(BukkenCntCsvInfo target, String createFile, String listSb)
                throws IOException {
    
            // 出力内容の設定
            PrintWriter bukkenCntInfo = new PrintWriter(new BufferedWriter(
                    new OutputStreamWriter(new FileOutputStream(createFile, true),
                            "SJIS")));
    
            bukkenCntInfo.print("\"");
            bukkenCntInfo.print(target.sTodoufukenName);
            bukkenCntInfo.print("\"");
            bukkenCntInfo.print(",");
            bukkenCntInfo.print("\"");
            bukkenCntInfo.print(target.nCount);
            bukkenCntInfo.print("\"");
            bukkenCntInfo.println();
            bukkenCntInfo.close();
        }
    
```
CC BY-SA 4.0
2020-02-26T06:58:09.567
63369
2020-02-27T11:04:58.873
2020-02-26T08:47:26.750
3060
37973
question
java
java.io.FileNotFoundException: (プロセスはファイルにアクセスできません。別のプロセスが使用中です。)
解決するか自信がないですが、close()処理を呼ばなくても自動で行うように、ということでtry-with-resourecesで書いてみます。

```

    private void createCsv(BukkenCntCsvInfo target, String createFile, String listSb)
            throws IOException {
    
        // 出力内容の設定
        try (PrintWriter bukkenCntInfo = new PrintWriter(new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(createFile, true),
                        "SJIS")))) {
    
            bukkenCntInfo.print("\"");
            bukkenCntInfo.print(target.sTodoufukenName);
            bukkenCntInfo.print("\"");
            bukkenCntInfo.print(",");
            bukkenCntInfo.print("\"");
            bukkenCntInfo.print(target.nCount);
            bukkenCntInfo.print("\"");
            bukkenCntInfo.println();
        } catch (Exception e) {
            throw e;
        }
    }
    
```
CC BY-SA 4.0
2020-02-27T07:28:45.850
63405
2020-02-27T07:28:45.850
9515
63369
answer
はじめまして、こんにちは。

まず前提ですが、このエラーはJavaによるものではなくWindowsが戻しているものとなります。  
文章のとおり他のプロセスが、ファイルハンドルを開いているため  
ファイルを開くことができないのが原因です。これにはいろいろな原因が考えられます。

  * 正常にファイルが閉じられていない
  * 途中でプロセスが止まったので開いたままになっている
  * 共有経由で他のユーザーやウィルス対策などのツールがファイルを開いている

これを回避するには以下の手段が考えられると思います

  * きちんとファイルを閉じる  
=> ただしコメントでふれらている通りどうしようもないケースもあります

  * 出力ファイル名を日付や現在時刻などを利用して毎回変える  
=> ファイル名が変化するので共有している場合問題になるかもしれません

  * 同時アクセスを制御できるようなシステム上に処理をくみ上げる  
=> サーブレットでCSVを出力してメモリサーバーに保持、共有はURLを介して行うなど
CC BY-SA 4.0
2020-02-27T11:04:58.873
63409
2020-02-27T11:04:58.873
37777
63369
answer