亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

JavaIO之FileInputStream&FileOutputStream源碼分析

2019-11-14 15:29:22
字體:
來源:轉載
供稿:網友
io java FileInputStream FileOutputStream

 

目錄[-]

  • 一、引子
  • 二、FileInputStream源碼分析
  • 三、FileOutputStream 源碼分析
  • 四、使用案例
  • 五、思考與小結

Writer      :BYSocket(泥沙磚瓦漿木匠)

微         博:BYSocket

豆         瓣:BYSocket

FaceBook:BYSocket

Twitter    :BYSocket

一、引子

文件,作為常見的數據源。關于操作文件的字節流就是 — FileInputStream & FileOutputStream。它們是Basic IO字節流中重要的實現類。

二、FileInputStream源碼分析

FileInputStream源碼如下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/**
 * FileInputStream 從文件系統的文件中獲取輸入字節流。文件取決于主機系統。
 *  比如讀取圖片等的原始字節流。如果讀取字符流,考慮使用 FiLeReader。
 */
publicclassSFileInputStream extendsInputStream
{
    /* 文件描述符類---此處用于打開文件的句柄 */
    PRivate final FileDescriptor fd;
  
    /* 引用文件的路徑 */
    private final String path;
  
    /* 文件通道,NIO部分 */
    private FileChannel channel = null;
  
    private final Object closeLock = new Object();
    private volatile boolean closed = false;
  
    private static final ThreadLocal<Boolean> runningFinalize =
        new ThreadLocal<>();
  
    private static boolean isRunningFinalize() {
        Boolean val;
        if ((val = runningFinalize.get()) != null)
            return val.booleanValue();
        return false;
    }
  
    /* 通過文件路徑名來創建FileInputStream */
    public FileInputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null);
    }
  
    /* 通過文件來創建FileInputStream */
    public FileInputStream(File file) throws FileNotFoundException {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(name);
        }
        if (name == null) {
            throw new NullPointerException();
        }
        if (file.isInvalid()) {
            throw new FileNotFoundException("Invalid file path");
        }
        fd = new FileDescriptor();
        fd.incrementAndGetUseCount();
        this.path = name;
        open(name);
    }
  
    /* 通過文件描述符類來創建FileInputStream */
    public FileInputStream(FileDescriptor fdObj) {
        SecurityManager security = System.getSecurityManager();
        if (fdObj == null) {
            throw new NullPointerException();
        }
        if (security != null) {
            security.checkRead(fdObj);
        }
        fd = fdObj;
        path = null;
        fd.incrementAndGetUseCount();
    }
  
    /* 打開文件,為了下一步讀取文件內容。native方法 */
    private native void open(String name) throws FileNotFoundException;
  
    /* 從此輸入流中讀取一個數據字節 */
    public int read() throws IOException {
        Object traceContext = IoTrace.fileReadBegin(path);
        int b = 0;
        try {
            b = read0();
        } finally {
            IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1);
        }
        return b;
    }
  
    /* 從此輸入流中讀取一個數據字節。native方法 */
    private native int read0() throws IOException;
  
    /* 從此輸入流中讀取多個字節到byte數組中。native方法 */
    private native int readBytes(byte b[], int off, int len) throws IOException;
  
    /* 從此輸入流中讀取多個字節到byte數組中。 */
    public int read(byte b[]) throws IOException {
        Object traceContext = IoTrace.fileReadBegin(path);
        int bytesRead = 0;
        try {
            bytesRead = readBytes(b, 0, b.length);
        } finally {
            IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
        }
        return bytesRead;
    }
  
    /* 從此輸入流中讀取最多len個字節到byte數組中。 */
    public int read(byte b[], int off, int len) throws IOException {
        Object traceContext = IoTrace.fileReadBegin(path);
        int bytesRead = 0;
        try {
            bytesRead = readBytes(b, off, len);
        } finally {
            IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
        }
        return bytesRead;
    }
  
      
    public native long skip(long n) throws IOException;
  
    /* 返回下一次對此輸入流調用的方法可以不受阻塞地從此輸入流讀?。ɑ蛱^)的估計剩余字節數。 */
    public native int available() throws IOException;
  
    /* 關閉此文件輸入流并釋放與此流有關的所有系統資源。 */
    public void close() throws IOException {
        synchronized (closeLock) {
            if (closed) {
                return;
            }
            closed = true;
        }
        if (channel != null) {
           fd.decrementAndGetUseCount();
           channel.close();
        }
  
        int useCount = fd.decrementAndGetUseCount();
  
        if ((useCount <= 0) || !isRunningFinalize()) {
            close0();
        }
    }
  
    public final FileDescriptor getFD() throws IOException {
        if (fd != null) return fd;
        throw new IOException();
    }
  
    /* 獲取此文件輸入流的唯一FileChannel對象 */
    publicFileChannel getChannel() {
        synchronized(this) {
            if(channel == null) {
                channel = FileChannelImpl.open(fd, path, true, false, this);
                fd.incrementAndGetUseCount();
            }
            returnchannel;
        }
    }
  
    privatestaticnativevoidinitIDs();
  
    privatenativevoidclose0() throwsIOException;
  
    static{
        initIDs();
    }
  
    protected void finalize() throws IOException {
        if((fd != null) &&  (fd != FileDescriptor.in)) {
            runningFinalize.set(Boolean.TRUE);
            try{
                close();
            } finally{
                runningFinalize.set(Boolean.FALSE);
            }
        }
    }
}

1. 三個核心方法

三個核心方法,也就是Override(重寫)了抽象類InputStreamread方法。

int read() 方法,即

 

?
1
public int read() throws IOException

代碼實現中很簡單,一個try中調用本地nativeread0()方法,直接從文件輸入流中讀取一個字節。IoTrace.fileReadEnd(),字面意思是防止文件沒有關閉讀的通道,導致讀文件失敗,一直開著讀的通道,會造成內存泄露。

 

int read(byte b[]) 方法,即

 

?
1
public int read(byte b[]) throws IOException

代碼實現也是比較簡單的,也是一個try中調用本地nativereadBytes()方法,直接從文件輸入流中讀取最多b.length個字節到byte數組b中。

int read(byte b[], int off, int len) 方法,即

 

?
1
public int read(byte b[], int off, int len) throws IOException

代碼實現和 int read(byte b[])方法 一樣,直接從文件輸入流中讀取最多len個字節到byte數組b中。

可是這里有個問:

Q: 為什么 int read(byte b[]) 方法需要自己獨立實現呢? 直接調用 int read(byte b[], int off, int len) 方法,即read(b , 0 , b.length),等價于read(b)?

A:待完善,希望路過大神回。。。。向下兼容?? Finally??

2. 值得一提的native方法

上面核心方法中為什么實現簡單,因為工作量都在native方法里面,即JVM里面實現了。native倒是不少一一列舉吧:

native void open(String name) // 打開文件,為了下一步讀取文件內容

native int read0() // 從文件輸入流中讀取一個字節

native int readBytes(byte b[], int off, int len) // 從文件輸入流中讀取,從off句柄開始的len個字節,并存儲至b字節數組內。

native void close0() // 關閉該文件輸入流及涉及的資源,比如說如果該文件輸入流的FileChannel對被獲取后,需要對FileChannel進行close。

其他還有值得一提的就是,在jdk1.4中,新增了NIO包,優化了一些IO處理的速度,所以在FileInputStream和FileOutputStream中新增了FileChannel getChannel()的方法。即獲取與該文件輸入流相關的 java.nio.channels.FileChannel對象。

 

三、FileOutputStream 源碼分析

FileOutputStream 源碼如下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/**
 * 文件輸入流是用于將數據寫入文件或者文件描述符類
 *  比如寫入圖片等的原始字節流。如果寫入字符流,考慮使用 FiLeWriter。
 */
publicclassSFileOutputStream extendsOutputStream
{
    /* 文件描述符類---此處用于打開文件的句柄 */
    private final FileDescriptor fd;
  
    /* 引用文件的路徑 */
    private final String path;
  
    /* 如果為 true,則將字節寫入文件末尾處,而不是寫入文件開始處 */
    private final boolean append;
  
    /* 關聯的FileChannel類,懶加載 */
    private FileChannel channel;
  
    private final Object closeLock = new Object();
    private volatile boolean closed = false;
    private static final ThreadLocal<Boolean> runningFinalize =
        new ThreadLocal<>();
  
    private static boolean isRunningFinalize() {
        Boolean val;
        if ((val = runningFinalize.get()) != null)
            return val.booleanValue();
        return false;
    }
  
    /* 通過文件名創建文件輸入流 */
    public FileOutputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null, false);
    }
  
    /* 通過文件名創建文件輸入流,并確定文件寫入起始處模式 */
    public FileOutputStream(String name, boolean append)
        throws FileNotFoundException
    {
        this(name != null ? new File(name) : null, append);
    }
  
    /* 通過文件創建文件輸入流,默認寫入文件的開始處 */
    public FileOutputStream(File file) throws FileNotFoundException {
        this(file, false);
    }
  
    /* 通過文件創建文件輸入流,并確定文件寫入起始處  */
    public FileOutputStream(File file, boolean append)
        throws FileNotFoundException
    {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(name);
        }
        if (name == null) {
            throw new NullPointerException();
        }
        if (file.isInvalid()) {
            throw new FileNotFoundException("Invalid file path");
        }
        this.fd = new FileDescriptor();
        this.append = append;
        this.path = name;
        fd.incrementAndGetUseCount();
        open(name, append);
    }
  
    /* 通過文件描述符類創建文件輸入流 */
    public FileOutputStream(FileDescriptor fdObj) {
        SecurityManager security = System.getSecurityManager();
        if (fdObj == null) {
            throw new NullPointerException();
        }
        if (security != null) {
            security.checkWrite(fdObj);
        }
        this.fd = fdObj;
        this.path = null;
        this.append = false;
  
        fd.incrementAndGetUseCount();
    }
  
    /* 打開文件,并確定文件寫入起始處模式 */
    private native void open(String name, boolean append)
        throws FileNotFoundException;
  
    /* 將指定的字節b寫入到該文件輸入流,并指定文件寫入起始處模式 */
    private native void write(int b, boolean append) throws IOException;
  
    /* 將指定的字節b寫入到該文件輸入流 */
    public void write(int b) throws IOException {
        Object traceContext = IoTrace.fileWriteBegin(path);
        int bytesWritten = 0;
        try {
            write(b, append);
            bytesWritten = 1;
        } finally {
            IoTrace.fileWriteEnd(traceContext, bytesWritten);
        }
    }
  
    /* 將指定的字節數組寫入該文件輸入流,并指定文件寫入起始處模式 */
    private native void writeBytes(byte b[], int off, int len, boolean append)
        throws IOException;
  
    /* 將指定的字節數組b寫入該文件輸入流 */
    public void write(byte b[]) throws IOException {
        Object traceContext = IoTrace.fileWriteBegin(path);
        int bytesWritten = 0;
        try {
            writeBytes(b, 0, b.length, append);
            bytesWritten = b.length;
        } finally {
            IoTrace.fileWriteEnd(traceContext, bytesWritten);
        }
    }
  
    /* 將指定len長度的字節數組b寫入該文件輸入流 */
    public void write(byte b[], int off, int len) throws IOException {
        Object traceContext = IoTrace.fileWriteBegin(path);
        int bytesWritten = 0;
        try {
            writeBytes(b, off, len, append);
            bytesWritten = len;
        } finally {
            IoTrace.fileWriteEnd(traceContext, bytesWritten);
        }
    }
  
    /* 關閉此文件輸出流并釋放與此流有關的所有系統資源 */
    publicvoidclose() throwsIOException {
        synchronized(closeLock) {
            if(closed) {
                return;
            }
            closed = true;
        }
  
        if(channel != null) {
            fd.decrementAndGetUseCount();
            channel.close();
        }
  
        intuseCount = fd.decrementAndGetUseCount();
  
        if((useCount <= 0) || !isRunningFinalize()) {
            close0();
        }
    }
  
     public final FileDescriptor getFD()  throws IOException {
        if(fd != null) returnfd;
        thrownewIOException();
     }
  
    publicFile Channel getChannel() {
        synchronized(this) {
            if(channel == null) {
                channel = FileChannelImpl.open(fd, path, false, true, append, this);
  
                fd.incrementAndGetUseCount();
            }
            returnchannel;
        }
    }
  
    protected void finalize() throws IOException {
        if(fd != null) {
            if(fd == FileDescriptor.out || fd == FileDescriptor.err) {
                flush();
            } else{
  
                runningFinalize.set(Boolean.TRUE);
                try{
                    close();
                } finally{
                    runningFinalize.set(Boolean.FALSE);
                }
            }
        }
    }
  
    private native void close0() throws IOException;
  
    private static native void initIDs();
  
    static{
        initIDs();
    }
  
}

 

 

1. 三個核心方法

三個核心方法,也就是Override(重寫)了抽象類OutputStreamwrite方法。

void write(int b) 方法,即

 

?
1
public void write(intb) throws IOException

 

代碼實現中很簡單,一個try中調用本地nativewrite()方法,直接將指定的字節b寫入文件輸出流。IoTrace.fileReadEnd()的意思和上面FileInputStream意思一致。

 

void write(byte b[]) 方法,即

 

?
1
public void write(byteb[]) throws IOException

 

代碼實現也是比較簡單的,也是一個try中調用本地nativewriteBytes()方法,直接將指定的字節數組寫入該文件輸入流。

void write(byte b[], int off, int len) 方法,即

 

?
1
public void write(byte b[], int off, int len) throws IOException

 

 


 

代碼實現和 void write(byte b[]) 方法 一樣,直接將指定的字節數組寫入該文件輸入流。

 

2. 值得一提的native方法

上面核心方法中為什么實現簡單,因為工作量都在native方法里面,即JVM里面實現了。native倒是不少一一列舉吧:

native void open(String name) // 打開文件,為了下一步讀取文件內容

native void write(int b, boolean append) // 直接將指定的字節b寫入文件輸出流

native native void writeBytes(byte b[], int off, int len, boolean append) // 直接將指定的字節數組寫入該文件輸入流。

native void close0() // 關閉該文件輸入流及涉及的資源,比如說如果該文件輸入流的FileChannel對被獲取后,需要對FileChannel進行close。

 

相似之處

其實到這里,該想一想。兩個源碼實現很相似,而且native方法也很相似。其實不能說“相似”,應該以“對應”來概括它們。

它們是一組,是一根吸管的兩個孔的關系:“一個Input一個Output”。

休息一下吧~ 看看小廣告:

開源代碼都在我的gitHub上哦 — https://github.com/JeffLi1993 作者留言“請手賤,點項目star,支持支持拜托拜托”

四、使用案例

下面先看代碼:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
packageorg.javacore.io;
  
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
  
/*
 * Copyright [2015] [Jeff Lee]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
  
/**
 * @author Jeff Lee
 * @since 2015-10-8 20:06:03
 * FileInputStream&FileOutputStream使用案例
 */
public class FileIOStreamT {
    private static final String thisFilePath =
            "src"+ File.separator +
            "org"+ File.separator +
            "javacore"+ File.separator +
            "io"+ File.separator +
            "FileIOStreamT.java";
    public static void main(String[] args) throws IOException {
        // 創建文件輸入流
        FileInputStream fileInputStream = new FileInputStream(thisFilePath);
        // 創建文件輸出流
        FileOutputStream fileOutputStream =  new FileOutputStream("data.txt");
          
        // 創建流的最大字節數組
        byte[] inOutBytes = new byte[fileInputStream.available()];
        // 將文件輸入流讀取,保存至inOutBytes數組
        fileInputStream.read(inOutBytes);
        // 將inOutBytes數組,寫出到data.txt文件中
        fileOutputStream.write(inOutBytes);
          
        fileOutputStream.close();
        fileInputStream.close();
    }
}

 

運行后,會發現根目錄中出現了一個“data.txt”文件,內容為上面的代碼。

1. 簡單地分析下源碼:

1、創建了FileInputStream,讀取該代碼文件為文件輸入流。

2、創建了FileOutputStream,作為文件輸出流,輸出至data.txt文件。

3、針對流的字節數組,一個 read ,一個write,完成讀取和寫入。

4、關閉流

2. 代碼調用的流程如圖所示:

iostream

3. 代碼雖簡單,但是有點小問題

FileInputStream.available() 是返回流中的估計剩余字節數。所以一般不會用此方法。

一般做法,比如創建一個 byte數組,大小1K。然后read至其返回值不為-1,一直讀取即可。邊讀邊寫。

五、思考與小結

FileInputStream & FileOutputStream 是一對來自 InputStream和OutputStream的實現類。用于本地文件讀寫(二進制格式按順序讀寫)。

本文小結:

1、FileInputStream 源碼分析

2、FileOutputStream 資源分析

3、FileInputStream & FileOutputStream 使用案例

4、其源碼調用過程

歡迎點擊我的博客及GitHub — 博客提供rss訂閱哦!

———- http://www.bysocket.com/ ————- https://github.com/JeffLi1993 ———-

全能程序員交流QQ群290551701,群內程序員都是來自,百度、阿里、京東、小米、去哪兒、餓了嗎、藍港等高級程序員 ,擁有豐富的經驗。加入我們,直線溝通技術大牛,最佳的學習環境,了解業內的一手的資訊。如果你想結實大牛,那 就加入進來,讓大牛帶你超神!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品按摩视频| 亚洲精品日韩av| 日韩成人激情视频| 久久精品国产69国产精品亚洲| 欧美激情xxxxx| 91精品国产高清自在线| 国产专区精品视频| 久久久久久午夜| 欧美另类极品videosbest最新版本| 亚洲日本成人女熟在线观看| 2019亚洲男人天堂| 欧美色视频日本版| 日韩精品在线视频观看| 这里只有精品在线观看| 亚洲区中文字幕| 欧美成人激情视频| 日韩精品黄色网| 97色在线观看免费视频| xxxx欧美18另类的高清| 久久免费视频在线观看| 国产精品天天狠天天看| 久久亚洲精品网站| 日本欧美爱爱爱| 正在播放亚洲1区| 国产专区精品视频| 欧美日韩高清区| 国模极品一区二区三区| 久久久久久亚洲精品| 欧美在线性视频| 97**国产露脸精品国产| 亚洲va码欧洲m码| 国产精品男女猛烈高潮激情| 日本久久久久久久| 亚洲一区二区三区乱码aⅴ蜜桃女| 欧美性xxxx在线播放| 国产精品日本精品| 在线免费观看羞羞视频一区二区| 久久不射电影网| 欧美大成色www永久网站婷| 日韩欧美高清在线视频| 久久好看免费视频| 精品亚洲男同gayvideo网站| www日韩中文字幕在线看| 91在线高清视频| 国产成人激情小视频| 欧美在线激情视频| 成人欧美一区二区三区黑人| 国产成人精品在线播放| 成人伊人精品色xxxx视频| 中文国产成人精品久久一| 日韩欧美一区二区三区| 日韩国产一区三区| 亚洲va国产va天堂va久久| 国产精品jizz在线观看麻豆| 精品女同一区二区三区在线播放| 91精品国产91| 成人黄色影片在线| 中文字幕精品一区久久久久| 欧美激情一级二级| 亚洲影院色无极综合| 欧美亚洲视频在线观看| 国产一区二区在线免费| 爽爽爽爽爽爽爽成人免费观看| 国产精品视频成人| 91在线高清免费观看| 国产精品久久久久久久久| 国产免费一区视频观看免费| 日韩欧美精品网站| 91精品国产91久久久久| 91超碰中文字幕久久精品| 欧美亚洲视频一区二区| 欧美另类暴力丝袜| 欧美日韩国产专区| 久久精品男人天堂| 亚洲跨种族黑人xxx| 欧美刺激性大交免费视频| 久久黄色av网站| 成人精品视频久久久久| 亚洲午夜av电影| 亚洲成人激情视频| 91日韩在线视频| 国产视频精品在线| 亚洲精品日韩av| 国产在线拍揄自揄视频不卡99| 亚洲午夜色婷婷在线| 国产日韩欧美在线视频观看| 精品亚洲夜色av98在线观看| 中文字幕欧美日韩va免费视频| 欧美日韩国产成人在线观看| 欧美日韩黄色大片| 亚洲综合色av| 亚洲欧美国产精品va在线观看| 最新亚洲国产精品| 久久久精品电影| 在线亚洲男人天堂| 中国china体内裑精亚洲片| 最好看的2019的中文字幕视频| 亚洲精品久久久久| 久久免费少妇高潮久久精品99| 亚洲加勒比久久88色综合| 欧美一级电影免费在线观看| 精品国内产的精品视频在线观看| 久久精品中文字幕免费mv| 激情av一区二区| 欧美一区二区.| 精品久久久久久久久久国产| 久久人体大胆视频| 国外成人性视频| 亚洲系列中文字幕| 97超碰国产精品女人人人爽| 69久久夜色精品国产69| 欧美日本中文字幕| 最新中文字幕亚洲| 91视频九色网站| 人人做人人澡人人爽欧美| 国产成+人+综合+亚洲欧美丁香花| 91福利视频在线观看| 欧美日韩第一页| 成人乱色短篇合集| 中文字幕亚洲无线码在线一区| 国产亚洲精品激情久久| 欧洲美女免费图片一区| 国产精品高清在线观看| 最新的欧美黄色| 最近更新的2019中文字幕| 91精品久久久久久久久久久久久| 亚洲最大av网| 在线色欧美三级视频| 日韩欧美在线视频日韩欧美在线视频| 国产精品美女久久久久久免费| 久久久久久久一区二区三区| 亚洲欧美中文日韩v在线观看| 欧美丰满少妇xxxxx做受| 国产精品都在这里| 欧美性猛xxx| 精品亚洲一区二区三区四区五区| 91综合免费在线| 亚洲免费视频网站| 97超碰国产精品女人人人爽| 欧美国产日韩视频| 草民午夜欧美限制a级福利片| 日本成人精品在线| 国产午夜精品理论片a级探花| 日韩在线视频二区| 国产91对白在线播放| 久久久久久香蕉网| 国产欧美精品一区二区三区介绍| 国外日韩电影在线观看| 2019中文在线观看| 97久久精品人人澡人人爽缅北| 国产精品精品视频一区二区三区| 成人免费视频网址| xxx欧美精品| 日韩男女性生活视频| 九九久久久久久久久激情| 亚洲精品免费在线视频| 精品国产欧美一区二区三区成人| 亚洲a在线播放| 亚洲午夜小视频| 国外色69视频在线观看| 8x拔播拔播x8国产精品| 亚洲自拍欧美色图| 91夜夜未满十八勿入爽爽影院| 亚洲系列中文字幕|