1

事実:

ファイルを移動する場合、次の 2 つの可能性があります。

  1. ソース ファイルと宛先ファイルは同じパーティションにあり、ファイル システム インデックスのみが更新されます。
  2. ソースと宛先は 2 つの異なるファイル システム上にあり、ファイルはバイトごとに移動する必要があります。(別名コピーオンムーブ)

質問:

ファイルが論理的に移動されるか物理的に移動されるかをどのように判断できますか?

私は大きなファイル (700 MB 以上) を転送しており、状況ごとに異なる動作を採用しています。


編集:

一度に 1 MB ずつファイルをコピーするためのブロッキング io 呼び出しを実行するワーカー スレッドを使用して、ファイルの移動ダイアログを既にコーディングしています。残り時間や転送速度の概算などの情報をユーザーに提供します。

問題は、ファイルを物理的に移動する前に、ファイルを論理的に移動できるかどうかをどのように確認するかです。

4

2 に答える 2

4

stat()Linux またはその他の *nice では、ソース ディレクトリと宛先ディレクトリを呼び出して、それらのst_dev値を比較します。それらが同じ場合は、論理的な移動を実行できます。そうでない場合は、物理的なコピーと削除を実行する必要があります。

Windows ではGetFileInformationByHandle()、2 つのディレクトリへのハンドルを呼び出して、それらの値を比較できdwVolumeSerialNumberます。これには Windows 2000 以降が必要であることに注意してください。

Java を使用しているようです。この OS レベルの情報 (おそらく JNI?) にアクセスできるポータルが必要です。

于 2009-04-10T06:47:01.353 に答える
2

わかりました、私は何かをしています:)

JNAを使用すると、 Java からWin32 API (および *nix API も)を呼び出すことができます。

私は呼び出しを試みGetFileInformationByHandle、結果を得ましたが、dwVolumeSerialNumber属性は常に0に等しくなります(C:およびD:ドライブで試しました)

次に、MSDN でこの関数を見ました: MoveFileEx. フラグ パラメータが 0 に設定されている場合、コピー オン ムーブ機能は無効になります。そしてそれは機能します!!!!

だから私は単に電話します

if (!Kernel32.INSTANCE.MoveFileEx(source.getAbsolutePath(), destination.getAbsolutePath(), 0)) {
    System.out.println("logical move failed");
}

インターフェイスに配置するコードは次Kernel32.javaのとおりです (このファイルは、JNAサイトのダウンロード セクションにある src.zip パッケージにあります)。

boolean MoveFileEx(String lpExistingFileName, String lpNewFileName, int dwFlags);

int MOVEFILE_REPLACE_EXISTING = 0x01;
int MOVEFILE_COPY_ALLOWED = 0x02;
int MOVEFILE_CREATE_HARDLINK = 0x04;
int MOVEFILE_WRITE_THROUGH = 0x08;
int MOVEFILE_DELAY_UNTIL_REBOOT = 0x10;
int MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20;
于 2009-04-10T08:34:23.063 に答える