精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Java文件的簡單讀寫、隨機讀寫、NIO讀寫與使用MappedByteBuffer讀寫

開發 后端
文件與目錄的創建和刪除較為簡單,因此忽略這部分內容的介紹,我們重點學習文件的讀寫。

 [[383912]]

 

文件與目錄的創建和刪除較為簡單,因此忽略這部分內容的介紹,我們重點學習文件的讀寫。本篇內容包括:

  • 簡單文件讀寫
  • 隨機訪問文件讀寫
  • NIO文件讀寫-FileChannel
  • 使用MappedByteBuffer讀寫文件

簡單文件讀寫

FileOutputStream

由于流是單向的,簡單文件寫可使用FileOutputStream,而讀文件則使用FileInputStream。

任何數據輸出到文件都是以字節為單位輸出,包括圖片、音頻、視頻。以圖片為例,如果沒有圖片格式解析器,那么圖片文件其實存儲的就只是按某種格式存儲的字節數據罷了。

FileOutputStream指文件字節輸出流,用于將字節數據輸出到文件,僅支持順序寫入、支持以追加方式寫入,但不支持在指定位置寫入。

打開一個文件輸出流并寫入數據的示例代碼如下。

  1. public class FileOutputStreamStu{ 
  2.     public void testWrite(byte[] data) throws IOException {                     
  3.         try(FileOutputStream fos = new FileOutputStream("/tmp/test.file",true)) { 
  4.             fos.write(data); 
  5.             fos.flush(); 
  6.         } 
  7.     } 

注意,如果不指定追加方式打開流,new FileOutputStream時會導致文件內容被清空,而FileOutputStream的默認構建函數是以非追加模式打開流的。

FileOutputStream的參數1為文件名,參數2為是否以追加模式打開流,如果為true,則字節將寫入文件的尾部而不是開頭。

調用flush方法目的是在流關閉之前清空緩沖區數據,實際上使用FileOutputStream并不需要調用flush方法,此處的刷盤指的是將緩存在JVM內存中的數據調用系統函數write寫入。如BufferedOutputStream,在調用BufferedOutputStream方法時,如果緩存未滿,實際上是不會調用系統函數write的,如下代碼所示。

  1. public class BufferedOutputStream extends FilterOutputStream { 
  2.     public synchronized void write(byte b[], int offint len) throws IOException { 
  3.         if (len >= buf.length) { 
  4.             flushBuffer(); 
  5.             out.write(b, off, len); 
  6.             return
  7.         } 
  8.         if (len > buf.length - count) { 
  9.             flushBuffer(); 
  10.         } 
  11.         System.arraycopy(b, off, buf, count, len); // 只寫入緩存 
  12.         count += len; 
  13.     } 

FileInputStream

FileInputStream指文件字節輸入流,用于將文件中的字節數據讀取到內存中,僅支持順序讀取,不可跳躍讀取。

打開一個文件輸入流讀取數據的案例代碼如下。

  1. public class FileInputStreamStu{ 
  2.     public void testRead() throws IOException {     
  3.         try (FileInputStream fis = new FileInputStream("/tmp/test/test.log")) { 
  4.             byte[] buf = new byte[1024]; 
  5.             int realReadLength = fis.read(buf); 
  6.         } 
  7.     } 

其中buf數組中下標從0到realReadLength的字節數據就是實際讀取的數據,如果realReadLength返回-1,則說明已經讀取到文件尾并且未讀取到任何數據。

當然,我們還可以一個字節一個字節的讀取,如下代碼所示。

  1. public class FileInputStreamStu{ 
  2.     public void testRead() throws IOException {      
  3.         try (FileInputStream fis = new FileInputStream("/tmp/test/test.log")) { 
  4.             int byteData = fis.read(); // 返回值取值范圍:[-1,255] 
  5.             if (byteData == -1) { 
  6.                 return; // 讀取到文件尾了 
  7.             } 
  8.             byte data = (byte) byteData; 
  9.             // data為讀取到的字節數據 
  10.         } 
  11.     } 

至于讀取到的字節數據如何使用就需要看你文件中存儲的是什么數據了。

如果整個文件存儲的是一張圖片,那么需要將整個文件讀取完,再按格式解析成圖片,而如果整個文件是配置文件,則可以一行一行讀取,遇到\n換行符則為一行,代碼如下。

  1. public class FileInputStreamStu{ 
  2.     @Test 
  3.     public void testRead() throws IOException { 
  4.         try (FileInputStream fis = new FileInputStream("/tmp/test/test.log")) { 
  5.             ByteBuffer buffer = ByteBuffer.allocate(1024); 
  6.             int byteData; 
  7.             while ((byteData = fis.read()) != -1) { 
  8.                 if (byteData == '\n') { 
  9.                     buffer.flip(); 
  10.                     String line = new String(buffer.array(), buffer.position(), buffer.limit()); 
  11.                     System.out.println(line); 
  12.                     buffer.clear(); 
  13.                     continue
  14.                 } 
  15.                 buffer.put((byte) byteData); 
  16.             } 
  17.         } 
  18.     } 

Java基于InputStream、OutputStream還提供了很多的API方便讀寫文件,如BufferedReader,但如果懶得去記這些API的話,只需要記住FileInputStream與FileOutputStream就夠了。

隨機訪問文件讀寫

RandomAccessFile相當于是FileInputStream與FileOutputStream的封裝結合,即可以讀也可以寫,并且RandomAccessFile支持移動到文件指定位置處開始讀或寫。

RandomAccessFile的使用如下。

  1. public class RandomAccessFileStu{ 
  2.     public void testRandomWrite(long index,long offset){ 
  3.         try (RandomAccessFile randomAccessFile = new RandomAccessFile("/tmp/test.idx""rw")) { 
  4.             randomAccessFile.seek(index * indexLength()); 
  5.             randomAccessFile.write(toByte(index)); 
  6.             randomAccessFile.write(toByte(offset)); 
  7.         } 
  8.     } 

RandomAccessFile構建方法:參數1為文件路徑,參數2為模式,'r'為讀,'w'為寫;

seek方法:在linux、unix操作系統下就是調用系統的lseek函數。

RandomAccessFile的seek方法通過調用native方法實現,源碼如下。

  1. JNIEXPORT void JNICALL 
  2. Java_java_io_RandomAccessFile_seek0(JNIEnv *env, 
  3.                     jobject this, jlong pos) { 
  4.     FD fd; 
  5.     fd = GET_FD(this, raf_fd); 
  6.     if (fd == -1) { 
  7.         JNU_ThrowIOException(env, "Stream Closed"); 
  8.         return
  9.     } 
  10.     if (pos < jlong_zero) { 
  11.         JNU_ThrowIOException(env, "Negative seek offset"); 
  12.     } 
  13.     // #define IO_Lseek lseek 
  14.     else if (IO_Lseek(fd, pos, SEEK_SET) == -1) { 
  15.         JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 
  16.     } 

Java_java_io_RandomAccessFile_seek0函數的參數1表示RandomAccessFile對象,參數2表示偏移量。函數中調用的IO_Lseek方法實際是操作系統的lseek方法。

RandomAccessFile提供的讀、寫、指定偏移量其實都是通過調用操作系統函數完成的,包括前面介紹的文件輸入流和文件輸出流也不例外。

NIO文件讀寫-FileChannel

Channel(通道)表示IO源與目標打開的連接,Channel類似于傳統的流,但Channel本身不能直接訪問數據,只能與Buffer進行交互。Channel(通道)主要用于傳輸數據,從緩沖區的一側傳到另一側的實體(如File、Socket),支持雙向傳遞。

正如SocketChannel是客戶端與服務端通信的通道,FileChannel就是我們讀寫文件的通道。FileChannel是線程安全的,也就是一個FileChannel可以被多個線程使用。對于多線程操作,同時只會有一個線程能對該通道所在文件進行修改。如果需要確保多線程的寫入順序,就必須要轉為隊列寫入。

FileChannel可通過FileOutputStream、FileInputStream、RandomAccessFile獲取,也可以通過FileChannel#open方法打開一個通道。

以通過FileOutputStream獲取FileChannel為例,通過FileOutputStream或RandomAccessFile獲取FileChannel方法相同,代碼如下。

  1. public class FileChannelStu{ 
  2.     public void testGetFileCahnnel(){ 
  3.         try(FileOutputStream fos = new FileOutputStream("/tmp/test.log"); 
  4.             FileChannel fileChannel = fos.getChannel()){ 
  5.            // do....    
  6.         }catch (IOException exception){ 
  7.         } 
  8.     } 

需要注意,通過FileOutputStream獲取的FileChannel只能執行寫操作,通過FileInputStream獲取的FileChannel只能執行讀操作,原因可查看getChannel方法源碼。

通過FileOutputStream或FileInputStream或RandomAccessFile打開的FileChannel,在流關閉時也會被關閉,可查看這幾個類的close方法源碼。

若想要獲取一個同時支持讀和寫的FileChannel需要通過open方法打開,代碼如下。

  1. public class FileChannelStu{ 
  2.     public void testOpenFileCahnnel(){ 
  3.         FileChannel channel = FileChannel.open
  4.                             Paths.get(URI.create("file:" + rootPath + "/" + postion.fileName)), 
  5.                             StandardOpenOption.READ,StandardOpenOption.WRITE); 
  6.         // do.... 
  7.         channel.close(); 
  8.     } 

open方法第二個變長參數傳StandardOpenOption.READ和StandardOpenOption.WRITE即可打開一個雙向讀寫的通道。

FileChannel允許對文件加鎖,文件鎖是進程級別的,不是線程級別的,文件鎖可以解決多個進程并發訪問、修改同一個文件的問題。文件鎖會被當前進程持有,一旦獲取到文件鎖就要調用一次release釋放鎖,當關閉對應的FileChannel對象時或當前JVM進程退出時,鎖也會自動被釋鎖。

文件鎖的使用案例代碼如下。

  1. public class FileChannelStu{ 
  2.     public void testFileLock(){ 
  3.         FileChannel channel = this.channel; 
  4.         FileLock fileLock = null
  5.         try { 
  6.             fileLock = channel.lock();// 獲取文件鎖 
  7.             // 執行寫操作 
  8.             channel.write(...); 
  9.             channel.write(...); 
  10.         } finally { 
  11.             if (fileLock != null) { 
  12.                 fileLock.release(); // 釋放文件鎖 
  13.             } 
  14.         } 
  15.     } 

當然,只要我們能確保同時只有一個進程對文件執行寫操作,那么就不需要鎖文件。RocketMQ也并沒有使用文件鎖,因為每個Broker有自己數據目錄,即使一臺機器上部署多個Broker也不會有多個進程對同一個日記文件操作的情況。

上面例子去掉文件鎖后代碼如下。

  1. public class FileChannelStu{ 
  2.     public void testWrite(){ 
  3.         FileChannel channel = this.channel; 
  4.         channel.write(...); 
  5.         channel.write(...); 
  6.     } 

這里還存在一個問題,就是并發寫數據問題。雖然FileChannel是線程安全的,但兩次write并不是原子性操作,如果要確保兩次write是連續寫入的,還必須要加鎖。在RocketMQ中,通過引用計數器替代了鎖。

FileChannel提供的force方法用于刷盤,即調用操作系統的fsync函數,使用如下。

  1. public class FileChannelStu{ 
  2.     public void closeChannel(){ 
  3.         this.channel.force(true); 
  4.         this.channel.close(); 
  5.     }         

force方法的參數表示除強制寫入內容更改外,文件元數據的更改是否也強制寫入。后面使用MappedByteBuffer時,可直接使用MappedByteBuffer的force方法。

FileChannel的force方法最終調用的C方法源碼如下:

  1. JNIEXPORT jint JNICALL 
  2. Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this, 
  3.                                           jobject fdo, jboolean md) 
  4.     jint fd = fdval(env, fdo); 
  5.     int result = 0; 
  6.     if (md == JNI_FALSE) { 
  7.         result = fdatasync(fd); 
  8.     } else { 
  9.         result = fsync(fd); 
  10.     } 
  11.     return handle(env, result, "Force failed"); 

參數md對應調用force方法傳遞的metaData參數。

使用FileChannel支持seek(position)到指定位置讀或寫數據,代碼如下。

  1. public class FileChannelStu{ 
  2.     public void testSeekWrite(){ 
  3.         FileChannel channel = this.channel; 
  4.         synchronized (channel) {  
  5.             channel.position(100); 
  6.             channel.write(ByteBuffer.wrap(toByte(index))); 
  7.             channel.write(ByteBuffer.wrap(toByte(offset))); 
  8.         } 
  9.     } 

上述例子的作用是將指針移動到物理偏移量100byte位置處,順序寫入index和offset。讀取同理,代碼如下。

  1. public class FileChannelStu{ 
  2.     public void testSeekRead(){ 
  3.         FileChannel channel = this.channel; 
  4.         synchronized (channel) {  
  5.             channel.position(100); 
  6.             ByteBuffer buffer = ByteBuffer.allocate(16); 
  7.             int realReadLength = channel.read(buffer);  
  8.             if(realReadLength==16){ 
  9.                 long index = buffer.getLong(); 
  10.                 long offset = buffer.getLong(); 
  11.             } 
  12.         } 
  13.     } 

其中read方法返回的是實際讀取的字節數,如果返回-1則代表已經是文件尾部了,沒有剩余內容可讀取。

使用MappedByteBuffer讀寫文件

MappedByteBuffer是Java提供的基于操作系統虛擬內存映射(MMAP)技術的文件讀寫API,底層不再通過read、write、seek等系統調用實現文件的讀寫。

我們需要通過FileChannel#map方法將文件的一個區域映射到內存中,代碼如下。

  1. public class MappedByteBufferStu{ 
  2.   @Test 
  3.   public void testMappedByteBuffer() throws IOException { 
  4.       FileChannel fileChannel = FileChannel.open(Paths.get(URI.create("file:/tmp/test/test.log")), 
  5.                 StandardOpenOption.WRITE, StandardOpenOption.READ); 
  6.       MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 4096); 
  7.       fileChannel.close(); 
  8.       mappedByteBuffer.position(1024); 
  9.       mappedByteBuffer.putLong(10000L); 
  10.       mappedByteBuffer.force();     
  11.   } 

上面代碼的功能是通過FileChannel將文件[0~4096)區域映射到內存中,調用FileChannel的map方法返回MappedByteBuffer,在映射之后關閉通道,隨后在指定位置處寫入一個8字節的long類型整數,最后調用force方法將寫入數據從內存寫回磁盤(刷盤)。

映射一旦建立了,就不依賴于用于創建它的文件通道,因此在創建MappedByteBuffer之后我們就可以關閉通道了,對映射的有效性沒有影響。

實際上將文件映射到內存比通過read、write系統調用方法讀取或寫入幾十KB的數據要昂貴,從性能的角度來看,MappedByteBuffer適合用于將大文件映射到內存中,如上百M、上GB的大文件。

FileChannel的map方法有三個參數:

  • MapMode:映射模式,可取值有READ_ONLY(只讀映射)、READ_WRITE(讀寫映射)、PRIVATE(私有映射),READ_ONLY只支持讀,READ_WRITE支持讀寫,而PRIVATE只支持在內存中修改,不會寫回磁盤;
  • position和size:映射區域,可以是整個文件,也可以是文件的某一部分,單位為字節。

需要注意的是,如果FileChannel是只讀模式,那么map方法的映射模式就不能指定為READ_WRITE。如果文件是剛剛創建的,只要映射成功,文件的大小就會變成(0+position+size)。

通過MappedByteBuffer讀取數據示例如下:

  1. public class MappedByteBufferStu{ 
  2.     @Test 
  3.     public void testMappedByteBufferOnlyRead() throws IOException { 
  4.         FileChannel fileChannel = FileChannel.open(Paths.get(URI.create("file:/tmp/test/test.log")), 
  5.                     StandardOpenOption.READ); 
  6.         MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, 4096); 
  7.         fileChannel.close(); 
  8.         mappedByteBuffer.position(1024); 
  9.         long value = mappedByteBuffer.getLong(); 
  10.         System.out.println(value); 
  11.     } 

mmap繞過了read、write系統函數調用,繞過了一次數據從內核空間到用戶空間的拷貝,即實現零拷貝,MappedByteBuffer使用直接內存而非JVM的堆內存。

mmap只是在虛擬內存分配了地址空間,只有在第一次訪問虛擬內存的時候才分配物理內存。在mmap之后,并沒有將文件內容加載到物理頁上,而是在虛擬內存中分配地址空間,當進程在訪問這段地址時,通過查找頁表,發現虛擬內存對應的頁沒有在物理內存中緩存則產生缺頁中斷,由內核的缺頁異常處理程序處理,將文件對應內容以頁為單位(4096)加載到物理內存中。

由于物理內存是有限的,mmap在寫入數據超過物理內存時,操作系統會進行頁置換,根據淘汰算法,將需要淘汰的頁置換成所需的新頁,所以mmap對應的內存是可以被淘汰的,被淘汰的內存頁如果是臟頁(有過寫操作修改頁內容),則操作系統會先將數據回寫磁盤再淘汰該頁。

數據寫過程如下:

  • 1.將需要寫入的數據寫到對應的虛擬內存地址;
  • 2.若對應的虛擬內存地址未對應物理內存,則產生缺頁中斷,由內核加載頁數據到物理內存;
  • 3.數據被寫入到虛擬內存對應的物理內存;
  • 4.在發生頁淘汰或刷盤時由操作系統將臟頁回寫到磁盤。

RocketMQ正是利用MappedByteBuffer實現索引文件的讀寫,實現一個基于文件系統的HashMap。

RocketMQ在創建新的CommitLog文件并通過FileChannel獲取MappedByteBuffer時會做一次預熱操作,即每個虛擬內存頁(Page Cache)都寫入四個字節的0x00,并強制刷盤將數據寫到文件中。這個動作的用處是通過讀寫操作把MMAP映射全部加載到物理內存中。并且在預熱之后還做了一個鎖住內存的操作,這是為了避免磁盤交換,防止操作系統把預熱過的頁臨時保存到swap區,防止程序再次讀取交換出去的數據頁時產生缺頁中斷。

參考文獻

【深入淺出Linux】關于mmap的解析

本文轉載自微信公眾號「Java藝術」,可以通過以下二維碼關注。轉載本文請聯系Java藝術公眾號。

 

責任編輯:武曉燕 來源: Java藝術
相關推薦

2011-11-17 15:30:34

JavaNIOIO

2025-02-04 17:24:22

2021-08-05 10:00:02

Python編程語言

2022-02-14 15:07:48

進程FileChanne線程

2013-05-27 10:58:10

propertiesJava語言

2023-08-03 07:30:01

JavaNIO庫

2010-11-19 11:32:25

Oracle存儲過程

2010-07-16 09:06:57

Perl文件

2010-11-19 10:57:43

Oracle讀寫文件

2021-04-02 06:35:49

Bash讀寫文件Linux

2010-11-19 11:22:25

oracle對系統文件

2021-06-29 07:47:23

多線程協作數據

2010-07-21 13:17:52

Perl文件讀寫

2010-07-14 17:11:57

Perl文件

2009-08-13 09:34:55

C#讀寫ini文件

2022-11-15 09:24:16

littlefs文件讀寫

2010-07-14 17:20:33

讀寫Perl文件

2013-06-09 10:04:35

Android開發XML讀寫XML解析

2013-06-09 13:07:23

Android開發XML讀寫XML解析

2013-06-09 12:49:15

Android開發XML讀寫XML解析
點贊
收藏

51CTO技術棧公眾號

三级男人添奶爽爽爽视频| 欧美日韩午夜爽爽| 亚洲天堂777| 欧美激情四色| 亚洲午夜激情免费视频| 久久久精品高清| av蜜臀在线| 国产精品乱人伦中文| 国产精品免费在线播放| 亚洲精品国产无码| 亚洲午夜91| 最近中文字幕mv在线一区二区三区四区 | 国产精品免费区二区三区观看| 日韩中文字幕在线观看视频| 亚洲一区色图| 国产亚洲欧美另类中文| 日本性生活一级片| 亚洲精品成a人ⅴ香蕉片| 精品国产91乱高清在线观看| 色中文字幕在线观看| 涩涩视频在线观看免费| 国产剧情在线观看一区二区| 国产成人一区二区在线| 国产精品成人久久| 亚洲精品成人无限看| 国产亚洲一区精品| a视频免费观看| 一级毛片精品毛片| 在线播放欧美女士性生活| 久久9精品区-无套内射无码| 久久青青色综合| 成人免费一区二区三区视频 | 国产美女久久精品香蕉69| 亚洲天堂视频网站| 亚洲国产综合在线看不卡| 成年人精品视频| jizzjizzjizz国产| 北条麻妃国产九九九精品小说| 日韩av中文在线| 日本性生活一级片| 成人av资源网址| 精品国产乱子伦一区| 精品国产午夜福利在线观看| 日韩毛片在线| 91国内精品野花午夜精品| 国产精品97在线| 亚洲私拍视频| 日韩欧美高清视频| 亚洲午夜无码av毛片久久| 中文字幕资源网在线观看免费 | 亚洲色图另类专区| 中文字幕日韩精品一区二区| 在线免费观看黄色| 国产精品国产三级国产三级人妇| 亚洲国产精品综合| 亚洲成人影院麻豆| 国产精品第四页| 资源网第一页久久久| 九色porny在线| 亚洲精品国产无套在线观| 亚洲精品天堂成人片av在线播放| www在线视频| 亚洲欧美另类久久久精品2019| 四虎影院一区二区| 丝袜美女在线观看| 亚洲成a人在线观看| 精品无码一区二区三区爱欲| av在线网页| 色婷婷综合五月| 一区二区三区网址| 亚洲在线资源| 精品日韩一区二区| 久久亚洲AV成人无码国产野外 | 高清在线观看日韩| 激情视频在线观看一区二区三区| 污污网站在线免费观看| 久久久99免费| 一级二级三级欧美| 青春草视频在线| 欧美日韩国产一中文字不卡| 欧美日韩在线免费播放| 少妇精品视频在线观看| 精品捆绑美女sm三区| 全黄一级裸体片| 午夜精品视频一区二区三区在线看| 欧美大胆在线视频| 国产精品乱子伦| 久久精品av麻豆的观看方式| av资源一区二区| 三级av在线播放| 综合网在线视频| 国产超级av在线| 一区二区三区| 亚洲精品国产欧美| www.xx日本| 亚洲美女一区| 国产日韩中文字幕| 人妻少妇一区二区三区| 中文字幕乱码亚洲精品一区| cao在线观看| 国产精品原创视频| 亚洲精品成人av| 国产精品白丝喷水在线观看| 国产欧美激情| 亚洲mm色国产网站| 国产黄在线播放| 亚洲国产成人av网| 爱豆国产剧免费观看大全剧苏畅 | 一区高清视频| 波多野结衣久久精品| 欧美一级xxx| 日本爱爱爱视频| 欧美亚洲免费| 国产成人av一区二区三区| av中文字幕一区二区三区| 午夜欧美大尺度福利影院在线看| 一区二区三区欧美精品| 国产精品手机在线播放| 性色av香蕉一区二区| 国产又粗又猛视频| 99在线精品一区二区三区| 超碰在线免费观看97| 欧美日韩亚洲国产| 亚洲国产精彩中文乱码av| 欧美黑人性猛交xxx| 蜜桃视频免费观看一区| 欧美亚洲另类在线一区二区三区| 激情网站在线| 日韩欧美国产一区二区在线播放| 欧美一区二区三区粗大| 久久久久99| 久久久福利视频| 欧美另类老肥妇| 亚洲电影免费观看高清完整版在线 | 国产精品主播一区二区| 国产精品久久一卡二卡| 天堂社区在线视频| 国产中文字幕一区二区三区 | 日韩成人精品一区二区三区| 国产午夜精品全部视频在线播放 | 免费欧美日韩| 精品午夜一区二区| 午夜影院在线播放| 国产视频精品一区二区三区| 国产精品久久久免费视频| 成人激情黄色小说| 国产妇女馒头高清泬20p多| 午夜免费欧美电影| 久久久久久久久爱| 日本xxxxxwwwww| 五月天婷婷综合| 国产黄色三级网站| 久久国产精品99国产| 欧美国产一区二区在线| 欧美特大特白屁股xxxx| 国产一区二区三区高清在线观看| 日韩免费av网站| 国产日韩精品一区二区三区| 日本888xxxx| 91综合久久| 懂色av一区二区三区在线播放| 丝袜国产在线| 日韩成人在线视频观看| av一级在线观看| 国产精品国产三级国产普通话三级| 天天干天天干天天干天天干天天干| 精品一区二区三| 亚洲a级在线观看| 波多野结衣中文字幕久久| 精品sm在线观看| 亚洲国产成人无码av在线| 国产视频视频一区| 激情五月婷婷基地| 欧美激情麻豆| 日本欧美精品久久久| 婷婷激情成人| 国内精品久久影院| 国产人成在线观看| 6080日韩午夜伦伦午夜伦| 国产真实乱人偷精品视频| 99re热视频精品| 国产理论在线播放| 午夜精品视频| 欧美一区二区高清在线观看| 午夜不卡一区| 91精品国产91久久久| yjizz视频网站在线播放| 日韩一区二区三区电影在线观看| 国产精品自拍视频一区| 久久精品免视看| 国产xxx在线观看| 久久久蜜桃一区二区人| 亚洲小视频在线播放| 国产欧美日韩精品高清二区综合区| 91精品久久久久久| 黄色软件视频在线观看| 久久精品国产2020观看福利| 四虎影视2018在线播放alocalhost| 欧美日本韩国一区二区三区视频| 久久久久久久久久久网| 国产日韩欧美精品综合| 亚洲香蕉中文网| 久久成人久久鬼色| 国产超级av在线| 黄色av一区| 欧美日韩亚洲国产成人| 婷婷精品在线观看| 99久久无色码| 日韩一区二区三区四区五区| 欧美专区在线视频| 黄页网站在线| 久久999免费视频| 麻豆传媒在线完整视频| 国产亚洲综合久久| 青青草在线免费观看| 精品久久久久久久久久久久久久久 | 欧美久久高跟鞋激| 欧美精品一二三四区| 亚洲国产日韩在线一区模特| 在线观看美女av| 国产精品青草综合久久久久99| 性囗交免费视频观看| 国产精品一区二区男女羞羞无遮挡| 亚洲视频在线观看一区二区三区| 亚洲日本成人| 日韩人妻无码精品久久久不卡| 91精品啪在线观看国产81旧版| 日本在线视频一区| 久草成人资源| 欧美日韩亚洲一区二区三区在线观看| 懂色av一区二区| 成人黄动漫网站免费| 韩国一区二区三区视频| 成人久久久久久| 亚洲欧美专区| 成人性生交xxxxx网站| 国产成人精品一区二区三区视频| 国产精品福利在线观看网址| 免费福利视频一区二区三区| 日韩av免费一区| 久久久久久久| 国产va免费精品高清在线观看| 中文字幕资源网在线观看免费 | 成人亚洲精品| 亚洲一区免费网站| 少妇精品在线| 成人在线资源网址| 乱亲女h秽乱长久久久| 国产一区精品视频| 色哟哟精品丝袜一区二区| 欧美人与物videos另类| 成人3d精品动漫精品一二三| 视频在线99| 亚洲成人99| 免费网站在线观看视频| 亚洲激情女人| 国产女女做受ⅹxx高潮| 日韩**一区毛片| 日本黄大片一区二区三区| 精品一区二区日韩| 国产chinesehd精品露脸| 成人的网站免费观看| 瑟瑟视频在线观看| 国产精品色在线观看| 欧美偷拍第一页| 五月婷婷综合在线| 波多野结衣一二区| 欧美一区三区四区| 视频一区二区免费| 亚洲天堂av综合网| 免费黄色网址在线观看| 久久久免费av| 日本精品不卡| 亚洲一区美女视频在线观看免费| 草草视频在线一区二区| 欧美极品一区二区| 99精品全国免费观看视频软件| 成人小视频在线观看免费| 亚洲一区二区网站| www.99r| 成人免费va视频| www.99热| 亚洲国产毛片aaaaa无费看| 美女又爽又黄免费视频| 6080亚洲精品一区二区| 亚洲AV成人无码一二三区在线| 中文字幕av一区二区| 在线观看电影av| 国产精品wwwwww| 99国产精品免费网站| 水蜜桃一区二区三区| 在线电影一区| 色噜噜狠狠一区二区三区狼国成人 | 国产精品一区二区三区在线播放 | 亚洲美女自拍偷拍| 久久精品成人| 白丝校花扒腿让我c| 国产精品青草综合久久久久99| 国产在线一区视频| 欧美另类一区二区三区| 视频午夜在线| 欧美精品少妇videofree| 日韩不卡免费高清视频| 国产精品午夜av在线| 99精品综合| 国产福利一区视频| 成人免费看的视频| 最新av电影网站| 在线视频你懂得一区| 日韩在线观看视频一区| www.国产一区| 成人免费福利| 久久精品ww人人做人人爽| 欧美成人一品| 久久6免费视频| 国产精品毛片久久久久久| www五月天com| 日韩激情视频在线| 电影在线观看一区| 国产精品大全| 午夜视频一区| 丰满饥渴老女人hd| 自拍偷拍国产亚洲| ,一级淫片a看免费| 在线观看亚洲视频| 婷婷激情一区| 欧美一区二区福利| 久久久青草婷婷精品综合日韩| 国产高清自拍视频| 精品久久久久久久大神国产| 欧美一级片免费| 久久久久久久久久久国产| 91精品国产自产在线丝袜啪| 日本一级淫片演员| 国产一区二区三区久久久| 国精产品视频一二二区| 欧美日韩午夜在线视频| 最近高清中文在线字幕在线观看| 国产精品老牛影院在线观看| 奇米亚洲欧美| 亚洲人辣妹窥探嘘嘘| 中文一区二区完整视频在线观看| www.av88| 色偷偷综合社区| 99国内精品久久久久| 99热一区二区三区| 从欧美一区二区三区| 国产成人精品av久久| 亚洲精品成人免费| 手机在线观看av网站| 茄子视频成人在线观看| 日韩av在线发布| 成人信息集中地| 欧美一区二区日韩| caoporn免费在线视频| 91九色极品视频| 激情久久久久| 精品无码一区二区三区| 欧美在线免费播放| 日本在线免费看| 99精彩视频在线观看免费| 亚洲伦伦在线| 在哪里可以看毛片| 欧美精品日韩综合在线| 色女人在线视频| 九色91国产| 毛片不卡一区二区| 久久综合色综合| 日韩精品在线免费观看| 高清在线一区| 97av中文字幕| 久久新电视剧免费观看| 伊人网免费视频| 久久久久国产精品免费| 要久久电视剧全集免费| 亚洲欧美天堂在线| 亚洲v精品v日韩v欧美v专区| 黄色大片在线免费观看| 97se亚洲综合| 日韩av不卡在线观看| 九九精品在线观看视频| 国产视频欧美视频| 亚州精品国产| www.浪潮av.com| 亚洲欧洲国产日韩| 水中色av综合| 2022国产精品| 日韩精品成人一区二区在线| 少妇影院在线观看| 亚洲性日韩精品一区二区| 久久在线观看| 男人天堂成人在线| 亚洲国产综合91精品麻豆| 国产永久免费高清在线观看视频| 91九色蝌蚪嫩草| 免费一级欧美片在线观看| 91porny在线| 欧美成人性色生活仑片| 欧洲美女日日| 182在线视频|