程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> JAVA NIO FileChannel 內存映射文件,niofilechannel

JAVA NIO FileChannel 內存映射文件,niofilechannel

編輯:JAVA綜合教程

JAVA NIO FileChannel 內存映射文件,niofilechannel


 

 

文件通道總是阻塞式的。 文件通道不能創建,只能通過(RandomAccessFile、FileInputStream、FileOutputStream)getChannel()獲得,具有與File形同的訪問權限。 線程安全。   文件鎖:鎖的對象是文件。
  1 package org.windwant.nio;
  2 
  3 
  4 import java.io.File;
  5 import java.io.FileNotFoundException;
  6 import java.io.IOException;
  7 import java.io.RandomAccessFile;
  8 import java.nio.ByteBuffer;
  9 import java.nio.MappedByteBuffer;
 10 import java.nio.channels.Channel;
 11 import java.nio.channels.FileChannel;
 12 import java.nio.channels.FileLock;
 13 import java.nio.channels.Selector;
 14 import java.util.concurrent.locks.ReadWriteLock;
 15 import java.util.concurrent.locks.ReentrantReadWriteLock;
 16 
 17 /**
 18  * Created by windwant on 2016/5/13.
 19  */
 20 public class NIOOpt {
 21 
 22     public static void main(String[] args) {
 23         try {
 24             MappedPrivateChannel();
 25         } catch (Exception e) {
 26             e.printStackTrace();
 27         }
 28     }
 29 
 30     /**
 31      * MapMode.PRIVATE 寫時拷貝(copy-on-write)映射:通過put()修改的任何修改,會導致產生一個私有的數據
 32      * 拷貝,寶貝中的數據只有MappedByteBuffer實例可以看到。不會對底層文件做任何修改。若緩沖區被回收,修改丟
 33      * 失,read/write方式建立通道。
 34      * 做修改,拷貝副本前,其它方式的映射區的修改,會反映到當前區域。映射相互的修改不可見
 35      * 允許父子進程共享內存頁
 36      * 處理一個文件多個映射場景。
 37      * 關閉通道,映射會保持。除非丟棄緩沖區本身。
 38      * MappedByteBuffer 對象是直接的,占用的內存位於jvm堆棧之外。
 39      */
 40     public static void MappedPrivateChannel() throws Exception {
 41         // Create a temp file and get a channel connected to it
 42         File tempFile = File.createTempFile ("mmaptest", null);
 43         RandomAccessFile file = new RandomAccessFile (tempFile, "rw");
 44         FileChannel channel = file.getChannel( );
 45         ByteBuffer temp = ByteBuffer.allocate (100);
 46         // Put something in the file, starting at location 0
 47         temp.put ("This is the file content".getBytes( ));
 48         temp.flip( );
 49         channel.write (temp, 0);
 50         // Put something else in the file, starting at location 8192.
 51         // 8192 is 8 KB, almost certainly a different memory/FS page.
 52         // This may cause a file hole, depending on the
 53         // filesystem page size.
 54         temp.clear( );
 55         temp.put ("This is more file content".getBytes( ));
 56         temp.flip( );
 57         channel.write (temp, 8192);
 58         // Create three types of mappings to the same file
 59         MappedByteBuffer ro = channel.map (
 60                 FileChannel.MapMode.READ_ONLY, 0, channel.size( ));
 61         MappedByteBuffer rw = channel.map (
 62                 FileChannel.MapMode.READ_WRITE, 0, channel.size( ));
 63         MappedByteBuffer cow = channel.map (
 64                 FileChannel.MapMode.PRIVATE, 0, channel.size( ));
 65         // the buffer states before any modifications
 66         System.out.println ("Begin");
 67         showBuffers (ro, rw, cow);
 68         // Modify the copy-on-write buffer
 69         cow.position (8);
 70         cow.put ("COW".getBytes( ));
 71         System.out.println ("Change to COW buffer");
 72         showBuffers (ro, rw, cow);
 73         // Modify the read/write buffer92
 74         rw.position (9);
 75         rw.put (" R/W ".getBytes( ));
 76         rw.position (8194);
 77         rw.put (" R/W ".getBytes( ));
 78         rw.force( );
 79         System.out.println ("Change to R/W buffer");
 80         showBuffers (ro, rw, cow);
 81         // Write to the file through the channel; hit both pages
 82         temp.clear( );
 83         temp.put ("Channel write ".getBytes( ));
 84         temp.flip( );
 85         channel.write (temp, 0);
 86         temp.rewind( );
 87         channel.write (temp, 8202);
 88         System.out.println ("Write on channel");
 89         showBuffers (ro, rw, cow);
 90         // Modify the copy-on-write buffer again
 91         cow.position (8207);
 92         cow.put (" COW2 ".getBytes( ));
 93         System.out.println ("Second change to COW buffer");
 94         showBuffers (ro, rw, cow);
 95         // Modify the read/write buffer
 96         rw.position (0);
 97         rw.put (" R/W2 ".getBytes( ));
 98         rw.position (8210);
 99         rw.put (" R/W2 ".getBytes( ));
100         rw.force( );
101         System.out.println ("Second change to R/W buffer");
102         showBuffers (ro, rw, cow);
103         // cleanup
104         channel.close( );
105         file.close( );
106         tempFile.delete( );
107     }
108 
109     // Show the current content of the three buffers
110     public static void showBuffers (ByteBuffer ro, ByteBuffer rw, ByteBuffer cow) throws Exception{
111         dumpBuffer ("R/O", ro);
112         dumpBuffer ("R/W", rw);
113         dumpBuffer ("COW", cow);
114         System.out.println ("");
115     }
116     // Dump buffer content, counting and skipping nulls
117     public static void dumpBuffer (String prefix, ByteBuffer buffer) throws Exception {
118         System.out.print (prefix + ": '");
119         int nulls = 0;
120         int limit = buffer.limit( );
121         for (int i = 0; i < limit; i++) {
122             char c = (char) buffer.get (i);
123             if (c == '\u0000') {
124                 nulls++;
125                 continue;
126             }
127             if (nulls != 0) {
128                 System.out.print ("|[" + nulls
129                         + " nulls]|");
130                 nulls = 0;
131             }
132             System.out.print (c);
133         }
134         System.out.println ("'");
135     }
136 
137     /**
138      * channel Gather/Scatter 矢量IO
139      */
140     public static void channelGatherScatter(){
141         ByteBuffer head = ByteBuffer.allocate(4);
142         ByteBuffer body = ByteBuffer.allocate(100);
143         RandomAccessFile afile = null;
144         RandomAccessFile bfile = null;
145         ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
146         try {
147             afile = new RandomAccessFile("hello.txt", "r");
148             bfile = new RandomAccessFile("hehe.txt", "rw");
149             readWriteLock.readLock().lock();
150             FileChannel fileChannel = afile.getChannel();
151             ByteBuffer[] buffers = {head, body};
152             while (fileChannel.read(buffers) != -1){
153             }
154             head.flip();
155             body.flip();
156             System.out.println(new String(head.array()));
157             System.out.println(new String(body.array()));
158             readWriteLock.readLock().unlock();
159             fileChannel.close();
160             afile.close();
161 
162             readWriteLock.writeLock().lock();
163             FileChannel bfileChannel = bfile.getChannel();
164 
165             while (bfileChannel.write(buffers) > 0){
166             }
167 
168             bfileChannel.position(bfileChannel.position() + 10);
169             bfileChannel.write(ByteBuffer.wrap("THIS IS THE TEST TEXT!".getBytes()));
170             bfileChannel.truncate(3); //改變文件大小
171             bfileChannel.force(true); //寫入磁盤文件 參數 是否更新文件元數據(所有者、訪問權限等)
172             readWriteLock.writeLock().unlock();
173             bfileChannel.close();
174             bfile.close();
175         }catch (Exception e){
176             e.printStackTrace();
177         }
178     }
179 
180     /**
181      * 基於MappedFileChannle的文件復制
182      * 文件鎖
183      */
184     public static void mappedFileChannelLock(){
185         RandomAccessFile afile = null;
186         RandomAccessFile bfile = null;
187         FileChannel fc = null;
188         FileChannel fcb = null;
189         try {
190             afile = new RandomAccessFile("hello.txt", "rw");
191             fc = afile.getChannel();
192             long length = fc.size();
193             FileLock fileLock = fc.tryLock(0, length, true);//true共享鎖 false 獨占鎖 從開始 鎖定全部內容 如果獲取不到鎖會返回null
194             if(null != fileLock) {
195                 MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, length);
196                 byte[] fbo = new byte[(int) length];
197                 mbb.get(fbo);
198                 System.out.println(new String(fbo, "UTF-8"));
199                 fileLock.release();
200                 bfile = new RandomAccessFile("hehe.txt", "rw");
201                 fcb = bfile.getChannel();
202                 fileLock = fcb.tryLock(0, length, false);
203                 MappedByteBuffer mbbb = fcb.map(FileChannel.MapMode.READ_WRITE, 0, length);
204 
205                 for (int i = 0; i < length; i++) {
206                     mbbb.put(i, fbo[i]);
207                 }
208                 mbbb.flip();
209                 mbbb.force();
210                 fileLock.release();
211             }
212         } catch (FileNotFoundException e) {
213             e.printStackTrace();
214         } catch (IOException e) {
215             e.printStackTrace();
216         }finally {
217             try {
218                 fc.close();
219                 fcb.close();
220                 afile.close();
221                 bfile.close();
222             } catch (IOException e) {
223                 e.printStackTrace();
224             }
225         }
226     }
227 
228     /**
229      * MappedByteBuffer map(MapMode mode, long position, long size)
230      * size大於文件大小,文件會做擴充
231      * MappedByteBuffer 內存映射緩沖池
232      * 基於MappedFileChannle的文件復制
233      * 讀寫鎖
234      * 直接讀取,修改磁盤上的文件。
235      * 自動緩存內存頁,比較高效。
236      */
237     public static void mappedFileChannel(){
238         RandomAccessFile afile = null;
239         RandomAccessFile bfile = null;
240         FileChannel fc = null;
241         FileChannel fcb = null;
242         ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
243         try {
244             afile = new RandomAccessFile("hello.txt", "rw");
245             readWriteLock.readLock().lock();
246             fc = afile.getChannel();
247             long length = fc.size();
248             MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, length);
249             byte[] fbo = new byte[(int) length];
250             mbb.get(fbo);
251             System.out.println(new String(fbo));
252             readWriteLock.readLock().unlock();
253             bfile = new RandomAccessFile("hehe.txt", "rw");
254             readWriteLock.writeLock().lock();
255             fcb = bfile.getChannel();
256             MappedByteBuffer mbbb = fcb.map(FileChannel.MapMode.READ_WRITE, 0, length);
257 
258             for (int i = 0; i < length; i++) {
259                 mbbb.put(i, fbo[i]);
260             }
261             mbbb.flip();
262             mbbb.force();
263             readWriteLock.writeLock().unlock();
264         } catch (FileNotFoundException e) {
265             e.printStackTrace();
266         } catch (IOException e) {
267             e.printStackTrace();
268         }finally {
269             try {
270                 fc.close();
271                 fcb.close();
272                 afile.close();
273                 bfile.close();
274             } catch (IOException e) {
275                 e.printStackTrace();
276             }
277         }
278     }
279 
280     /**
281      * FileChannel文件讀取
282      */
283     public static void fileChannel(){
284         try {
285             RandomAccessFile afile = new RandomAccessFile("hello.txt", "rw");
286             FileChannel fc = afile.getChannel();
287             ByteBuffer bb = ByteBuffer.allocate(48);
288             int byteRead;
289             while ((byteRead = fc.read(bb)) != -1){//確保讀完
290                 System.out.println("read:" + byteRead);
291                 bb.flip();//翻轉為讀狀態
292                 while (bb.hasRemaining()){//直到沒有可讀的字節
293                     System.out.println(String.valueOf(bb.get()));
294                 }
295                 bb.clear();
296             }
297             fc.close();
298             afile.close();
299         } catch (FileNotFoundException e) {
300             e.printStackTrace();
301         } catch (IOException e) {
302             e.printStackTrace();
303         }
304     }
305 
306     /**
307      * 基於FileChannel transferTo transferFrom 方法文件復制
308      */
309     public static void fileTransfer(){
310         try {
311             RandomAccessFile afile = new RandomAccessFile("hello.txt", "rw");
312             RandomAccessFile bfile = new RandomAccessFile("hehe.txt", "rw");
313             FileChannel ac = afile.getChannel();
314             FileChannel bc = bfile.getChannel();
315             long position = 0;
316             long count = ac.size();
317 //            bc.transferFrom(ac, position, count);
318             ac.transferTo(position, count, bc);
319             ac.close();
320             afile.close();
321             bc.close();
322             bfile.close();
323         } catch (FileNotFoundException e) {
324             e.printStackTrace();
325         } catch (IOException e) {
326             e.printStackTrace();
327         }
328     }
329 
330     public static void fileSelector(){
331         try {
332             RandomAccessFile afile = new RandomAccessFile("hello.txt", "rw");
333             Channel c = afile.getChannel();
334             Selector s = Selector.open();
335         } catch (FileNotFoundException e) {
336             e.printStackTrace();
337         } catch (IOException e) {
338             e.printStackTrace();
339         }
340     }
341 
342     /**
343      * 基於基本channel buffer的文件復制操作
344      */
345     public static void fileTransferByNormal() {
346         try {
347             RandomAccessFile afile = new RandomAccessFile("hello.txt", "rw");
348             RandomAccessFile bfile = new RandomAccessFile("hehe.txt", "rw");
349             FileChannel ac = afile.getChannel();
350             FileChannel bc = bfile.getChannel();
351 
352             ByteBuffer bf = ByteBuffer.allocateDirect(16 * 1024);
353             while (ac.read(bf) != -1) {
354                 bf.flip();
355                 while (bf.hasRemaining()) {//確保寫完
356                     bc.write(bf);
357                 }
358                 bf.clear();
359             }
360             ac.close();
361             afile.close();
362             bc.close();
363             bfile.close();
364         } catch (FileNotFoundException e) {
365             e.printStackTrace();
366         } catch (IOException e) {
367             e.printStackTrace();
368         }
369     }
370 }

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved