4

私はファイルの再帰的なコピーを行っていますが、xcopy /D新しいファイルの宛先ファイルのみをコピーしたいのと同じです(コピープロセスでいくつかのファイルを変更する必要があるため、直接使用することはできません)。xcopy

JavaではlastModified()、宛先ファイルがソースファイルよりも古く、非常に遅いかどうかを確認するために使用します。

  • プロセスを高速化できますか (おそらく JNI を使用しますか??)?
  • ジョブをより適切に実行できる他のコピー スクリプトはありますか (新しいファイルのコピー + regexp で一部のテキスト ファイルを変更)。

とにかくファイルをコピーすることはオプションではありません。これは、最終更新日を確認する (ネットワーク経由でコピーする) よりも時間がかかるためです。

4

4 に答える 4

4

なぜこんなに遅いのかを判断する必要があります。

プログラムを実行しているとき、プロセスの CPU 使用率はどのくらいですか。ユーザーが 50% を超える場合は、プログラムを最適化できるはずです。20% 未満の場合は、できることはあまりありません。

調査しているファイルがメモリではなくディスク上にあるため、通常、この方法は低速です。この場合は、ディスクへのアクセス方法を高速化するか、より高速なドライブを入手する必要があります。たとえば、SSD はこれを行うと 10 ~ 100 倍速くなります。

一括クエリが役立つ場合があります。これを行うには、複数のスレッドを使用して lastModified の日付を確認します。たとえば、固定サイズのスレッド プールを持ち、各ファイルにタスクを追加します。スレッド プールのサイズによって、一度にポーリングされるファイルの数が決まります。

これにより、OS はディスク上のレイアウトに合わせて要求を並べ替えることができます。注: これは理論上は問題ありませんが、OS/ハードウェアで速度が向上するかどうかをテストする必要があります。;)

于 2010-11-29T17:21:10.773 に答える
2

それで、ネットワークドライブでこれに出くわしました。痛い。17000以上のファイルを含むディレクトリがありました。ローカル ドライブでは、最終更新日を確認するのに 2 秒もかかりませんでした。ネットワーク ドライブでは 58 秒かかりました!!! もちろん、私のアプリはインタラクティブなアプリなので、いくつか不満がありました.

いくつかの調査の後、Windows Kernel32 findfirstfile/findnextfile/findclose を実行してプロセスを劇的に改善する JNI コードを実装することが可能であると判断しましたが、32 ビット バージョンと 64 ビット バージョンなどがありました。クロスプラットフォーム機能を失います。

ここで少し厄介なハックがありますが、私がやったことです。私のアプリは主に Windows で動作しますが、そのように制限したくなかったので、次のようにしました。Windows 上で動作しているかどうかを確認します。その場合は、ローカル ハードディスクを使用しているかどうかを確認してください。そうでない場合は、ハック的な方法を実行します。

大文字と小文字を区別せずにすべてを保存しました。'ABC' と 'abc' の両方のファイルを持つディレクトリを持つ可能性のある他の OS にとっては、おそらく良い考えではありません。これを気にする必要がある場合は、 new File("ABC") と new File("abc") を作成し、 equals メソッドを使用してそれらを比較することで決定できます。Windows のような大文字と小文字を区別しないファイル システムでは true を返しますが、UNIX システムでは false を返します。

少しハックかもしれませんが、ネットワークドライブでの所要時間は 58 秒から 1.6 秒に短縮されたので、ハックに耐えることができます。

        boolean useJaveDefaultMethod = true;

    if(System.getProperty("os.name").startsWith("Windows"))
    {
        File f2 = f.getParentFile();
        while(true)
        {
            if(f2.getParentFile() == null)
            {
                String s = FileSystemView.getFileSystemView().getSystemTypeDescription(f2);
                if(FileSystemView.getFileSystemView().isDrive(f2) && "Local Disk".equalsIgnoreCase(s))
                {
                    useJaveDefaultMethod = true;
                }
                else
                {
                    useJaveDefaultMethod = false;
                }
                break;
            }
            f2 = f2.getParentFile();
        }
    }
    if(!useJaveDefaultMethod)
    {
        try
        {
            ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/C", "dir " + f.getParent());
            pb.redirectErrorStream(true);
            Process process = pb.start();
            InputStreamReader isr = new InputStreamReader(process.getInputStream());
            BufferedReader br = new BufferedReader(isr);

            String line;
            DateFormat df = new SimpleDateFormat("dd-MMM-yy hh:mm a");
            while((line = br.readLine()) != null)
            {
                try
                {
                    Date filedate = df.parse(line);
                    String filename = line.substring(38);
                    dirCache.put(filename.toLowerCase(), filedate.getTime());
                }
                catch(Exception ex)
                {

                }
            }
            process.waitFor();

            Long filetime = dirCache.get(f.getName().toLowerCase());
            if(filetime != null)
                return filetime;

        }
        catch(Exception Exception)
        {
        }
    }

    // this is SO SLOW on a networked drive!
    long lastModifiedDate = f.lastModified();
    dirCache.put(f.getName().toLowerCase(), lastModifiedDate);

    return lastModifiedDate;
于 2015-04-17T16:40:25.967 に答える
1

残念ながら、Java が lastModified のルックアップを処理する方法は遅いです (基本的に、情報を要求すると、各ファイルの基礎となるファイル システムを照会します。listFiles などでこのデータを一括でロードすることはありません)。

これを一括で実行するために、より効率的なネイティブ プログラムを呼び出すこともできますが、そのようなソリューションはデプロイ先のプラットフォームに密接に結び付いています。

于 2010-11-29T16:34:01.437 に答える
1

ネットワーク経由でこれを行っていると思います。そうしないと、コピーにほとんど意味がありません。ネットワーク ディレクトリの操作は遅く、不運です。全体の操作にかかる時間を最小限に抑えるために、特定のサイズのしきい値を下回るファイルをいつでもコピーできます。

私はここで Kris に同意しません。Java のやり方に驚くほど非効率的なものは何もありません。

于 2010-11-30T22:22:15.183 に答える