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 は Buffer (バッファー) と Channel (チャネル) に基づいており、API は従来の IO ストリームに関連付けられた FileChannel クラスと Selector (セレクター) を提供します。ファイル チャネルは FileInputStream または FileOutputStream によって取得でき、チャネルを通じてファイルの読み取りと書き込みを行うことができます。
3. JAVA NIO では、ファイル メモリ マッピングの概念も導入されています。ほとんどの最新のオペレーティング システムは仮想メモリ マッピングをサポートしているため、カーネル空間アドレスとユーザー空間の仮想アドレスを同じ物理アドレスにマップでき、DMA ハードウェア(アクセスのみが可能)になります。物理メモリ アドレス)は、カーネル プロセスとユーザー空間プロセスの両方から見えるバッファを埋める可能性があります。以下の図に示すように
IO、BufferedIO、NIOを使用したファイルコピーの時間のかかる比較を見てみましょう: 11 MBのオーディオファイル
従来のIO方法の所要時間: 21ms
NIOファイルチャネルメソッドの使用時間-ファイル コピーの実装にかかる時間: 16 ミリ秒
NIO ファイル メモリ マッピングとファイル チャネルを使用したファイル コピーの実装にかかる時間: 7 ミリ秒
FileUtils ファイル コピー ツール クラスの使用にかかる時間: 53 ミリ秒
package com.maystar.utils;
import java.io.File ;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.MappedByteBuffer;
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();
}
}