日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

.NET Core/.NET之Stream简介

發布時間:2023/12/4 asp.net 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET Core/.NET之Stream简介 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

之前寫了一篇C#裝飾模式的文章用.NET Core實現裝飾模式和.NET Core的Stream簡介?提到了.NET Core的Stream, 所以這里盡量把Stream介紹全點. (都是書上的內容)

.NET Core/.NET的Streams

首先需要知道, System.IO命名空間是低級I/O功能的大本營.

Stream的結構

.NET Core里面的Stream主要是三個概念: 存儲(backing stores 我不知道怎么翻譯比較好),?裝飾器, 適配器.

backing stores是讓輸入和輸出發揮作用的端點, 例如文件或者網絡連接. 就是下面任意一點或兩點:

  • 一個源, 從它這里字節可以被順序的讀取

  • 一個目的地, 字節可以被連續的寫入.

程序員可以通過Stream類來發揮backing store的作用. Stream類有一套方法, 可以進行讀取, 寫入, 定位等操作. 個數組不同的是, 數組是把所有的數據都一同放在了內存里, 而stream則是順序的/連續的處理數據, 要么是一次處理一個字節, 要么是一次處理特定大小(不能太大, 可管理的范圍內)的數據.

于是, stream可以用比較小的固定大小的內存來處理無論多大的backing store.

中間的那部分就是裝飾器Stream. 它符合裝飾模式.

從圖中可以看到, Stream又分為兩部分:

  • Backing Store Streams: 硬連接到特定類型的backing store, 例如FileStream和NetworkStream

  • Decorator Streams 裝飾器Stream: 使用某種方式把數據進行了轉化, 例如DeflateStream和CryptoStream.

裝飾器Stream有如下結構性的優點(參考裝飾模式):

  • 無需讓backing store stream去實現例如壓縮, 加密等功能.

  • 裝飾的時候接口(interface)并沒有變化

  • 可以在運行時進行裝飾

  • 可以串聯裝飾(先后進行多個裝飾)

backing store和裝飾器stream都是按字節進行處理的. 盡管這很靈活和高效, 但是程序一般還是采用更高級別的處理方式例如文字或者xml.

適配器通過使用特殊化的方法把類里面的stream進行包裝成特殊的格式. 這就彌合了上述的間隔.

例如 text reader有一個ReadLine方法, XML writer又WriteAttributes方法.

注意: 適配器包裝了stream, 這點和裝飾器一樣, 但是不一樣的是, 適配器本身并不是stream, 它一般會把所有針對字節的方法都隱藏起來. 所以本文就不介紹適配器了.

總結一下:

backing store stream 提供原始數據, 裝飾器stream提供透明的轉換(例如加密); 適配器提供方法來處理高級別的類型例如字符串和xml.

想要連成串的話, 秩序把對象傳遞到另一個對象的構造函數里.

使用Stream

Stream抽象類是所有Stream的基類.

它的方法和屬性主要分三類基本操作: 讀, 寫, 尋址(Seek); 和管理操作: 關閉(close), 沖(flush)和設定超時:

這些方法都有異步的版本, 加async, 返回Task即可.

一個例子:

using System;

using System.IO;


namespace Test

{

? ? class Program

? ? {

? ? ? ? static void Main(string[] args)

? ? ? ? {

? ? ? ? ? ? // 在當前目錄創建按一個 test.txt 文件

? ? ? ? ? ? using (Stream s = new FileStream("test.txt", FileMode.Create))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Console.WriteLine(s.CanRead); // True

? ? ? ? ? ? ? ? Console.WriteLine(s.CanWrite); // True

? ? ? ? ? ? ? ? Console.WriteLine(s.CanSeek); // True

? ? ? ? ? ? ? ? s.WriteByte(101);

? ? ? ? ? ? ? ? s.WriteByte(102);

? ? ? ? ? ? ? ? byte[] block = { 1, 2, 3, 4, 5 };

? ? ? ? ? ? ? ? s.Write(block, 0, block.Length); // 寫 5 字節

? ? ? ? ? ? ? ? Console.WriteLine(s.Length); // 7

? ? ? ? ? ? ? ? Console.WriteLine(s.Position); // 7

? ? ? ? ? ? ? ? s.Position = 0; // 回到開頭位置

? ? ? ? ? ? ? ? Console.WriteLine(s.ReadByte()); // 101

? ? ? ? ? ? ? ? Console.WriteLine(s.ReadByte()); // 102

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 從block數組開始的地方開始read:

? ? ? ? ? ? ? ? Console.WriteLine(s.Read(block, 0, block.Length)); // 5

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 假設最后一次read返回 5, 那就是在文件結尾, 所以read會返回0:

? ? ? ? ? ? ? ? Console.WriteLine(s.Read(block, 0, block.Length)); // 0

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

運行結果:

?

異步例子:

using System;

using System.IO;

using System.Threading.Tasks;


namespace Test

{

? ? class Program

? ? {

? ? ? ? static void Main(string[] args)

? ? ? ? {

? ? ? ? ? ? Task.Run(AsyncDemo).GetAwaiter().GetResult();

? ? ? ? }


? ? ? ? async static Task AsyncDemo()

? ? ? ? {

? ? ? ? ? ? using (Stream s = new FileStream("test.txt", FileMode.Create))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? byte[] block = { 1, 2, 3, 4, 5 };

? ? ? ? ? ? ? ? await s.WriteAsync(block, 0, block.Length);?

? ? ? ? ? ? ? ? s.Position = 0;

? ? ? ? ? ? ? ? Console.WriteLine(await s.ReadAsync(block, 0, block.Length));

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

異步版本比較適合慢的stream, 例如網絡的stream.

讀和寫

CanRead和CanWrite屬性可以判斷Stream是否可以讀寫.

Read方法把stream的一塊數據寫入到數組, 返回接受到的字節數, 它總是小于等于count這個參數. 如果它小于count, 就說明要么是已經讀取到stream的結尾了, 要么stream給的數據塊太小了(網絡stream經常這樣).

一個讀取1000字節stream的例子:

? ? ? ? ? // 假設s是某個stream

? ? ? ? ? ? byte[] data = new byte[1000];

? ? ? ? ? ? // bytesRead 的結束位置肯定是1000, 除非stream的長度不足1000

? ? ? ? ? ? int bytesRead = 0;

? ? ? ? ? ? int chunkSize = 1;

? ? ? ? ? ? while (bytesRead < data.Length && chunkSize > 0)

? ? ? ? ? ? ? ? bytesRead +=

? ? ? ? ? ? ? ? ? ?chunkSize = s.Read(data, bytesRead, data.Length - bytesRead);

ReadByte方法更簡單一些, 一次就讀一個字節, 如果返回-1表示讀取到stream的結尾了. 返回類型是int.

Write和WriteByte就是相應的寫入方法了. 如果無法寫入某個字節, 那就會拋出異常.

上面方法簽名里的offset參數, 表示的是緩沖數組開始讀取或寫入的位置, 而不是指stream里面的位置.

尋址 Seek

CanSeek為true的話, Stream就可以被尋址. 可以查詢和修改可尋址的stream(例如文件stream)的長度, 也可以隨時修改讀取和寫入的位置.

Position屬性就是所需要的, 它是相對于stream開始位置的.

Seek方法就允許你移動到當前位置或者stream的尾部.

注意改變FileStream的Position會花去幾微秒. 如果是在大規模循環里面做這個操作的話, 建議使用MemoryMappedFile類.

對于不可尋址的Stream(例如加密Stream), 想知道它的長度只能是把它讀完. 而且你要是想讀取前一部分的話必須關閉stream, 然后再開始一個全新的stream才可以.

關閉和Flush

Stream用完之后必須被處理掉(dispose)來釋放底層資源例如文件和socket處理. 通常使用using來實現.

  • Dispose和Close方法功能上是一樣的.

  • 重復close和flush一個stream不會報錯.

關閉裝飾器stream的時候會同時關閉裝飾器和它的backing store stream.

針對一連串的裝飾器裝飾的stream, 關閉最外層的裝飾器就會關閉所有.

有些stream從backing store讀取/寫入的時候有一個緩存機制, 這就減少了實際到backing store的往返次數以達到提高性能的目的(例如FileStream).

這就意味著你寫入數據到stream的時候可能不會立即寫入到backing store; 它會有延遲, 直到緩沖被填滿.

Flush方法會強制內部緩沖的數據被立即的寫入. Flush會在stream關閉的時候自動被調用. 所以你不需要這樣寫: s.Flush(); s.Close();

超時

如果CanTimeout屬性為true的話, 那么該stream就可以設定讀或寫的超時.

網絡stream支持超時, 而文件和內存stream則不支持.

支持超時的stream, 通過ReadTimeout和WriteTimeout屬性可以設定超時, 單位毫秒. 0表示無超時.

Read和Write方法通過拋出異常的方式來表示超時已經發生了.

線程安全

stream并不是線程安全的, 也就是說兩個線程同時讀或寫一個stream的時候就會報錯.

Stream通過Synchronized方法來解決這個問題. 該方法接受stream為參數, 返回一個線程安全的包裝結果.

這個包裝結果在每次讀, 寫, 尋址的時候會獲得一個獨立鎖/排他鎖, 所以同一時刻只有一個線程可以執行操作.

實際上, 這允許多個線程同時為同一個數據追加數據, 而其他類型的操作(例如同讀)則需要額外的鎖來保證每個線程可以訪問到stream相應的部分.

Backing Store Stream

FileStream

文件流

構建一個FileStream:?

FileStream fs1 = File.OpenRead("readme.bin"); // Read-only FileStream fs2 = File.OpenWrite(@"c:\temp\writeme.tmp"); // Write-only FileStream fs3 = File.Create(@"c:\temp\writeme.tmp"); // Read/write

?

OpenWrite和Create對于已經存在的文件來說, 它的行為是不同的.

Create會把現有文件的內容清理掉, 寫入的時候從頭開寫.

OpenWrite則是完整的保存著現有的內容, 而stream的位置定位在0. 如果寫入的內容比原來的內容少, 那么OpenWrite打開并寫完之后的內容是原內容和新寫入內容的混合體.

直接構建FileStream:

var fs = new FileStream ("readwrite.tmp", FileMode.Open); // Read/write

?

其構造函數里面還可以傳入其他參數, 具體請看文檔.

File類的快捷方法:

下面這些靜態方法會一次性把整個文件讀進內存:

  • File.ReadAllText(返回string)

  • File.ReadAllLines(返回string數組)?

  • File.ReadAllBytes(返回byte數組)

下面的方法直接寫入整個文件:

  • File.WriteAllText

  • File.WriteAllLines

  • File.WriteAllBytes

  • File.AppendAllText?(很適合附加log文件)?

還有一個靜態方法叫File.ReadLines: 它有點想ReadAllLines, 但是它返回的是一個懶加載的IEnumerable<string>. 這個實際上效率更高一些, 因為不必一次性把整個文件都加載到內存里. LINQ非常適合處理這個結果. 例如:

int longLines = File.ReadLines ("filePath").Count (l => l.Length > 80);

?

指定的文件名:

可以是絕對路徑也可以是相對路徑.

可已修改靜態屬性Environment.CurrentDirectory的值來改變當前的路徑. (注意: 默認的當前路徑不一定是exe所在的目錄)

AppDomain.CurrentDomain.BaseDirectory會返回應用的基目錄, 它通常是包含exe的目錄.?

指定相對于這個目錄的地址最好使用Path.Combine方法:

string baseFolder = AppDomain.CurrentDomain.BaseDirectory;string logoPath = Path.Combine(baseFolder, "logo.jpg");Console.WriteLine(File.Exists(logoPath));

?

通過網絡對文件讀寫要使用UNC路徑:

例如: \\JoesPC\PicShare \pic.jpg 或者 \\10.1.1.2\PicShare\pic.jpg.

FileMode:

所有的FileStream的構造器都會接收一個文件名和一個FileMode枚舉作為參數. 如果選擇FileMode請看下圖:

其他特性還是需要看文檔.

MemoryStream

MemoryStream在隨機訪問不可尋址的stream時就有用了.

如果你知道源stream的大小可以接受, 你就可以直接把它復制到MemoryStream里:

var ms = new MemoryStream();sourceStream.CopyTo(ms);

?

可以通過ToArray方法把MemoryStream轉化成數組.

GetBuffer方法也是同樣的功能, 但是因為它是直接把底層的存儲數組的引用直接返回了, 所以會更有效率. 不過不幸的是, 這個數組通常比stream的真實長度要長.

注意: Close和Flush 一個MemoryStream是可選的. 如果關閉了MemoryStream, 你就再也不能對它讀寫了, 但是仍然可以調用ToArray方法來獲取其底層的數據.

Flush則對MemoryStream毫無用處.

PipeStream

PipeStream通過Windows Pipe 協議, 允許一個進程(process)和另一個進程通信.

分兩種:

  • 匿名進程(快一點), 允許同一個電腦內的父子進程單向通信.

  • 命名進程(更靈活), 允許同一個電腦內或者同一個windows網絡內的不同電腦間的任意兩個進程間進行雙向通信

pipe很適合一個電腦上的進程間交互(IPC), 它并不依賴于網絡傳輸, 這也意味著沒有網絡開銷, 也不在乎防火墻.

注意: pipe是基于Stream的, 一個進程等待接受一串字符的同時另一個進程發送它們.

PipeStream是抽象類.

具體的實現類有4個:

匿名pipe:

  • AnonymousePipeServerStream

  • AnonymousePipeClientStream

命名Pipe:

  • NamedPipeServerStream

  • NamePipeClientStream

命名Pipe

命名pipe的雙方通過同名的pipe進行通信. 協議規定了兩個角色: 服務器和客戶端. 按照下述方式進行通信:

  • 服務器實例化一個NamedPipeServerStream然后調用WaitForConnection方法.

  • 客戶端實例化一個NamedPipeClientStream然后調用Connect方法(可以設定超時).

然后雙方就可以讀寫stream來進行通信了.

例子:

using System;

using System.IO;

using System.IO.Pipes;

using System.Threading.Tasks;


namespace Test

{

? ? class Program

? ? {

? ? ? ? static void Main(string[] args)

? ? ? ? {

? ? ? ? ? ? Console.WriteLine(DateTime.Now.ToString());

? ? ? ? ? ? using (var s = new NamedPipeServerStream("pipedream"))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? s.WaitForConnection();

? ? ? ? ? ? ? ? s.WriteByte(100); // Send the value 100.

? ? ? ? ? ? ? ? Console.WriteLine(s.ReadByte());

? ? ? ? ? ? }

? ? ? ? ? ? Console.WriteLine(DateTime.Now.ToString());

? ? ? ? }

? ? }

}

using System;

using System.IO.Pipes;


namespace Test2

{

? ? class Program

? ? {

? ? ? ? static void Main(string[] args)

? ? ? ? {

? ? ? ? ? ? Console.WriteLine(DateTime.Now.ToString());

? ? ? ? ? ? using (var s = new NamedPipeClientStream("pipedream"))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? s.Connect();

? ? ? ? ? ? ? ? Console.WriteLine(s.ReadByte());

? ? ? ? ? ? ? ? s.WriteByte(200); // Send the value 200 back.

? ? ? ? ? ? }

? ? ? ? ? ? Console.WriteLine(DateTime.Now.ToString());

? ? ? ? }

? ? }

}

命名的PipeStream默認情況下是雙向的, 所以任意一方都可以進行讀寫操作, 這也意味著服務器和客戶端必須達成某種協議來協調它們的操作, 避免同時進行發送和接收.

還需要協定好每次傳輸的長度.

在處理長度大于一字節的信息的時候, pipe提供了一個信息傳輸的模式, 如果這個啟用了, 一方在調用read的時候可以通過檢查IsMessageComplete屬性來知道消息什么時候結束.

例子:

static byte[] ReadMessage(PipeStream s)

? ? ? ? {

? ? ? ? ? ? MemoryStream ms = new MemoryStream();

? ? ? ? ? ? byte[] buffer = new byte[0x1000]; // Read in 4 KB blocks

? ? ? ? ? ? do { ms.Write(buffer, 0, s.Read(buffer, 0, buffer.Length)); }

? ? ? ? ? ? while (!s.IsMessageComplete); return ms.ToArray();

? ? ? ? }

注意: 針對PipeStream不可以通過Read返回值是0的方式來它是否已經完成讀取消息了. 這是因為它和其他的Stream不同, pipe stream和network stream沒有確定的終點. 在兩個信息傳送動作之間, 它們就干等著.

這樣啟用信息傳輸模式, 服務器端 :

using (var s = new NamedPipeServerStream("pipedream", PipeDirection.InOut, 1, PipeTransmissionMode.Message))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? s.WaitForConnection();

? ? ? ? ? ? ? ? byte[] msg = Encoding.UTF8.GetBytes("Hello");

? ? ? ? ? ? ? ? s.Write(msg, 0, msg.Length);

? ? ? ? ? ? ? ? Console.WriteLine(Encoding.UTF8.GetString(ReadMessage(s)));

? ? ? ? ? ? }

客戶端:

using (var s = new NamedPipeClientStream("pipedream"))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? s.Connect();

? ? ? ? ? ? ? ? s.ReadMode = PipeTransmissionMode.Message;

? ? ? ? ? ? ? ? Console.WriteLine(Encoding.UTF8.GetString(ReadMessage(s)));

? ? ? ? ? ? ? ? byte[] msg = Encoding.UTF8.GetBytes("Hello right back!");

? ? ? ? ? ? ? ? s.Write(msg, 0, msg.Length);

? ? ? ? ? ? }


匿名pipe:

匿名pipe提供父子進程間的單向通信. 流程如下:

  • 服務器實例化一個AnonymousPipeServerStream, 并指定PipeDirection是In還是Out

  • 服務器調用GetClientHandleAsString方法來獲取一個pipe的標識, 然后會把它傳遞給客戶端(通常是啟動子進程的參數 argument)

  • 子進程實例化一個AnonymousePipeClientStream, 指定相反的PipeDirection

  • 服務器通過調用DisposeLocalCopyOfClientHandle釋放步驟2的本地處理,?

  • 父子進程間通過讀寫stream進行通信

因為匿名pipe是單向的, 所以服務器必須創建兩份pipe來進行雙向通信

例子:

server:

using System;

using System.Diagnostics;

using System.IO;

using System.IO.Pipes;

using System.Text;

using System.Threading.Tasks;


namespace Test

{

? ? class Program

? ? {

? ? ? ? static void Main(string[] args)

? ? ? ? {

? ? ? ? ? ? string clientExe = @"D:\Projects\Test2\bin\Debug\netcoreapp2.0\win10-x64\publish\Test2.exe";

? ? ? ? ? ? HandleInheritability inherit = HandleInheritability.Inheritable;

? ? ? ? ? ? using (var tx = new AnonymousPipeServerStream(PipeDirection.Out, inherit))

? ? ? ? ? ? using (var rx = new AnonymousPipeServerStream(PipeDirection.In, inherit))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? string txID = tx.GetClientHandleAsString();

? ? ? ? ? ? ? ? string rxID = rx.GetClientHandleAsString();

? ? ? ? ? ? ? ? var startInfo = new ProcessStartInfo(clientExe, txID + " " + rxID);

? ? ? ? ? ? ? ? startInfo.UseShellExecute = false; // Required for child process

? ? ? ? ? ? ? ? Process p = Process.Start(startInfo);

? ? ? ? ? ? ? ? tx.DisposeLocalCopyOfClientHandle(); // Release unmanaged

? ? ? ? ? ? ? ? rx.DisposeLocalCopyOfClientHandle(); // handle resources.

? ? ? ? ? ? ? ? tx.WriteByte(100);

? ? ? ? ? ? ? ? Console.WriteLine("Server received: " + rx.ReadByte());

? ? ? ? ? ? ? ? p.WaitForExit();

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

client:

using System;

using System.IO.Pipes;


namespace Test2

{

? ? class Program

? ? {

? ? ? ? static void Main(string[] args)

? ? ? ? {

? ? ? ? ? ? string rxID = args[0]; // Note we're reversing the

? ? ? ? ? ? string txID = args[1]; // receive and transmit roles.

? ? ? ? ? ? using (var rx = new AnonymousPipeClientStream(PipeDirection.In, rxID))

? ? ? ? ? ? using (var tx = new AnonymousPipeClientStream(PipeDirection.Out, txID))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Console.WriteLine("Client received: " + rx.ReadByte());

? ? ? ? ? ? ? ? tx.WriteByte(200);

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

最好發布一下client成為獨立運行的exe:

dotnet publish --self-contained --runtime win10-x64

?

運行結果:

?

匿名pipe不支持消息模式, 所以你必須自己來為傳輸的長度制定協議. 有一種做法是: 在每次傳輸的前4個字節里存放一個整數表示消息的長度, 可以使用BitConverter類來對整型和長度為4的字節數組進行轉換.

BufferedStream

BufferedStream對另一個stream進行裝飾或者說包裝, 讓它擁有緩沖的能力.它也是眾多裝飾stream類型中的一個.

緩沖肯定會通過減少往返backing store的次數來提升性能.

下面這個例子是把一個FileStream裝飾成20k的緩沖stream:

// Write 100K to a file:

? ? ? ? ? ? File.WriteAllBytes("myFile.bin", new byte[100000]);

? ? ? ? ? ? using (FileStream fs = File.OpenRead("myFile.bin"))

? ? ? ? ? ? using (BufferedStream bs = new BufferedStream(fs, 20000)) //20K buffer

? ? ? ? ? ? {

? ? ? ? ? ? ? ? bs.ReadByte();

? ? ? ? ? ? ? ? Console.WriteLine(fs.Position); // 20000

? ? ? ? ? ? }

? ? ? ? }

通過預讀緩沖, 底層的stream會在讀取1字節后, 直接預讀了20000字節, 這樣我們在另外調用ReadByte 19999次之后, 才會再次訪問到FileStream.

這個例子是把BufferedStream和FileStream耦合到一起, 實際上這個例子里面的緩沖作用有限, 因為FileStream有一個內置的緩沖. 這個例子也只能擴大一下緩沖而已.

關閉BufferedStream就會關閉底層的backing store stream..

Stream適配器

Stream只按字節處理, 對string, 整型, xml等都是通過字節進行讀寫的, 所以必須插入一個適配器.

.NET Core提供了這些文字適配器:

  • TextReader, TextWriter

  • StreamReader, StreamWriter

  • StringReader, StringWriter

二進制適配器(適用于原始類型例如int bool string float等):

  • BinaryReader, BinaryWriter

XML適配器:

  • XmlReader, XmlWiter

這些適配器的關系圖:

文字適配器

TextReader 和 TextWriter是文字適配器的基類. 它倆分別對應兩套實現:

  • StreamReader/StreamWriter: 使用Stream作為原始數據存儲, 把stream的字節轉化成字符或字符串

  • StringReader/StringWriter: 使用的是內存中的字符串

TextReader:

Peek方法會返回下一個字符而不改變當前(可以看作是索引)的位置.

在Stream讀取到結束點的時候Peek和無參數的Read方法都會返回-1, 否則它們會返回一個可以被轉換成字符的整型.

Read的重載方法(接受char[]緩沖參數)在功能上和ReadBlock方法是一樣的.

ReadLine方法會一直讀取直到遇到了CR或LF或CR+LF對(以后再介紹), 然后會放回字符串, 但是不包含CR/LF等字符.

注意: C#應該使用"\r\n"來還行, 順序寫反了可能會不換行患者換兩行.

TextWriter:

方法與TextReader類似.

Write和WriteLine有幾個重載方法可以接受所有的原始類型, 還有object類型. 這些方法會調用被傳入參數的ToString方法. 另外也可以在構造函數或者調用方法的時候通過IFormatProvider進行指定.

WriteLine會在給定的文字后邊加上CR+LF, 您可以通過修改NewLine屬性來改變這個行為(尤其是與UNIX文件格式交互的時候).

上面講的這些方法, 都有異步版本的

?

StreamReader和StreamWriter

直接看例子即可:

using (FileStream fs = File.Create("test.txt"))

? ? ? ? ? ? using (TextWriter writer = new StreamWriter(fs))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? writer.WriteLine("Line 1");

? ? ? ? ? ? ? ? writer.WriteLine("Line 2");

? ? ? ? ? ? }


? ? ? ? ? ? using (FileStream fs = File.OpenRead("test.txt"))

? ? ? ? ? ? using (TextReader reader = new StreamReader(fs))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Console.WriteLine(reader.ReadLine());

? ? ? ? ? ? ? ? Console.WriteLine(reader.ReadLine());

? ? ? ? ? ? }

?

由于文字適配器經常要處理文件, 所以File類提供了一些靜態方法例如: CreateText, AppendText, OpenText來做快捷操作:

上面的例子可以寫成:

using (TextWriter writer = File.CreateText("test.txt"))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? writer.WriteLine("Line1");

? ? ? ? ? ? ? ? writer.WriteLine("Line2");

? ? ? ? ? ? }

? ? ? ? ? ? using (TextWriter writer = File.AppendText("test.txt"))

? ? ? ? ? ? ? ? writer.WriteLine("Line3");

? ? ? ? ? ? using (TextReader reader = File.OpenText("test.txt"))

? ? ? ? ? ? ? ? while (reader.Peek() > -1)

? ? ? ? ? ? ? ? ? ? Console.WriteLine(reader.ReadLine());

代碼中可以看到, 如何知道是否讀取到了文件的結尾(通過reader.Peek()). 另一個方法是使用reader.ReadLine方法讀取直到返回null.

也可以讀取其他的類型, 例如int(因為TextWriter會調用ToString方法), 但是讀取的時候想要變成原來的類型就得進行解析字符串操作了.

?

字符串編碼

TextReader和TextWriter是抽象類, 跟sream或者backing store沒有連接. StreamReader和StreamWriter則連接著一個底層的字節流, 所以它們必須對字符串和字節進行轉換. 它們通過System.Text.Encoding類來做這些工作, 也就是構建StreamReader或StreamWriter的時候選擇一個Encoding. 如果你沒選那么就是UTF-8了.

注意: 如果你明確指定了一個編碼, 那么StreamWriter默認會在流的前邊加一個前綴, 這個前綴是用來識別編碼的. 如果你不想這樣做的話, 那么可以這樣做:

var encoding = new UTF8Encoding( ? ? ? ? ? ? ? ?encoderShouldEmitUTF8Identifier: false,throwOnInvalidBytes: true);

?

第二個參數是告訴StreamWriter, 如果遇到了本編碼下的非法字符串, 那就拋出一個異常. 如果不指定編碼的情況下, 也是這樣的.

最簡單的編碼是ASCII, 每一個字符通過一個字節來表示. ASCII對Unicode的前127個字符進行了映射, 包含了US鍵盤上面所有的鍵. 而其他的字符, 例如特殊字符和非英語字符等無法被表達的字符則會顯示成□. 默認的UTF-8編碼影射了所有的Unicode字符, 但是它更復雜. 前127個字節使用單字節, 這是為了和ASCII兼容; 而剩下的字節編碼成了不定長的字節數(通常是2或者3字節).

UTF-8處理西方語言的文字還不錯, 但是在stream里面搜索/尋址就會遇到麻煩了, 這時可以使用UTF-16這個候選(Encoding類里面叫Unicode).

UTF-16針對每個字符使用2個或4個字節, 但是由于C#的char類型是16bit的, 所以針對.NET的char, UTF-16正好使用兩個字節. 這樣在stream里面找到特定字符的索引就方便多了.

UTF-16會使用一個2字節長的前綴, 來識別字節對是按little-endian還是big-endian的順序存儲的. windows系統默認使用little-endian.

?

StringReader和StringWriter

這兩個適配器根本不包裝stream; 它們使用String或StringBuilder作為數據源, 所以不需要字節轉換.?

實際上這兩個類存在的主要優勢就是: 它們和StreamReader/StreamWriter具有同一個父類.

例如有一個含有xml的字符串, 我想把它用XmlReader進行解析, XmlReader.Create方法可以接受下列參數:

  • URI

  • Stream

  • TextReader

因為StringReader是TextReader的子類, 所以我就可以這樣做:

XmlReader reader = XmlReader.Create(new StringReader("...xml string..."));

?

二進制適配器

BinaryReader和BinaryWriter可以讀取/寫入下列類型: bool, byte, char, decimal, float, double, short, int, long, sbyte, ushort, uint, ulong 以及string和由原始類型組成的數組.

和StreamReader/StreamWriter不同的是, 二進制適配器對原始數據類型的存儲效率是非常高的, 因為都是在內存里.

int使用4個字節, double 8個字節......

string則是通過文字編碼(就像StreamReader和StreamWriter), 但是長度是固定的, 以便可以對string回讀, 而不需要使用分隔符.

舉個例子:

public class Person

? ? {

? ? ? ? public string Name;

? ? ? ? public int Age;

? ? ? ? public double Height;


? ? ? ? public void SaveData(Stream s)

? ? ? ? {

? ? ? ? ? ? var w = new BinaryWriter(s);

? ? ? ? ? ? w.Write(Name);

? ? ? ? ? ? w.Write(Age);

? ? ? ? ? ? w.Write(Height);

? ? ? ? ? ? w.Flush();

? ? ? ? }


? ? ? ? public void LoadData(Stream s)

? ? ? ? {

? ? ? ? ? ? var r = new BinaryReader(s);

? ? ? ? ? ? Name = r.ReadString();

? ? ? ? ? ? Age = r.ReadInt32();

? ? ? ? ? ? Height = r.ReadDouble();

? ? ? ? }


? ? }

這個例子里, Person類使用SaveData和LoadData兩個方法把它的數據寫入到Stream/從Stream讀取出來, 里面用的是二進制適配器.

由于BinaryReader可以讀取到字節數組, 所以可以把要讀取的內容轉化成可尋址的stream:

byte[] data = new BinaryReader(s).ReadBytes((int)sbyte.Length);

??

關閉和清理Stream適配器

有四種做法可以把stream適配器清理掉:

  • 只關閉適配器

  • 關閉適配器, 然后關閉stream

  • (對于Writers), Flush適配器, 然后關閉Stream.

  • (對于Readers), 關閉Stream.

  • 注意: Close和Dispose對于適配器來說功能是一樣的, 這點對Stream也一樣.

    上面的前兩種寫法實際上是一樣的, 因為關閉適配器的話會自動關閉底層的Stream. 當嵌套使用using的時候, 就是隱式的使用方法2:

    using (FileStream fs = File.Create("test.txt")) ? ? ? ?
    ? ?
    using (TextWriter writer = new StreamWriter(fs)){writer.WriteLine("Line");}

    ?

    這是因為嵌套的dispose是從內而外的, 適配器先關閉, 然后是Stream. 此外, 如果在適配器的構造函數里發生異常了, 這個Stream仍然會關閉, 嵌套使用using是很難出錯的.

    注意: 不要在關閉或flush stream的適配器writer之前去關閉stream, 那會截斷在適配器緩沖的數據.

    第3, 4中方法之所以可行, 是因為適配器是比較另類的, 它們是可選disposable的對象. 看下面的例子:

    using (FileStream fs = new FileStream("test.txt", FileMode.Create))

    ? ? ? ? ? ? {

    ? ? ? ? ? ? ? ? StreamWriter writer = new StreamWriter(fs);

    ? ? ? ? ? ? ? ? writer.WriteLine("Hello");

    ? ? ? ? ? ? ? ? writer.Flush();


    ? ? ? ? ? ? ? ? fs.Position = 0;

    ? ? ? ? ? ? ? ? Console.WriteLine(fs.ReadByte());

    ? ? ? ? ? ? }

    這里, 我對一個文件進行了寫入動作, 然后重定位stream, 讀取第一個字節. 我想把Stream開著, 因為以后還要用到.

    這時, 如果我dispose了StreamWriter, 那么FileStream就被關閉了, 以后就無法操作它了. 所以沒有調用writer的dispose或close方法.

    但是這里需要flush一下, 以確保StreamWriter的緩存的內容都寫入到了底層的stream里.

    注意: 鑒于適配器的dispose是可選的, 所以不再使用的適配器就可以躲開GC的清理操作.

    .net 4.5以后, StreamReader/StreamWriter有了一個新的構造函數, 它可以接受一個參數, 來指定在dispose之后是否讓Stream保持開放:

    using (var fs = new FileStream("test.txt", FileMode.Create))

    ? ? ? ? ? ? {

    ? ? ? ? ? ? ? ? using (var writer = new StreamWriter(fs, new UTF8Encoding(false, true),

    ? ? ? ? ? ? ? ? 0x400, true))

    ? ? ? ? ? ? ? ? ? ? writer.WriteLine("Hello");

    ? ? ? ? ? ? ? ? fs.Position = 0; Console.WriteLine(fs.ReadByte());

    ? ? ? ? ? ? ? ? Console.WriteLine(fs.Length);

    ? ? ? ? ? ? }

    壓縮Stream

    在System.IO.Compression下有兩個壓縮Stream: DeflateStream和GZipStream. 它們都使用了一個類似于ZIP格式的壓縮算法. 不同的是GZipStream會在開頭和結尾寫入額外的協議--包括CRC錯誤校驗.GZipStream也符合其他軟件的標準.

    這兩種Stream在讀寫的時候有這兩個條件:

    • 寫入Stream的時候是壓縮

    • 讀取Stream的時候是解壓縮

    DeflateStream和GZipStream都是裝飾器(參考裝飾設計模式); 它們會壓縮/解壓縮從構造函數傳遞進來的Stream. 例如:

    using (Stream s = File.Create("compressed.bin"))

    ? ? ? ? ? ? using (Stream ds = new DeflateStream(s, CompressionMode.Compress))

    ? ? ? ? ? ? ? ? for (byte i = 0; i < 100; i++)

    ? ? ? ? ? ? ? ? ? ? ds.WriteByte(i);

    ? ? ? ? ? ? using (Stream s = File.OpenRead("compressed.bin"))

    ? ? ? ? ? ? using (Stream ds = new DeflateStream(s, CompressionMode.Decompress))

    ? ? ? ? ? ? ? ? for (byte i = 0; i < 100; i++)

    ? ? ? ? ? ? ? ? ? ? Console.WriteLine(ds.ReadByte()); // Writes 0 to 99

    上面這個例子里, 即使是壓縮的比較小的, 文件在壓縮后也有241字節長, 比原來的兩倍還多....這是因為, 壓縮算法對于這種"稠密"的非重復的二進制數據處理的很不好(加密的數據更完), 但是它對文本類的文件還是處理的很好的.

    Task.Run(async () =>

    ? ? ? ? ? ? {

    ? ? ? ? ? ? ? ? string[] words = "The quick brown fox jumps over the lazy dog".Split();

    ? ? ? ? ? ? ? ? Random rand = new Random();

    ? ? ? ? ? ? ? ? using (Stream s = File.Create("compressed.bin"))

    ? ? ? ? ? ? ? ? using (Stream ds = new DeflateStream(s, CompressionMode.Compress))

    ? ? ? ? ? ? ? ? using (TextWriter w = new StreamWriter(ds))

    ? ? ? ? ? ? ? ? ? ? for (int i = 0; i < 1000; i++)

    ? ? ? ? ? ? ? ? ? ? ? ? await w.WriteAsync(words[rand.Next(words.Length)] + " ");

    ? ? ? ? ? ? ? ? Console.WriteLine(new FileInfo("compressed.bin").Length);

    ? ? ? ? ? ? ? ? using (Stream s = File.OpenRead("compressed.bin"))

    ? ? ? ? ? ? ? ? using (Stream ds = new DeflateStream(s, CompressionMode.Decompress))

    ? ? ? ? ? ? ? ? using (TextReader r = new StreamReader(ds))

    ? ? ? ? ? ? ? ? ? ? Console.Write(await r.ReadToEndAsync());

    ? ? ? ? ? ? }).GetAwaiter().GetResult();


    壓縮后的長度是856!

    在內存中壓縮

    有時候需要把整個壓縮都放在內存里, 這就要用到MemoryStream:

    byte[] data = new byte[1000]; // 對于空數組, 我們可以期待一個很好的壓縮比率!

    ? ? ? ? ? ? var ms = new MemoryStream();

    ? ? ? ? ? ? using (Stream ds = new DeflateStream(ms, CompressionMode.Compress))

    ? ? ? ? ? ? ? ? ds.Write(data, 0, data.Length);

    ? ? ? ? ? ? byte[] compressed = ms.ToArray();

    ? ? ? ? ? ? Console.WriteLine(compressed.Length); // 14

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 解壓回數組:

    ? ? ? ? ? ? ms = new MemoryStream(compressed);

    ? ? ? ? ? ? using (Stream ds = new DeflateStream(ms, CompressionMode.Decompress))

    ? ? ? ? ? ? ? ? for (int i = 0; i < 1000; i += ds.Read(data, i, 1000 - i)) ;

    這里第一個using走完的時候MemoryStream會被關閉, 所以只能使用ToArray方法來提取它的數據.

    下面是另外一種異步的做法, 可以避免關閉MemoryStream:

    Task.Run(async () =>

    ? ? ? ? ? ? {

    ? ? ? ? ? ? ? ? byte[] data = new byte[1000];

    ? ? ? ? ? ? ? ? MemoryStream ms = new MemoryStream();

    ? ? ? ? ? ? ? ? using (Stream ds = new DeflateStream(ms, CompressionMode.Compress, true))

    ? ? ? ? ? ? ? ? ? ? await ds.WriteAsync(data, 0, data.Length);

    ? ? ? ? ? ? ? ? Console.WriteLine(ms.Length);

    ? ? ? ? ? ? ? ? ms.Position = 0;

    ? ? ? ? ? ? ? ? using (Stream ds = new DeflateStream(ms, CompressionMode.Decompress))

    ? ? ? ? ? ? ? ? ? ? for (int i = 0; i < 1000; i += await ds.ReadAsync(data, i, 1000 - i)) ;

    ? ? ? ? ? ? }).GetAwaiter().GetResult();

    注意DeflateStream的最后一個參數.

    ?

    ZIP文件操作

    .NET 4.5之后, 通過新引入的ZpiArchive和ZipFile類(System.IO.Compression下, Assembly是System.IO.Compression.FileSytem.dll), 我們就可以直接操作zip文件了.

    zip格式相對于DelfateStream和GZipStream的優勢是, 它可以作為多個文件的容器.

    ZipArchive配合Stream進行工作, 而ZipFile則是更多的和文件打交道.(ZipFile是ZipArchive的一個Helper類).

    ZipFIle的CreateFromDirectory方法會把指定目錄下的所有文件打包成zip文件:

    ZipFile.CreateFromDirectory (@"d:\MyFolder", @"d:\compressed.zip");

    ?

    而ExtractToDirectory則是做相反的工作:

    ZipFile.ExtractToDirectory (@"d:\compressed.zip", @"d:\MyFolder");

    ?

    壓縮的時候, 可以指定是否對文件的大小, 壓縮速度進行優化, 也可以指定壓縮后是否包含源目錄.

    ZipFile的Open方法可以用來讀寫單獨的條目, 它會返回一個ZipArchive對象(你也可以通過使用Stream對象初始化ZipArchive對象得到). 調用Open方法的時候, 你可以指定文件名和指定想要進行的動作: 讀, 寫, 更新. 你可以通過Entries屬性遍歷所有的條目, 想找到特定的條目可以使用GetEntry方法:

    using (ZipArchive zip = ZipFile.Open (@"d:\zz.zip", ZipArchiveMode.Read)) ? ?foreach (ZipArchiveEntry entry in zip.Entries)Console.WriteLine (entry.FullName + " " + entry.Length);

    ?

    ZipArchiveEntry還有一個Delete方法和一個ExtractToFile(這個其實是ZipFIleExtensions里面的extension方法)方法, 還有個Open方法返回可讀寫的Stream. 你可以通過調用CreateEntry方法(或者CreateEntryFromFile這個extension方法)在ZipArchive上創建新的條目.

    例子:

    byte[] data = File.ReadAllBytes (@"d:\foo.dll");using (ZipArchive zip = ZipFile.Open (@"d:\zz.zip", ZipArchiveMode.Update))zip.CreateEntry (@"bin\X64\foo.dll").Open().Write (data, 0, data.Length);

    ?

    上面例子里的操作完全可以在內存中實現, 使用MemoryStream即可.

    相關文章:

    • 用.NET Core實現裝飾模式和.NET Core的Stream簡介

    • C# ?觀察者模式 以及 delegate 和 event

    • 用C#(.NET Core) 實現簡單工廠和工廠方法設計模式

    • 用C# (.NET Core) 實現抽象工廠設計模式

    • 使用 C#/.NET Core 實現單體設計模式

    • 使用C# (.NET Core) 實現命令設計模式 (Command Pattern)

    • 使用C#實現適配器模式 (Adapter Pattern) 和外觀模式 (Facade Pattern)

    原文地址?:http://www.cnblogs.com/cgzl/p/8722498.html

    .NET社區新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com

    總結

    以上是生活随笔為你收集整理的.NET Core/.NET之Stream简介的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    久久久av电影 | 久久精品国产亚洲精品 | 国产成人三级 | 久久黄色网址 | 在线免费观看视频a | 国产精品高清在线 | 高清av免费一区中文字幕 | 91麻豆精品国产91久久久久久久久 | 国产午夜三级一区二区三桃花影视 | 狠狠色香婷婷久久亚洲精品 | 91麻豆国产福利在线观看 | 四虎影视精品永久在线观看 | 日韩av区 | 夜夜操天天摸 | 久久国产精品色婷婷 | 亚洲综合在线发布 | 17婷婷久久www | 天天做日日做天天爽视频免费 | 四虎在线免费观看视频 | 五月婷亚洲 | 中文字幕av播放 | 久久久久久久亚洲精品 | av黄色一级片 | 97在线精品国自产拍中文 | 99精品视频在线观看 | 天天色天天色 | 98涩涩国产露脸精品国产网 | 99日韩精品 | 91人人爱 | 在线看黄色的网站 | 特级黄色电影 | 激情图片区 | 麻花天美星空视频 | 免费观看性生活大片3 | 97在线观看 | 欧美性猛片, | 五月婷婷婷婷婷 | 毛片网站免费在线观看 | 亚洲欧洲精品在线 | 日本精品一区二区三区在线观看 | 成年人视频在线免费播放 | 亚洲午夜久久久久 | 天天干夜夜爽 | 91精选在线观看 | 日韩免费大片 | 亚洲热久久 | 天天射天天艹 | 国产69精品久久久久久 | 青青草国产精品视频 | 操操操日日日干干干 | 色激情五月 | 黄色小说在线免费观看 | 波多野结衣电影一区 | 日韩 国产| 黄色成人av在线 | 五月丁婷婷 | 精品亚洲va在线va天堂资源站 | 91视频在线网址 | 69热国产视频 | 999ZYZ玖玖资源站永久 | 国产不卡视频在线 | 成人黄色大片网站 | 91禁在线看 | 免费在线观看不卡av | 人成免费网站 | av7777777| 91激情视频在线 | 国产高清av | 久久影视中文字幕 | 久久久精品亚洲 | 婷婷亚洲综合五月天小说 | 国产精选视频 | 欧美福利片在线观看 | 中文字幕中文字幕在线中文字幕三区 | 国产精品色在线 | 日韩中文字幕在线观看 | 亚洲 欧美 变态 国产 另类 | 亚洲成色777777在线观看影院 | 深爱激情久久 | 91av欧美| 久久国产剧场电影 | 日韩黄色网络 | 日韩欧美综合在线视频 | 91高清视频| 免费69视频 | 国产亚州av | 91丨porny丨九色 | 久久久人人爽 | 黄色aaa毛片 | 中文字幕在线观看第一区 | 国产黄色成人av | 久久综合之合合综合久久 | 青青河边草观看完整版高清 | 国外调教视频网站 | 天天爽人人爽夜夜爽 | 亚洲久草在线视频 | 婷婷丁香激情五月 | 韩国在线一区二区 | 久久er99热精品一区二区三区 | 久久免费资源 | 日韩精品免费一区 | 91久久精品日日躁夜夜躁国产 | 激情小说 五月 | 伊人天堂av | 天天色宗合 | 麻豆视频在线看 | 夜夜躁日日躁 | 国产欧美综合在线观看 | 特级黄色片免费看 | 日韩精品你懂的 | 激情网站网址 | 欧美日韩精品影院 | 欧美综合干 | 中文字幕在线播放一区二区 | 国产精品96久久久久久吹潮 | 91精品国产91久久久久福利 | 麻豆首页 | 在线国产激情视频 | 干天天 | 激情视频一区二区三区 | 色av男人的天堂免费在线 | 国产视频一二三 | 国产精品毛片一区二区三区 | 911av视频| av 在线观看 | 天天干夜夜夜操天 | 五月婷婷激情网 | 国产福利网站 | 欧美在线观看小视频 | 免费人人干| 日韩r级电影在线观看 | 天天色天| 久久国产美女 | av片中文字幕| 亚洲国内精品 | 99免费精品 | 91片网| 国产资源中文字幕 | 国产成人精品久久久久 | 天天色天天操天天爽 | 349k.cc看片app| 中文字幕日韩伦理 | 美女免费网视频 | 免费精品在线视频 | 亚洲精品免费在线观看视频 | 国内少妇自拍视频一区 | 亚洲 在线| www久久久久| 偷拍精偷拍精品欧洲亚洲网站 | 国产精品美女免费看 | 青青河边草观看完整版高清 | 国产精品v a免费视频 | 麻豆一区二区 | 久久视频这里只有精品 | 91精品国产99久久久久 | 最新av网址在线 | 又黄又爽的视频在线观看网站 | 狠狠黄| 97福利在线 | 日韩av免费在线电影 | 久久精品99国产 | 欧美激情视频一区 | 午夜视频在线观看欧美 | 麻豆视频观看 | 欧美精品在线观看 | 日韩精品视频第一页 | 国产精品永久免费视频 | 欧美精品一区二区免费 | 一区二区三区不卡在线 | 成年人在线免费看 | 深爱激情开心 | 午夜精品久久久久久久爽 | 天天射天天操天天 | 久久免费看视频 | 99精品在线免费观看 | 国产97在线视频 | 免费的黄色av | 精品久久久一区二区 | 中文字幕亚洲欧美日韩 | 欧美不卡视频在线 | 超碰成人网 | 国产在线一区二区 | 国产成人精品久久久久蜜臀 | 高清不卡一区二区三区 | 国内精品中文字幕 | 国产69精品久久99不卡的观看体验 | 天天插狠狠干 | 国产999精品 | 成人免费看片98欧美 | 九九热国产视频 | 制服丝袜天堂 | 91色网址| 免费特级黄色片 | 国产91精品一区二区麻豆亚洲 | 日韩v在线 | 91亚洲精品久久久久图片蜜桃 | 天天玩天天干 | 国产综合激情 | 国产精品99久久久久久久久久久久 | 男女精品久久 | 丁香五月网久久综合 | 午夜久久网站 | 干干干操操操 | 激情影院在线 | 午夜精品福利一区二区三区蜜桃 | 午夜视频免费在线观看 | 色姑娘综合天天 | 亚洲精品tv | 天天玩天天干天天操 | 日日操狠狠干 | 99精品视频在线播放免费 | 日韩成人黄色av | av中文天堂在线 | 久久久穴 | 成年人毛片在线观看 | 欧美中文字幕久久 | 色亚洲激情 | 精品人人人人 | 91成人在线免费观看 | 亚洲欧美视屏 | 国产欧美日韩精品一区二区免费 | 国产成人精品综合久久久 | 久久国产精品偷 | 成人在线观看你懂的 | 欧美日韩高清一区 | 日操操 | 亚洲成人精品在线观看 | 高清国产午夜精品久久久久久 | 人人爽人人射 | 亚洲欧美一区二区三区孕妇写真 | 欧美日韩国产一区二 | 国产小视频在线播放 | 日韩精品免费在线 | 日日日日 | 色狠狠综合| 亚洲 欧美 国产 va在线影院 | 又黄又刺激又爽的视频 | 欧美视频一区二 | 婷婷丁香狠狠爱 | 天天躁日日躁狠狠躁av麻豆 | 久久久久亚洲国产 | 欧美日韩1区 | 一区二区三区日韩视频在线观看 | 精品日韩中文字幕 | 国产精品九九九九九九 | 国产精品自产拍在线观看蜜 | 国产精品一区二区久久 | 色婷婷国产精品一区在线观看 | 99热最新精品 | 中文字幕在线网址 | 天天射天 | 在线v片免费观看视频 | 天天干天天干天天色 | 黄色亚洲 | 国产区久久| 色多多视频在线 | 婷婷伊人五月 | 九九热免费在线视频 | 激情视频二区 | 激情 亚洲| 在线观看av不卡 | av福利在线免费观看 | av电影av在线 | 亚洲精品456在线播放乱码 | 久久尤物电影视频在线观看 | 亚洲一区二区三区四区精品 | 国产网站在线免费观看 | 国产精品理论片在线观看 | 欧美精品一级视频 | 国产高清网站 | 在线观看免费av片 | 黄色大片日本 | 久久免费观看少妇a级毛片 久久久久成人免费 | 天堂av在线网址 | 九九视频在线观看视频6 | 91高清免费观看 | 99草视频 | 2018好看的中文在线观看 | 午夜国产福利在线观看 | 在线精品国产 | 色是在线视频 | 国产成人一二片 | 久久调教视频 | 欧美日韩精品在线视频 | 精品一二区 | 亚洲精品国产精品国产 | 国产黄色在线看 | 黄p在线播放 | 国产综合香蕉五月婷在线 | 国产视频亚洲精品 | 色婷婷六月天 | 九草视频在线 | 欧美成人亚洲成人 | 久久激情电影 | 天天射天天爱天天干 | 在线精品亚洲一区二区 | 免费精品人在线二线三线 | 在线免费中文字幕 | 免费看片日韩 | 天无日天天操天天干 | 精品国产aⅴ麻豆 | 欧美特一级片 | 亚洲 精品在线视频 | 九九涩涩av台湾日本热热 | 中文字幕中文中文字幕 | 欧美性久久久 | 国产精品永久在线 | 亚洲热视频 | 欧洲亚洲精品 | 天天操天天舔天天干 | 蜜臀av性久久久久蜜臀aⅴ四虎 | av高清一区二区三区 | 免费三级黄色片 | 免费a现在观看 | 成年人电影毛片 | 激情久久五月 | 男女视频91 | a黄色| 精品国产欧美一区二区 | 国产九色在线播放九色 | 精品国产福利在线 | 免费看的av片 | 91成人天堂久久成人 | 99视频这里只有 | 国产精品亚洲片夜色在线 | 日韩电影在线观看中文字幕 | 亚洲爱av| 成人免费在线视频观看 | 成人毛片一区 | 久久免费a| 欧美精品中文字幕亚洲专区 | 国产污视频在线观看 | 日韩99热 | va视频在线 | 美女在线观看av | 美女网站久久 | 精品黄色片 | 91理论片午午伦夜理片久久 | 超碰97免费 | 天天操天天玩 | 丁香电影小说免费视频观看 | 国产精品久久久久久久久久不蜜月 | 亚洲专区在线视频 | 日韩高清毛片 | 最近中文字幕大全中文字幕免费 | 最近2019年日本中文免费字幕 | 久久久久99精品成人片三人毛片 | av网址最新 | av网站在线免费观看 | 国产一级黄 | 久久久www成人免费毛片麻豆 | 日韩成人精品 | 欧美日韩午夜在线 | 免费观看国产视频 | 欧美日韩一区二区视频在线观看 | 国产视频一区在线免费观看 | 西西44人体做爰大胆视频 | 少妇性aaaaaaaaa视频 | h视频日本 | 9999精品| 国产毛片久久 | 国产成人福利在线观看 | 天天艹天天 | 在线观看91精品国产网站 | 欧美大片大全 | 国产涩图| 国产中文a | 久久免费视频2 | 又黄又刺激的网站 | 亚洲欧美色婷婷 | 久久久精品视频成人 | 午夜视频99 | 国产视频黄 | 国产成人精品亚洲 | 日韩黄在线观看 | 日日日日 | 久久久久 免费视频 | 97色噜噜 | 久久天堂影院 | 91丨九色丨蝌蚪丨老版 | 久久久国产精品成人免费 | 国产中文字幕第一页 | 亚洲精区二区三区四区麻豆 | 97超碰中文字幕 | 亚洲九九九在线观看 | 色一级片 | 激情综合网在线观看 | 国产 视频 高清 免费 | av免费电影在线观看 | 久久五月激情 | 色综合在| 天天夜夜狠狠操 | 久久无码精品一区二区三区 | 美女搞黄国产视频网站 | av一区二区在线观看中文字幕 | 97成人精品视频在线播放 | 91精品毛片 | av黄色一级片 | 在线观看一区二区视频 | 中文字幕在线观看2018 | 亚洲天堂色婷婷 | 不卡av免费在线观看 | 亚洲精品久久在线 | 国产黄在线免费观看 | 欧美激情视频一区二区三区 | 日韩在线观看影院 | 九九99靖品| 日本不卡视频 | 国产在线播放观看 | www.天天干 | 亚洲欧美日韩一区二区三区在线观看 | 成人av在线资源 | 欧美精品一区在线发布 | 国产淫片免费看 | 免费欧美精品 | 黄色视屏免费在线观看 | 国产精品久久久久久久久久东京 | 国产做爰视频 | 黄色成人影视 | 在线国产专区 | 欧美天天射 | 国产高清视频免费 | 日本激情中文字幕 | 高潮久久久久久久久 | 国产成人高清在线 | 69视频网站 | 97视频播放 | 操老逼免费视频 | 91在线一区二区 | 美女天天操 | 黄a网站| 久久综合偷偷噜噜噜色 | 中文资源在线播放 | 国产精品一区二区免费 | 精品成人免费 | 手机看片99 | 一区二区三区国产欧美 | 国产精品成人自产拍在线观看 | 在线草 | 日日爽 | 福利av影院 | 国产精品理论片在线播放 | 久久日韩精品 | 91少妇精拍在线播放 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 亚洲精品高清在线 | 婷婷色在线资源 | 欧美在线18 | 国产精品福利视频 | 成人高清av在线 | 超碰人人超碰 | 亚洲日本精品视频 | 久久一区二区三区国产精品 | 69av免费视频 | 激情网五月天 | 午夜丰满寂寞少妇精品 | 在线亚洲人成电影网站色www | 三级黄在线 | 国产一区二区免费 | 99精品国产高清在线观看 | 午夜精品一区二区三区在线播放 | 中文字幕在线免费看 | 91精品在线免费观看视频 | 日韩中文字幕国产精品 | 五月婷在线 | 麻豆免费在线播放 | 91最新视频在线观看 | 日本精品一区二区三区在线播放视频 | 精品在线二区 | 一级黄色视屏 | 成人av播放 | 国产精品国产三级国产aⅴ9色 | japanesexxx乱女另类 | 不卡av在线播放 | 在线免费观看视频一区 | 久久视频在线观看免费 | 国产又粗又猛又色又黄视频 | 蜜臀av一区二区 | 国产成人精品一区二区三区网站观看 | 久久久性 | 国产一级片一区二区三区 | 99久热在线精品视频 | 丁香电影小说免费视频观看 | 日韩1级片 | 中文字幕在线观看91 | 黄色在线免费观看网址 | 国产精品美女久久久久久久 | 国产成a人亚洲精v品在线观看 | 国产九色视频在线观看 | 狠狠干天天干 | 亚洲精品视频在线免费 | 日韩欧美大片免费观看 | av丝袜在线 | 久久久一本精品99久久精品 | 国产亚洲在线视频 | 最近中文字幕免费观看 | 涩av在线| 99re中文字幕 | 精品国产精品久久一区免费式 | 免费亚洲婷婷 | 男女拍拍免费视频 | 日韩免费电影网站 | 国产精品一区二区三区四区在线观看 | 91九色视频观看 | 国产91精品看黄网站 | 亚洲视频2 | 9热精品 | 91精品视频在线 | 一区二区在线不卡 | 超碰国产在线 | 久久精品视频在线观看免费 | 婷色在线 | 国内99视频 | 日日狠狠 | 中文字幕一区二 | 国产理论在线 | 免费av免费观看 | 手机av在线不卡 | 夜夜嗨av色一区二区不卡 | 国产视频久久 | 91亚洲国产成人 | 日韩免费av片 | 日日夜夜噜 | 免费在线黄网 | 亚洲一区久久 | 国产v亚洲v | 欧美日韩在线观看不卡 | 久久久在线免费观看 | 亚洲影院色 | 国产一级免费播放 | 涩涩网站在线观看 | 日韩av一区二区三区四区 | 亚洲精品国产精品国自产在线 | 99热这里是精品 | 在线观看视频免费大全 | 91色偷偷| 成人免费观看完整版电影 | 免费a视频 | 欧美日韩在线免费观看 | 久久免费a | 日韩激情影院 | 久久免费福利 | 日日草天天干 | 欧美日韩视频在线 | 成人综合婷婷国产精品久久免费 | 精品久久久久久久久久久久 | 亚洲无吗视频在线 | 韩日色视频 | 国产成人精品一区二区三区在线观看 | 亚洲精品小视频 | 国产成人99久久亚洲综合精品 | 久久精品a | 欧美大香线蕉线伊人久久 | 国产一级片视频 | 人人干人人做 | 丁香六月av| 久久精品一区二区三 | 在线影院中文字幕 | 欧美国产精品久久久久久免费 | 精品一区二区三区久久久 | 国产三级av在线 | 欧美日韩1区2区 | 久久综合中文字幕 | 99在线视频网站 | 国产最顶级的黄色片在线免费观看 | 美女久久久久 | 欧美激情第八页 | 亚洲免费小视频 | 狠狠色丁香婷婷综合视频 | 国产欧美日韩一区 | 五月婷婷丁香色 | 中文字幕a∨在线乱码免费看 | bayu135国产精品视频 | 91视频免费播放 | 久久99精品热在线观看 | 在线观看成人一级片 | 黄色av大片 | 中文字幕在线影院 | 亚洲精品综合在线观看 | 亚洲成人精品影院 | 中日韩欧美精彩视频 | 国产看片网站 | 99色视频在线 | 日韩免费小视频 | 亚洲高清视频在线观看 | 欧美日韩亚洲在线观看 | 2022国产精品视频 | 久久久久久久久久久免费视频 | 在线观看黄色大片 | 亚洲综合日韩在线 | 亚洲日本va午夜在线影院 | av在线观 | 日韩电影在线一区 | 久久国产精品成人免费浪潮 | 日韩在线视频网址 | www.av中文字幕.com | 久久9999久久免费精品国产 | 国产品久精国精产拍 | 中文字幕av专区 | 亚洲91av| 婷婷在线不卡 | 91男人影院| 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 五月天综合网站 | 国产1区在线观看 | 亚洲一级国产 | 国产亚洲婷婷免费 | 日韩一级电影在线 | 在线观看av大片 | 国内亚洲精品 | 亚洲人人网 | 欧美成人免费在线 | 中文字幕一二三区 | 亚洲精品乱码久久久久久蜜桃欧美 | 玖玖视频网 | 成人免费观看网站 | 六月久久婷婷 | 国产精品视频永久免费播放 | 久久久久亚洲国产 | 精品99在线视频 | 亚洲成人免费在线观看 | 狠狠色噜噜狠狠狠合久 | 日韩av在线看 | 蜜臀av麻豆 | 久久国产精品99国产精 | 久久激情小视频 | 97超碰在线免费 | 国产成人一区二区在线观看 | 91网免费看| 中文乱码视频在线观看 | 亚洲人人网 | 国产在线国偷精品产拍免费yy | 亚洲国产精品一区二区久久hs | 日韩免费av网址 | 国产精品免费看久久久8精臀av | 日日操日日操 | 欧美一二区视频 | 国产黄在线 | av免费网站 | 青青草国产成人99久久 | 日韩91在线 | 亚洲激情p | 久久久69| 国产a高清| 久久成年人网站 | 国产精品毛片久久蜜 | av午夜电影 | 91久久人澡人人添人人爽欧美 | 青青五月天 | 日本激情视频中文字幕 | 免费看黄在线网站 | 国产精品福利在线 | 96av在线| 草久热| 99久久精品免费看 | 精品国产大片 | 97成人精品视频在线观看 | 亚洲视频资源在线 | 精品久久久久久亚洲综合网站 | 国产在线理论片 | 日本精品视频免费观看 | 99久久综合狠狠综合久久 | 日韩精品一区二区三区免费视频观看 | 国产精品专区在线 | 亚洲国产日韩欧美在线 | 天天综合中文 | 又黄又爽的视频在线观看网站 | 欧美激情另类文学 | 天天色天天综合 | 欧美性性网 | 日韩日韩日韩日韩 | 午夜在线免费视频 | 日韩精品欧美专区 | 丁香久久激情 | 五月婷婷丁香 | 97香蕉久久超级碰碰高清版 | 一区二区三区四区五区在线 | 久久久久欠精品国产毛片国产毛生 | 美女性爽视频国产免费app | 国产一区二区三区视频在线 | 久久www免费人成看片高清 | 一区二区伦理 | 日韩精品资源 | 欧美精品久久久久久久久久白贞 | 久久精品79国产精品 | 亚洲精品综合一区二区 | 青草视频在线播放 | 国产成人333kkk | 91粉色视频 | 996久久国产精品线观看 | 欧美日韩一区二区免费在线观看 | 日韩av影视在线 | 免费毛片一区二区三区久久久 | 欧美性黑人 | 日韩精品一区二区三区水蜜桃 | 国产大片免费久久 | 91精品视频一区二区三区 | 激情深爱| 四虎最新入口 | 西西人体4444www高清视频 | 在线观看完整版 | 99精品国产99久久久久久97 | 人人爽人人爽人人片 | 91精品第一页 | 国产精品久久久久久a | 久久久午夜精品理论片中文字幕 | 成人av中文字幕在线观看 | 久久精品久久99精品久久 | 国产xxxxx在线观看 | 国产精品久久婷婷六月丁香 | 欧美专区国产专区 | 日韩在线观看视频一区二区三区 | 日韩一区二区三区高清在线观看 | 久久高清免费观看 | 国产精品激情在线观看 | 国产精品久久久一区二区 | 久久久久久久久久国产精品 | 香蕉久久久久 | 97电影在线看视频 | 国产成人精品久久久久 | 久久视频免费看 | 亚洲情影院 | 97涩涩视频 | 香蕉视频久久久 | 国产精品va最新国产精品视频 | 亚洲精品视频在 | 99久久精品久久久久久清纯 | av超碰免费在线 | av不卡免费在线观看 | 国产 日韩 欧美 中文 在线播放 | 日日操网站 | 日韩在线欧美在线 | 夜夜视频欧洲 | 色视频网站在线 | 射射射综合网 | 人人艹视频 | 久久爱影视i | 国产精品久久视频 | 国产成人精品一区二区三区福利 | 亚洲综合色视频在线观看 | av中文字幕亚洲 | 欧美不卡在线 | www.亚洲黄| 天天躁日日| 久久99久久99精品免费看小说 | 在线视频日韩一区 | av黄色一级片 | 久影院 | 亚洲综合欧美激情 | 亚洲午夜精品久久久久久久久久久久 | 欧美日韩国产在线一区 | 欧美a级在线免费观看 | 91视频麻豆视频 | 亚洲狠狠丁香婷婷综合久久久 | 色婷婷午夜 | 天天射天天搞 | 日本久久精品 | 久久精品96| 亚洲香蕉视频 | 激情久久久 | 欧美成a人片在线观看久 | 欧美日韩在线看 | 国产资源网 | 91精选 | 久久久亚洲成人 | 在线视频区 | 免费观看的av | 日韩一区二区三区不卡 | 欧美精品一区在线发布 | 久久综合色天天久久综合图片 | 日韩欧美视频一区二区三区 | 午夜黄色一级片 | 日韩精品中字 | 国产免费资源 | 亚洲无在线 | av日韩中文 | 麻豆视频免费在线观看 | 国产精品18久久久久久久 | 欧美激情综合五月色丁香小说 | 特级西西444www高清大视频 | 国产爽妇网| 国产伦理一区 | 久久国产精品免费观看 | 三级黄色片在线观看 | 黄色小说免费在线观看 | 国产一级二级三级视频 | 欧洲在线免费视频 | 99久久精品网 | 免费黄色网址大全 | 日日夜夜人人天天 | 日韩综合一区二区三区 | 中文伊人 | 人人澡人摸人人添学生av | 国产小视频你懂的在线 | 日韩三级一区 | 久久99精品视频 | 国产视频日本 | 草久久精品 | 国产精品网在线观看 | 欧美亚洲三级 | 高清av免费一区中文字幕 | 久久精品国亚洲 | 欧美日韩亚洲在线观看 | 国产精品麻豆三级一区视频 | 日日夜夜免费精品视频 | 91精品免费视频 | 激情视频91 | 中文字幕色在线视频 | 天天干天天操天天拍 | 日本久久久久久久久久 | 国产在线一区二区 | 18女毛片 | 久久免费视频观看 | 99av在线视频 | 欧美片一区二区三区 | 国产精品综合久久久久 | 日韩a在线播放 | 久久99精品国产麻豆婷婷 | 色狠狠综合天天综合综合 | 911精品美国片911久久久 | 91九色视频在线观看 | 色在线国产 | 99精品久久久久久久 | 伊人久久五月天 | 超碰免费成人 | 九九九热精品免费视频观看网站 | 福利视频导航网址 | 成全在线视频免费观看 | 香蕉视频亚洲 | 午夜18视频在线观看 | 久久五月天婷婷 | 久久伊人热 | 亚洲国产精品免费 | av在线一二三区 | 日韩在线电影一区 | 51精品国自产在线 | 天天搞天天干 | 国产人免费人成免费视频 | 久人人 | 在线观看国产日韩欧美 | 亚洲精品一区二区精华 | 精品国产精品一区二区夜夜嗨 | 国产精品女人久久久久久 | 91福利社在线观看 | 成年人精品 | 五月激情电影 | 国产成人精品国内自产拍免费看 | www.久久久com | 亚洲国产大片 | 中文理论片 | 伊人五月天 | 91成人在线观看喷潮 | 国产精品久久久久久久久久新婚 | 91精品视频在线观看免费 | 国产在线不卡视频 | 成全在线视频免费观看 | av国产网站 | 国产免费成人av | 香蕉免费在线 | 国产精品18久久久久久首页狼 | 久久久精品国产免费观看一区二区 | 在线不卡的av| 国产高清在线不卡 | 免费一级毛毛片 | 国产精品久久一 | 人人玩人人添人人澡97 | 久久免费视屏 | 久久情侣偷拍 | 色婷婷精品| 日韩在线观看免费 | 深夜福利视频在线观看 | 日韩a级免费视频 | 免费日韩av电影 | 中文字幕在线高清 | 午夜成人免费影院 | 国产第一页在线播放 | 在线观看免费黄视频 | 久艹在线观看视频 | 色综合中文字幕 | 中文字幕日韩精品有码视频 | 伊人婷婷在线 | 日韩一二区在线 | 亚洲资源视频 | 欧美片网站yy | 色综合久久88色综合天天人守婷 | 一区二区三区久久 | 亚洲午夜精品一区二区三区电影院 | 久久精品国产亚洲 | 日韩在线播放视频 | 天天插天天干 | 亚洲 综合 专区 | 在线观看中文av | 日韩激情精品 | 国产91精品一区二区麻豆亚洲 | 久久久久久久亚洲精品 | 午夜精品久久久 | 日韩电影久久久 | av无限看 | 精品伊人久久久 | 婷婷丁香激情综合 | 国产在线更新 | 中文字幕精品一区二区三区电影 | 成人 亚洲 欧美 | 97在线视频免费 | 97在线观看免费观看高清 | h视频在线看 | 日韩久久精品一区 | 欧亚日韩精品一区二区在线 | 摸阴视频| 国产午夜在线观看视频 | www视频在线免费观看 | 亚洲天天 | 新版资源中文在线观看 | 国产精品福利在线播放 | 国产精品久久久久久一区二区 | 国产96在线| 国产精品久久 | 久久久国产99久久国产一 | 中文字幕在线专区 | 天天天天天天干 | 国产黄色精品在线 | 一二三精品视频 | 在线观看第一页 | 国产黄色电影 | 亚洲v欧美v国产v在线观看 | 天堂网中文在线 | 国产精品美女www爽爽爽视频 | 亚洲精品国产品国语在线 | 久久成年人 | 日韩在观看线 | 久久综合中文字幕 | 日精品| 国产欧美精品在线观看 | 精品一区二区久久久久久久网站 | 中文在线a在线 | 一级片黄色片网站 | 99久久久久久 | 91桃色免费观看 | 欧美另类视频 | 一区三区视频 | 91久久精品日日躁夜夜躁国产 | 日韩有码第一页 | 国产高清视频免费最新在线 | 国产成人精品电影久久久 | 特黄特黄的视频 | 国际精品久久久久 | 婷婷亚洲激情 | 国产一区视频免费在线观看 | 亚洲精品999 | 五月天亚洲激情 | 久久夜色精品国产欧美乱 | 狠色狠色综合久久 | 国产特级毛片 | 久久一区二区三区超碰国产精品 | 成人久久免费视频 | 在线视频观看亚洲 | 亚洲三级黄 | www日韩欧美 | 成人国产精品免费 | 亚洲免费不卡 | 国产精品麻豆99久久久久久 | 狠狠gao| 在线观看深夜视频 | 国产婷婷在线观看 | 综合在线观看色 | 中文av在线播放 | 中文字幕色在线视频 | 国产福利一区二区在线 | 日韩欧美xxxx | 国内精品久久久久久久久久久久 | 国产精品av免费在线观看 | 国产香蕉久久精品综合网 | 99亚洲精品视频 | 国产.精品.日韩.另类.中文.在线.播放 | 国产精品96久久久久久吹潮 | 亚州精品天堂中文字幕 | 91传媒91久久久 | 天天伊人网 | 最新91在线视频 | 免费网站看v片在线a | 久久麻豆精品 | 国产 一区二区三区 在线 | 亚洲资源网 | 精品视频免费久久久看 | 久久久久久久久久久高潮一区二区 | 91久久久久久久一区二区 | 91麻豆国产福利在线观看 | 天天色天天骑天天射 | 久色 网 | 国产又黄又硬又爽 | 中文字幕av在线电影 | 亚洲精品一区二区18漫画 | 制服丝袜一区二区 | 久久乐九色婷婷综合色狠狠182 | 日韩欧美99 | 久久不见久久见免费影院 | 亚洲精品国产日韩 | 亚洲欧美国产精品18p |