国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - Java BufferedWriter BufferedReader 源碼分析

Java BufferedWriter BufferedReader 源碼分析

2020-05-25 11:14lqh JAVA教程

本文是關于Java BufferedWriter ,BufferedReader 簡介、分析源碼 對Java IO 流深入了解,希望看到的同學對你有所幫助

一:BufferedWriter

 1、類功能簡介:

        BufferedWriter、緩存字符輸出流、他的功能是為傳入的底層字符輸出流提供緩存功能、同樣當使用底層字符輸出流向目的地中寫入字符或者字符數組時、每寫入一次就要打開一次到目的地的連接、這樣頻繁的訪問不斷效率底下、也有可能會對存儲介質造成一定的破壞、比如當我們向磁盤中不斷的寫入字節時、夸張一點、將一個非常大單位是G的字節數據寫入到磁盤的指定文件中的、沒寫入一個字節就要打開一次到這個磁盤的通道、這個結果無疑是恐怖的、而當我們使用BufferedWriter將底層字符輸出流、比如FileReader包裝一下之后、我們可以在程序中先將要寫入到文件中的字符寫入到BufferedWriter的內置緩存空間中、然后當達到一定數量時、一次性寫入FileReader流中、此時、FileReader就可以打開一次通道、將這個數據塊寫入到文件中、這樣做雖然不可能達到一次訪問就將所有數據寫入磁盤中的效果、但也大大提高了效率和減少了磁盤的訪問量!這就是其意義所在、 他的具體工作原理在這里簡單提一下:這里可能說的比較亂、具體可以看源碼、不懂再回頭看看這里、當程序中每次將字符或者字符數組寫入到BufferedWriter中時、都會檢查BufferedWriter中的緩存字符數組buf(buf的大小是默認的或者在創建bw時指定的、一般使用默認的就好)是否存滿、如果沒有存滿則將字符寫入到buf中、如果存滿、則調用底層的writer(char[] b, int off, int len)將buf中的所有字符一次性寫入到底層out中、如果寫入的是字符數組、如果buf中已滿則同上面滿的時候的處理、如果能夠存下寫入的字符數組、則存入buf中、如果存不下、并且要寫入buf的字符個數小于buf的長度、則將buf中所有字符寫入到out中、然后將要寫入的字符存放到buf中(從下標0開始存放)、如果要寫入out中的字符超過buf的長度、則直接寫入out中、

2、BufferedWriter  API簡介:

?
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
  A:關鍵字
private Writer out;        底層字符輸出流
 
 
private char cb[];         緩沖數組
 
private int nChars, nextChar;      nChars--cb的size,nextChar--cb中下一個字符的下標
 
private static int defaultCharBufferSize = 8192;       默認cb大小
 
private String lineSeparator;     換行符、用于newLine方法。不同平臺具有不同的值。
 
  B:構造方法
 
BufferedWriter(Writer out)        使用默認cb大小創建BufferedWriter bw。
 
BufferedWriter(Writer out, int sz)        使用默認cb大小創建BufferedWriter bw。
 
  C:一般方法
 
void close()      關閉此流、釋放與此流有關的資源。
 
void flushBuffer()        將cb中緩存的字符flush到底層out中、
 
void flush()  刷新此流、同時刷新底層out流
 
void newLine()        寫入一個換行符。
 
void write(int c)     將一個單個字符寫入到cb中。
 
void write(char cbuf[], int off, int len) 將一個從下標off開始長度為len個字符寫入cb中
 
void write(String s, int off, int len)        將一個字符串的一部分寫入cb中

3、源碼分析

?
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
package com.chy.io.original.code;
 
import java.io.IOException;
import java.io.PrintWriter;
 
 
/**
 * 為字符輸出流提供緩沖功能、提高效率。可以使用指定字符緩沖數組大小也可以使用默認字符緩沖數組大小。
 */
 
public class BufferedWriter extends Writer {
 
    //底層字符輸出流
  private Writer out;
 
  //緩沖數組
  private char cb[];
  //nChars--cb中總的字符數,nextChar--cb中下一個字符的下標
  private int nChars, nextChar;
 
  //默認cb大小
  private static int defaultCharBufferSize = 8192;
 
  /**
   * Line separator string. This is the value of the line.separator
   * property at the moment that the stream was created.
   * 換行符、用于newLine方法。不同平臺具有不同的值。
   */
  private String lineSeparator;
 
  /**
   * 使用默認cb大小創建BufferedWriter bw。
   */
  public BufferedWriter(Writer out) {
    this(out, defaultCharBufferSize);
  }
 
  /**
   * 使用指定cb大小創建br、初始化相關字段
   */
  public BufferedWriter(Writer out, int sz) {
        super(out);
            if (sz <= 0)
              throw new IllegalArgumentException("Buffer size <= 0");
            this.out = out;
            cb = new char[sz];
            nChars = sz;
            nextChar = 0;
            //獲取不同平臺下的換行符表示方式。
            lineSeparator = (String) java.security.AccessController.doPrivileged(
                new sun.security.action.GetPropertyAction("line.separator"));
  }
 
  /** 檢測底層字符輸出流是否關閉*/
  private void ensureOpen() throws IOException {
        if (out == null)
          throw new IOException("Stream closed");
  }
 
  /**
   * 將cb中緩存的字符flush到底層out中、但是不flush底層out中的字符。
   * 并且將cb清空。
   */
  void flushBuffer() throws IOException {
        synchronized (lock) {
          ensureOpen();
          if (nextChar == 0)
            return;
          out.write(cb, 0, nextChar);
          nextChar = 0;
        }
  }
 
  /**
   * 將一個單個字符寫入到cb中。
   */
  public void write(int c) throws IOException {
        synchronized (lock) {
          ensureOpen();
          if (nextChar >= nChars)
            flushBuffer();
          cb[nextChar++] = (char) c;
        }
  }
 
  /**
   * Our own little min method, to avoid loading java.lang.Math if we've run
   * out of file descriptors and we're trying to print a stack trace.
   */
  private int min(int a, int b) {
    if (a < b) return a;
    return b;
  }
 
  /**
   * 將一個從下標off開始長度為len個字符寫入cb中
   */
  public void write(char cbuf[], int off, int len) throws IOException {
        synchronized (lock) {
          ensureOpen();
          if ((off < 0) || (off > cbuf.length) || (len < 0) ||
            ((off + len) > cbuf.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
          } else if (len == 0) {
            return;
          }
    
          if (len >= nChars) {
                /* 如果len大于cb的長度、那么就直接將cb中現有的字符和cbuf中的字符寫入out中、
                 * 而不是寫入cb、再寫入out中 。
                 */
                flushBuffer();
                out.write(cbuf, off, len);
                return;
          }
    
          int b = off, t = off + len;
          while (b < t) {
                int d = min(nChars - nextChar, t - b);
                System.arraycopy(cbuf, b, cb, nextChar, d);
                b += d;
                nextChar += d;
                if (nextChar >= nChars)
                  flushBuffer();
          }
        }
  }
 
  /**
   * 將一個字符串的一部分寫入cb中
   */
  public void write(String s, int off, int len) throws IOException {
    synchronized (lock) {
      ensureOpen();
 
      int b = off, t = off + len;
      while (b < t) {
        int d = min(nChars - nextChar, t - b);
        s.getChars(b, b + d, cb, nextChar);
        b += d;
        nextChar += d;
        if (nextChar >= nChars)
          flushBuffer();
      }
    }
  }
 
  /**
   * 寫入一個換行符。
   */
  public void newLine() throws IOException {
    write(lineSeparator);
  }
 
  /**
   * 刷新此流、同時刷新底層out流
   */
  public void flush() throws IOException {
        synchronized (lock) {
          flushBuffer();
          out.flush();
        }
  }
  /**
   * 關閉此流、釋放與此流有關的資源。
   */
  public void close() throws IOException {
        synchronized (lock) {
          if (out == null) {
            return;
          }
          try {
            flushBuffer();
          } finally {
            out.close();
            out = null;
            cb = null;
          }
        }
  }
}

 4、實例演示:與下面的BufferedReader結合使用實現字符類型的文件的拷貝。

二:BufferedReader

 1、類功能簡介:

        緩沖字符輸入流、他的功能是為傳入的底層字符輸入流提供緩沖功能、他會通過底層字符輸入流(in)中的字符讀取到自己的buffer中(內置緩存字符數組)、然后程序調用BufferedReader的read方法將buffer中的字符讀取到程序中、當buffer中的字符被讀取完之后、BufferedReader會從in中讀取下一個數據塊到buffer中供程序讀取、直到in中數據被讀取完畢、這樣做的好處一是提高了讀取的效率、二是減少了打開存儲介質的連接次數、詳細的原因下面BufferedWriter有說到。其有個關鍵的方法fill()就是每當buffer中數據被讀取完之后從in中將數據填充到buffer中、程序從內存中讀取數據的速度是從磁盤中讀取的十倍!這是一個很恐怖的效率的提升、同時我們也不能無禁止的指定BufferedReader的buffer大小、畢竟、一次性讀取in中耗時較長、二是內存價格相對昂貴、我們能做的就是盡量在其中找到合理點。一般也不用我們費這個心、創建BufferedReader時使用buffer的默認大小就好。

2、BufferedReader  API簡介:

?
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
A:構造方法
 
 BufferedReader(Reader in, int sz)     根據指定大小和底層字符輸入流創建BufferedReader。br
 
 BufferedReader(Reader in)     使用默認大小創建底層輸出流的緩沖流
 
 
   B:一般方法
 
 void close()  關閉此流、釋放與此流有關的所有資源
 
 void mark(int readAheadLimit) 標記此流此時的位置
 
 boolean markSupported()       判斷此流是否支持標記
 
 void reset()  重置in被最后一次mark的位置
 
 boolean ready()       判斷此流是否可以讀取字符
 
 int read()        讀取單個字符、以整數形式返回。如果讀到in的結尾則返回-1
 
 int read(char[] cbuf, int off, int len)   將in中len個字符讀取到cbuf從下標off開始長度len中
 
 String readLine() 讀取一行
 
 long skip(long n)     丟棄in中n個字符

 3、源碼分析

?
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
package com.chy.io.original.code;
 
import java.io.IOException;
 
/**
 * 為底層字符輸入流添加字符緩沖cb數組。提高效率
 * @version     1.1, 13/11/17
 * @author      andyChen
 */
 
public class BufferedReader extends Reader {
 
  private Reader in;
 
  private char cb[];
  private int nChars, nextChar;
 
  private static final int INVALIDATED = -2;
  private static final int UNMARKED = -1;
  private int markedChar = UNMARKED;
  private int readAheadLimit = 0; /* Valid only when markedChar > 0 */
 
  /** If the next character is a line feed, skip it */
  private boolean skipLF = false;
 
  /** The skipLF flag when the mark was set */
  private boolean markedSkipLF = false;
 
  private static int defaultCharBufferSize = 8192;
  private static int defaultExpectedLineLength = 80;
 
  /**
   * 根據指定大小和底層字符輸入流創建BufferedReader。br
   */
  public BufferedReader(Reader in, int sz) {
        super(in);
        if (sz <= 0)
          throw new IllegalArgumentException("Buffer size <= 0");
        this.in = in;
        cb = new char[sz];
        nextChar = nChars = 0;
  }
 
  /**
   * 使用默認大小創建底層輸出流的緩沖流
   */
  public BufferedReader(Reader in) {
    this(in, defaultCharBufferSize);
  }
 
  /** 檢測底層字符輸入流in是否關閉 */
  private void ensureOpen() throws IOException {
        if (in == null)
          throw new IOException("Stream closed");
  }
 
  /**
   * 填充cb。
   */
  private void fill() throws IOException {
        int dst;
        if (markedChar <= UNMARKED) {
          /* No mark */
          dst = 0;
        } else {
          /* Marked */
          int delta = nextChar - markedChar;
          if (delta >= readAheadLimit) {
            /* Gone past read-ahead limit: Invalidate mark */
            markedChar = INVALIDATED;
            readAheadLimit = 0;
            dst = 0;
          } else {
            if (readAheadLimit <= cb.length) {
              /* Shuffle in the current buffer */
              System.arraycopy(cb, markedChar, cb, 0, delta);
              markedChar = 0;
              dst = delta;
            } else {
              /* Reallocate buffer to accommodate read-ahead limit */
              char ncb[] = new char[readAheadLimit];
              System.arraycopy(cb, markedChar, ncb, 0, delta);
              cb = ncb;
              markedChar = 0;
              dst = delta;
            }
            nextChar = nChars = delta;
          }
        }
    
        int n;
        do {
          n = in.read(cb, dst, cb.length - dst);
        } while (n == 0);
        if (n > 0) {
          nChars = dst + n;
          nextChar = dst;
        }
  }
 
  /**
   * 讀取單個字符、以整數形式返回。如果讀到in的結尾則返回-1。
   */
  public int read() throws IOException {
        synchronized (lock) {
          ensureOpen();
          for (;;) {
            if (nextChar >= nChars) {
              fill();
              if (nextChar >= nChars)
                return -1;
            }
            if (skipLF) {
              skipLF = false;
              if (cb[nextChar] == '\n') {
                nextChar++;
                continue;
              }
            }
            return cb[nextChar++];
          }
        }
  }
 
  /**
   * 將in中len個字符讀取到cbuf從下標off開始長度len中
   */
  private int read1(char[] cbuf, int off, int len) throws IOException {
        if (nextChar >= nChars) {
          /* If the requested length is at least as large as the buffer, and
            if there is no mark/reset activity, and if line feeds are not
            being skipped, do not bother to copy the characters into the
            local buffer. In this way buffered streams will cascade
            harmlessly. */
          if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {
            return in.read(cbuf, off, len);
          }
          fill();
        }
        if (nextChar >= nChars) return -1;
        if (skipLF) {
          skipLF = false;
          if (cb[nextChar] == '\n') {
            nextChar++;
            if (nextChar >= nChars)
              fill();
            if (nextChar >= nChars)
              return -1;
          }
        }
        int n = Math.min(len, nChars - nextChar);
        System.arraycopy(cb, nextChar, cbuf, off, n);
        nextChar += n;
        return n;
  }
 
  /**
   * 將in中len個字符讀取到cbuf從下標off開始長度len中
   */
  public int read(char cbuf[], int off, int len) throws IOException {
    synchronized (lock) {
      ensureOpen();
      if ((off < 0) || (off > cbuf.length) || (len < 0) ||
        ((off + len) > cbuf.length) || ((off + len) < 0)) {
        throw new IndexOutOfBoundsException();
      } else if (len == 0) {
        return 0;
      }
 
      int n = read1(cbuf, off, len);
      if (n <= 0) return n;
      while ((n < len) && in.ready()) {
        int n1 = read1(cbuf, off + n, len - n);
        if (n1 <= 0) break;
        n += n1;
      }
      return n;
    }
  }
 
  /**
   * 從in中讀取一行、是否忽略換行符
   */
  String readLine(boolean ignoreLF) throws IOException {
        StringBuffer s = null;
        int startChar;
    
    synchronized (lock) {
      ensureOpen();
      boolean omitLF = ignoreLF || skipLF;
        bufferLoop:
        for (;;) {
    
            if (nextChar >= nChars)
              fill();
            if (nextChar >= nChars) { /* EOF */
              if (s != null && s.length() > 0)
                return s.toString();
              else
                return null;
            }
            boolean eol = false;
            char c = 0;
            int i;
    
            /* Skip a leftover '\n', if necessary */
            if (omitLF && (cb[nextChar] == '\n'))
              nextChar++;
            skipLF = false;
            omitLF = false;
    
          charLoop:
            for (i = nextChar; i < nChars; i++) {
              c = cb[i];
              if ((c == '\n') || (c == '\r')) {
                eol = true;
                break charLoop;
              }
            }
    
            startChar = nextChar;
            nextChar = i;
    
            if (eol) {
              String str;
              if (s == null) {
                str = new String(cb, startChar, i - startChar);
              } else {
                s.append(cb, startChar, i - startChar);
                str = s.toString();
              }
              nextChar++;
              if (c == '\r') {
                skipLF = true;
              }
              return str;
            }
            
            if (s == null)
              s = new StringBuffer(defaultExpectedLineLength);
            s.append(cb, startChar, i - startChar);
          }
    }
  }
 
  /**
   * 從in中讀取一行、
   */
  public String readLine() throws IOException {
    return readLine(false);
  }
 
  /**
   * 丟棄in中n個字符
   */
  public long skip(long n) throws IOException {
        if (n < 0L) {
          throw new IllegalArgumentException("skip value is negative");
        }
        synchronized (lock) {
          ensureOpen();
          long r = n;
          while (r > 0) {
            if (nextChar >= nChars)
              fill();
            if (nextChar >= nChars)  /* EOF */
              break;
            if (skipLF) {
              skipLF = false;
              if (cb[nextChar] == '\n') {
                nextChar++;
              }
            }
            long d = nChars - nextChar;
            if (r <= d) {
              nextChar += r;
              r = 0;
              break;
            }
            else {
              r -= d;
              nextChar = nChars;
            }
          }
          return n - r;
        }
  }
 
  /**
   * 判斷cb中是否為空、或者底層in中是否有可讀字符。
   */
  public boolean ready() throws IOException {
        synchronized (lock) {
          ensureOpen();
    
          /*
           * If newline needs to be skipped and the next char to be read
           * is a newline character, then just skip it right away.
           */
          if (skipLF) {
            /* Note that in.ready() will return true if and only if the next
             * read on the stream will not block.
             */
            if (nextChar >= nChars && in.ready()) {
              fill();
            }
            if (nextChar < nChars) {
              if (cb[nextChar] == '\n')
                nextChar++;
              skipLF = false;
            }
          }
          return (nextChar < nChars) || in.ready();
        }
  }
 
  /**
   * 判斷此流是否支持標記
   */
  public boolean markSupported() {
    return true;
  }
 
  /**
   * 標記此流此時的位置、當調用reset方法失效前最多允許讀取readAheadLimit個字符。
   */
  public void mark(int readAheadLimit) throws IOException {
        if (readAheadLimit < 0) {
          throw new IllegalArgumentException("Read-ahead limit < 0");
        }
        synchronized (lock) {
          ensureOpen();
          this.readAheadLimit = readAheadLimit;
          markedChar = nextChar;
          markedSkipLF = skipLF;
        }
  }
 
  /**
   * 重置in被最后一次mark的位置。即下一個字符從被最后一次mark的位置開始讀取。
   */
  public void reset() throws IOException {
        synchronized (lock) {
          ensureOpen();
          if (markedChar < 0)
            throw new IOException((markedChar == INVALIDATED)
                       ? "Mark invalid"
                       : "Stream not marked");
          nextChar = markedChar;
          skipLF = markedSkipLF;
        }
  }
 
  //關閉此流、釋放與此流有關的所有資源
  public void close() throws IOException {
        synchronized (lock) {
          if (in == null)
            return;
          in.close();
          in = null;
          cb = null;
        }
  }
}

4、實例演示:

?
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
package com.chy.io.original.test;
 
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
 
public class BufferedWriterAndBufferedReaderTest {
    /**
     * 這里對這兩個類的測試比較簡單、就是對文件字符流進行包裝、實現文件拷貝
     * 有興趣的可以測試一下效率、、偷個懶、、可無視
     */
    public static void main(String[] args) throws IOException{
        File resouceFile = new File("D:\\test.txt");
        File targetFile = new File("E:\\copyOftest.txt");
        
        BufferedReader br = new BufferedReader(new FileReader(resouceFile));
        BufferedWriter bw = new BufferedWriter(new FileWriter(targetFile));
        
        char[] cbuf = new char[1024];
        int n = 0;
        while((n = br.read(cbuf)) != -1){
            bw.write(cbuf, 0, n);
        }
        //不要忘記刷新和關閉流、否則一方面資源沒有及時釋放、另一方面有可能照成數據丟失
        br.close();
        bw.flush();
        bw.close();
    }
}

總結:

        對于BufferedReader、BufferedWriter、本質就是為底層字符輸入輸出流添加緩沖功能、先將底層流中的要讀取或者要寫入的數據先以一次讀取一組的形式來講數據讀取或者寫入到buffer中、再對buffer進行操作、這樣不但效率、還能節省資源。最后、在程序中、出于效率的考慮、也應為低級流使用這兩個類進行裝飾一下、而不是直接拿著流直接上、覺得能實現就行。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 看毛片网 | 国产精品一区二区久久 | 精品粉嫩超白一线天av | 免费观看黄视频 | 国产免费av网站 | 午夜视频在线观看网站 | 日韩精品一区二区在线 | 亚洲免费影院 | 成人激情视频 | 成人午夜影视 | 成人在线观看av | 成人在线免费观看 | 成人欧美一区二区三区视频xxx | 国产一区二区三区四区五区密私 | 日本视频一区二区三区 | 性片网站| 亚洲久久 | 精品国产乱码久久久久久蜜柚 | 天天色成人综合网 | 欧美 亚洲 一区 | 99久久国产免费 | 97成人在线免费视频 | 日本免费视频 | 欧美一区二区三区在线 | 日韩av一区二区在线观看 | 这里只有精品视频 | yy6080久久伦理一区二区 | 黄色一级毛片儿 | 欧美日韩精品一区 | 国内自拍视频网 | 久久综合av | 91在线视频观看 | 免费黄色大片网址 | 久久av一区二区三区 | 欧美日韩在线一区二区三区 | 国产精品视频在线观看 | 午夜伦理电影 | 国产一区久久久 | 久久精彩免费视频 | 成人在线视频观看 | 中文字幕一二三区 |