1. 従来の JAVA IO システムでは、ディスク ファイル データを読み取るプロセスは次のとおりです。
このクラスには read(byte b[]) メソッドがあります。保存および読み取りたいデータを取得します。 read(byte b[]) メソッドのソース コードを参照すると、内部的に readBytes(b, 0, b.length) メソッドを呼び出し、さらに readBytes(b, 0, b.length) メソッドを呼び出すことがわかります。はネイティブ メソッド (ローカル メソッド) であり、最後にこのローカル メソッドを通じてシステム コールが開始されます。つまり、システム カーネルの read() メソッドが呼び出され、カーネルはディスクからカーネル バッファにデータを読み取ります。このプロセスでは、ディスク コントローラーが DMA 操作を通じてディスクからデータを読み取り、カーネル バッファーを取得します。このプロセスは CPU に依存しません。次にユーザー プロセスは、カーネル バッファーからユーザー空間バッファーにデータをコピーします。次に、ユーザー プロセスはユーザー空間バッファーからデータを読み取ります。ユーザープロセスはハードウェアに直接アクセスできないためです。したがって、カーネルはファイルを読み取るための仲介者として機能する必要があります。
プロセス全体を以下の図に示します:
2. JAVA 1.4 以降、JAVA は NIO にファイル チャネルの概念を導入しました。従来の IO がバイト (バイト) に基づいていることです。ストリーム (ストリーム) ですが、NIO はバッファーとチャネルに基づいています。この API は、従来の IO ストリームに関連付けられた FileChannel クラスとセレクターを提供します。ファイル チャネルは FileInputStream または FileOutputStream によって取得でき、チャネルを通じてファイルの読み取りと書き込みを行うことができます。
3. JAVA NIO では、ファイル メモリ マッピングの概念も導入されています。ほとんどの最新のオペレーティング システムは、仮想メモリ マッピングをサポートしています。これにより、カーネル空間アドレスとユーザー空間の仮想アドレスを同じ物理アドレスにマップできます。ハードウェア (物理メモリ アドレスのみにアクセスできる) は、カーネル プロセスとユーザー空間プロセスの両方から見えるバッファを埋めることができます。以下の図に示すように:
IO、BufferedIO、NIO をそれぞれ使用したファイル コピーの時間のかかる比較を見てみましょう: 11 MB オーディオ ファイル
従来の IO 方法を使用したファイル コピーには時間がかかります: 21ms
NIO ファイル チャネルを使用する場合、この方法ではファイルのコピーに 16 ミリ秒かかります。NIO ファイル メモリ マッピングとファイル チャネルを使用してファイルをコピーするのにかかる時間は 7 ミリ秒です。パッケージ com.maystar.utils を使用する場合は 53 ミリ秒です。 ;
import java.io.File;
import java.io.FileInputStream;
import java.nio.channels.FileChannel;
import org.apache. commons.io.FileUtils;
public class FileCopyTest {
public static void main(String[] args) throws Exception {
String sourcePath = "F:\glzmv.mp3"
String destPath1 = "F: \glzmvCopy1.mp3";
文字列 destPath2 = "F:\glzmvCopy2.mp3";
文字列 destPath3 = = " ;
long t1 = System.currentTimeMillis();
traditionalCopy(sourcePath,destPath1);
long t2 = System.currentTimeMillis(); 1) + "ミリ秒") ; nioCopy ( ); + " ms");
long t4 = System.currentTimeMillis();
System.out.println("NIO ファイル メモリ マッピングとファイル チャネルを使用したファイル コピーの実装には時間がかかります:" + (t 4 -t3) + "ms"); nioCopy3 ( ) nioCopy3(sourcePath, destPath4); + "ms"); }
private static void nioCopy3(String sourcePath, String destPath) throws Exception { File dest = new File(destPath);// ソース コードを表示します。 io-2.4 も nio 操作を使用して nioCopy と同様の操作を実装しますが、その理由は、FileUtils.copyFile で doCopyFile を実行した後、IOUtils ツール クラスがさまざまな型に応じて対応するコンストラクターを呼び出すためです。ストリームの。
}} r r Private Static Void Niocopy2 (String SourcePath, String Destpath) が例外をスローします {
File Source = New File (SourcePath);
File Dest = New file (destpath); )) {
(宛先); FileChannelsourceCh = getChannel(); FileChannel destCh = fos.getChannel(); .map(FileChannel.MapMode.READ_ONLY, 0, sourceCh.size());
destCh.write(mbb);
destCh() .閉じる ファイルソース = 新しいファイル(ソースパス);
ファイル dest = new File(destPath);
if(!dest.exists()) {
dest.createNewFile();
}
FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(dest);
byte [] buf = 新しいバイト [fis.available()];
int len = 0;
while((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fis.close();
fos.close();
}
private static void nioCopy(String sourcePath, String destPath) throws Exception{
File source = new File(sourcePath);
ファイル dest = new File(destPath);
if(!dest.exists()) {
dest.createNewFile();
}
FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(dest);
FileChannelsourceCh = fis.getChannel();
FileChannel destCh = fos.getChannel();
destCh.transferFrom(sourceCh, 0, sourceCh.size());
sourceCh.close();
destCh.close();
}
}