Javaでのファイルの読み込みと出力の書き方を2度聞かれたのですが、その時は大まかに覚えただけで明確に説明できませんでしたので、今日はこの辺を特別にまとめておきたいと思います。そしてそれをみんなと共有します。
まず、一般的に使用されるファイルの読み取りおよび出力ストリームには、FileInputStream/FileOutputStream、FileReader/FileWriter、および RandomAccessFile の 3 つがあります。参考までに、簡単な例をいくつか示します:
基本記事:
1.
FileRead fr = new FileReader(filename); String s; while( (s=fr.readLine())!=null){ ... } fr.close(); //FileWriter同理,输出时可用write()函数 //Java I/O中所有的Reader、Writer都是面向字符流的输出输出
2.
FileInputStream fi =new FileInputStream(filename); int in; while( (in=fi.read())!=-1){ ... } fi.close(); //FileOutputStream同理 //Java I/O中所有的Reader、Writer都是面向字节流的输出输出
3.
RandomAccessFile ra =new RandomAccessFile(filename,"rw");//后面的参数指定的是 打开文件流的方式,“rw”是指读写,“r”是只读,Java不提供只写 ra.seek(number);//将文件指针移动到number处,这里文件指针可以理解为文件开始读的位置 ra.skipByte(number);//跳过number个字节 ra.read(); ra.close(); //RandomAccessFile既可以读也可以写,而且可以利用seek()函数指定位置
以下はBaidu百科事典からの紹介です:
RandomAccessFileはInputStreamとOutputStreamに属しませんクラス部門。実際、DataInput インターフェイスと DataOutput インターフェイス (DataInputStream と DataOutputStream もこれら 2 つのインターフェイスを実装します) を実装することを除いて、これら 2 つのクラスとは何の関係もありません。また、InputStream と OutputStream が用意した関数も使用しません。完全に独立したクラスであり、すべてのメソッド (ほとんどがそれ自体に属します) は最初から作成されます。これは、RandomAccessFile がファイル内で前後に移動できるため、その動作が他の I/O クラスとは根本的に異なるためであると考えられます。全体として、これは Object を直接継承する独立したクラスです。
上級:
nio では、Java は I/O ストリームを再実装し、速度を向上させるためにいくつかの新しいメソッドを導入します。主にチャネルとメモリマップされたファイルを紹介します
1. チャネル:
チャネルとバッファは対になっている概念であり、「Java で考える」の例は特に理解しやすいです。読みたいファイルを炭鉱、データとして扱います。私たちが望んでいる石炭です。チャネルは石炭を運ぶベルトコンベアのようなもので、ベルトコンベアから石炭を直接取り出す方法はなく、トラックを使用して石炭を積み出す必要があります。トラックは主に石炭を取り出す役割を果たします。チャネルからデータを取得し、それを作成したプログラムに渡します。チャネルと対話できる唯一のバッファーは ByteBuffer です。チャネルによってサポートされるストリームを解析する方法はバイト ストリームであることがわかります。つまり、FileInputStream/FileOutputStream、RandomAccessFile
例:
a.
FileChannel fc =new FileOutputStream(filename).getChannel(); fc.write(ByteBuffer.wrap("something test".getBytes() ));//这里使用ByteBuffer比较简单,其实ByteBuffer可以利用个put()函数写入byte数组 fc.close();
b.
fc= new FileOutputStream(filename).getChannel(); ByteBuffer buff = ByteBuffer.allocate(size);//没错,ByteBuffer是不提供显示构造函数的,想要新建一个对象必须利用allocate()函数来分配空间。 fc.read(buff); fc.close();
なぜI/Oにチャネルを使用することを考えるのですか?主な考慮事項はパフォーマンスの問題であり、チャネルとバッファです。これにより、プログラムが許可されます。一定量の文字を読み書きする場合、InputStream/OutputStream のみを使用すると、Reader/Writer は一度に 1 バイト/文字しか読み書きできません。プログラムが I/O を実行する場合、関数のこの部分 (システム コールの呼び出し) を解決するためにプログラムをオペレーティング システムに引き渡す必要があります。オペレーティング システムに引き渡される回数を減らすことで、I/O にかかる時間を効果的に削減できます。 O
2. メモリ マッピング ファイル:
メモリ マップ ファイルの主な意味は、実際にはファイルがメモリに配置され、非常に効率的な非常に大きな配列としてアクセスされることです。なぜそれが優れているのでしょうか? これは Java 仮想マシンとオペレーティング システムから始まります (実際、私はよく理解していません。ちょうどそれを明確に説明した記事を読みました。リンクは http://www.360doc.com/ です)。内容 ...) この記事では主に Java I/O の原理とメモリ マップト ファイルの原理を紹介します。要約すると、Java I/O の主な実装方法は間違いなくシステム コールを使用することであり、今回はシステム コールによって、まず使用するファイルがハードディスクからカーネルの I/O バッファに転送されます。ファイル内にさらに多くのコンテンツが必要な場合 (プログラムの局所性の原則により、より多くのコンテンツをコピーすることで効率が向上します)、それをカーネルの I/O バッファから Java にインポートします。プロセス自身のプライベートメモリ空間。メモリ マップト ファイルは、2 つのコピーの方法を放棄し、Java プロセスの仮想空間とファイル オブジェクトの間のマッピングを直接形成します。プライベート メモリ空間で目的のコンテンツが見つからない場合、ページ フォールト例外が発生します。この問題を解決するには、下位レベルのシステム コールが使用されます (実際、ページ フォールト例外処理も I/O システム コールに含まれます)。これにより、カーネル I/O バッファからプロセス プライベートへのオーバーヘッドが削減されるという利点があります。住所。
例:
FileChannel fc = new RandomAccessFile(filename,"rw").getChannel(); MappedByteBuffer mb = fc.map(FileChannel.MapMode.READ_WRITE,start,length); mb.put((byte)'x'); mb.get(); fc.close();
これを書いていて、「Kong Yiji」で「フェンネル」を書く 4 つの方法を突然思い出しました。Java でファイルを開く方法は少なくとも 5 つあり、それぞれに独自の長所と短所があります。 。これからは、ローブを着て、Java でファイルを読み書きする 5 つの方法を知っているかどうか他の人に尋ねることもできます