<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 14.2 流操作相關類 所謂流模型,指的是一種用于提供相對于文件讀寫更高層的數據讀寫的模型.使用流模型,你的代碼不需要關心當前操作的是文件,內存還是socket(參考第 18章,"使用wxSocket編程",其中演示了用流方式使用socket的方法).某些wxWidgets標準類同時支持文件讀寫操作和流讀寫操作, 比如wxImage類. wxStreamBase類是所有流類的基類,它聲明的函數包括類似OnSysRead和OnSysWrite等需要繼承類實現的函數.其子類wxInputStream和wxOutputStream則提供了更具體的流類(比如wxFileInputStream和 wxFileOutputStream子類)共同需要的用于讀寫操作的基本函數.讓我們來具體來看一下wxWidgets提供的各種流操作相關類. 文件流 wxFileInputStream和wxFileOutputStream是基于wxFile類實現的,可以通過文件名,wxFile 對象或者整數文件描述符的方式來進行初始化.下面的例子演示了使用wxFileInputStream來進行文件讀取,文件指針移位并讀取當前位置數據等. ``` #include "wx/wfstream.h" // 構造函數初始化流緩沖區并且打開文件名參數對應的文件. // wxFileInputStream將在析構函數中自動關閉對應的文件描述符. wxFileInputStream inStream(filename); // 讀100個字節 int byteCount = 100; char data[100]; if (inStream.Read((void*) data, byteCount). LastError() != wxSTREAM_NOERROR) { // 發生了異常 // 異常列表請參考wxStreamBase的相關文檔. } // 你可以通過下面的方法判斷到底成功讀取了多少個字節. size_t reallyRead = inStream.LastRead(); // 將文件游標移動到文件開始處. // SeekI函數的返回值為移動游標以前的游標相對于文件起始處的位置 off_t oldPosition = inStream.SeekI(0, wxFromBeginning); // 獲得當前的文件游標位置 off_t position = inStream.TellI(); ``` 使用wxFileOutputStream的方法也很直觀.下面的代碼演示了使用wxFileInputStream和wxFileOutputStream實現文件拷貝的方法.每次拷貝1024個字節.為了使代碼更簡介,這里沒有顯示錯誤處理的代碼. ``` // 下面的代碼實現固定單位大小的流拷貝. // 緩沖區的使用是為了加快拷貝的速度. void BufferedCopy(wxInputStream& inStream, wxOutputStream& outStream, size_t size) { static unsigned char buf[1024]; size_t bytesLeft = size; while (bytesLeft &gt; 0) { size_t bytesToRead = wxMin((size_t) sizeof(buf), bytesLeft); inStream.Read((void*) buf, bytesToRead); outStream.Write((void*) buf, bytesToRead); bytesLeft -= bytesToRead; } } void CopyFile(const wxString& from, const wxString& to) { wxFileInputStream inStream(from); wxFileOutputStream outStream(to); BufferedCopy(inStream, outStream, inStream.GetSize()); } ``` wxFFileInputStream和wxFFileOutputStream跟wxFileInputStream和 wxFileOutputStream的用法幾乎完全一樣, 不同之處在于前者是基于wxFFile類而不是wxFile類的. 因此它們的初始化方法也不同,相應的,前者可以使用FILE指針或wxFFile對象來初始化.文件結束處理相應的有所不同: wxFileInputStream在最后一個字節被讀取的時候報告wxSTREAM_EOF, 而wxFFileInputStream則在最后一個字節以后進行讀操作的時候返回wxSTREAM_EOF. 內存和字符串流 wxMemoryInputStream和wxMemoryOutputStream使用內部緩沖區來處理流數據.默認的構造函數都采用 char*類型的緩沖區指針和緩沖區大小作為參數.如果沒有這些參數,則表明要求該類的事例自己進行動態緩沖區管理.我們很快會看到一個相關的例子. wxStringInputStream則采用一個wxString引用作為構造參數來進行數據讀取. wxStringOutputStream采用一個開選的wxString指針作為參數來進行數據寫操作;如果構造參數沒有指示wxString指針,則將構造一個內部的wxString對象,這個對象可以通過GetString函數來訪問. 讀寫數據類型 到目前為止,我們描述的流類型都處理的是原始的字節流數據.在實際的應用程序中,這些字節流必須被賦予特定的函數.為了幫助你實現這一點,你可以使用下面四個類來以一個更高的層級處理數據.這四個類分別是:wxTextInputStream, wxTextOutputStream, wxDataInputStream和wxDataOutputStream.這些類通過別的流類型類構造,它們提供了操作更高級的C++數據類型的方法. wxTextInputStream從一段人類可讀的文本中獲取數據.如果你使用的構造類為文件相關類,你需要自己進行文件是否讀完的判斷.即使這樣,讀到空數據項(長度為0的字符串或者數字0)還是無法避免,因為很多文本文件都用空白符(比如換行符)來結束.下面的例子演示了怎樣使用由wxFileInputStream構造的wxTextInputStream: ``` wxFileInputStream input( wxT("mytext.txt") ); wxTextInputStream text( input ); wxUint8 i1; float f2; wxString line; text &gt;&gt; i1; // 讀一個8bit整數. text &gt;&gt; i1 &gt;&gt; f2; // 先讀一個8bit整數再讀一個浮點數. text &gt;&gt; line; // 讀一行文本 ``` wxTextOutputStream則將文本數據寫至輸出流,換行符自動使用當前平臺的換行符.下面的例子演示了將文本數據輸出到標準錯誤輸出流: ``` #include "wx/wfstream.h" #include "wx/txtstrm.h" wxFFileOutputStream output( stderr ); wxTextOutputStream cout( output ); cout &lt;&lt; wxT("This is a text line") &lt;&lt; endl; cout &lt;&lt; 1234; cout &lt;&lt; 1.23456; ``` wxDataInputStream和wxDataOutputStream使用發放類似,但是它使用二進制的方法處理數據.數據使用可移植的方式存儲因此能夠作到平臺無關.下面的例子分別演示了以這種方式從數據文件讀取以及寫入數據文件. ``` #include "wx/wfstream.h" #include "wx/datstrm.h" wxFileInputStream input( wxT("mytext.dat") ); wxDataInputStream store( input ); wxUint8 i1; float f2; wxString line; store &gt;&gt; i1; // 讀取一個8bit整數 store &gt;&gt; i1 &gt;&gt; f2; // 讀取一個8bit整數,然后讀取一個浮點數. store &gt;&gt; line; // 讀取一行文本 #include "wx/wfstream.h" #include "wx/datstrm.h" wxFileOutputStream output(wxT("mytext.dat") ); wxDataOutputStream store( output ); store &lt;&lt; 2 &lt;&lt; 8 &lt;&lt; 1.2; store &lt;&lt; wxT("This is a text line") ; ``` Socket流 wxSocketOutputStream和wxSocketInputStream是通過wxSocket對象構造的,詳情參見第18章. 過濾器流對象 wxFilterInputStream和wxFilterOutputStream是過濾器流對象的基類,過濾器流對象是一種特殊的流對象,它用來將過濾后的數據輸入到其它的流對象.wxZlibInputStream是一個典型的過濾器流對象.如果你在其構造函數中指定一個文件源為一個zlib格式的壓縮文件的文件流對象,你可以直接從wxZlibInputStream中讀取數據而不需要關心解壓縮的機制.類似的,你可以使用一個 wxFileOutputStream來構造一個wxZlibOutputStream對象,如果你將數據寫入wxZlibOutputStream對象,壓縮后的數據將被寫入對應的文件中. 下面的例子演示了怎樣將一段文本壓縮以后存放入另外一個緩沖區中: ``` #include "wx/mstream.h" #include "wx/zstream.h" const char* buf = "01234567890123456789012345678901234567890123456789"; // 創建一個寫入wxMemoryOutputStream對象的wxZlibOutputStream類 wxMemoryOutputStream memStreamOut; wxZlibOutputStream zStreamOut(memStreamOut); // 壓縮buf以后寫入wxMemoryOutputStream zStreamOut.Write(buf, strlen(buf)); // 獲取寫入的大小 int sz = memStreamOut.GetSize(); // 分配合適大小的緩沖區 // 拷貝數據 unsigned char* data = new unsigned char[sz]; memStreamOut.CopyTo(data, sz); ``` Zip流對象 wxZipInputStream是一個更復雜一點的流對象,因為它是以文檔的方式而不是線性的二進制數據的方式工作的.事實上,文檔是通過另外的類wxArchiveClassFactory和wxArchiveEntry來處理的,但是你可以不用關心這些細節.要使用 wxZipInputStream類,你可以有兩種構造方法,一種是直接使用一個指向zip文件的文件流對象,另外一種方法則是通過一個zip文件路徑和一個zip文件中文檔的路徑來指定一個zip數據流.下面的例子演示了這兩種方法: ``` #include "wx/wfstream.h" #include "wx/zipstrm.h" #include "wx/txtstrm.h" // 方法一: 以兩步方式創建zip輸入流. wxZipEntry* entry; wxFFileInputStream in(wxT("test.zip")); wxZipInputStream zip(in); wxTextInputStream txt(zip); wxString data; while (entry = zip.GetNextEntry()) { wxString name = entry->GetName(); // 訪問元數據 txt &gt;&gt; data; // 訪問數據 delete entry; } // 方法二: 直接指定源文檔路徑和內部文件路徑. wxZipInputStream in(wxT("test.zip"), wxT("text.txt")); wxTextInputStream txt(zip); wxString data; txt &gt;&gt; data; // 訪問數據 ``` wxZipOutputStream用來寫zip壓縮文件. PutNextEntry或PutNextDirEntry函數用來在壓縮文件中創建一個新的文件(目錄),然后就可以寫相應的數據了.例如: ``` #include "wx/wfstream.h" #include "wx/zipstrm.h" #include "wx/txtstrm.h" wxFFileOutputStream out(wxT("test.zip")); wxZipOutputStream zip(out); wxTextOutputStream txt(zip); zip.PutNextEntry(wxT("entry1.txt")); txt &lt;&lt; wxT("Some text for entry1\n"); zip.PutNextEntry(wxT("entry2.txt")); txt &lt;&lt; wxT("Some text for entry2\n"); ``` 虛擬文件系統 wxWidgets提供了一套虛擬文件系統機制,讓你的應用程序可以象使用普通文件那樣使用包括zip文件中的文件,內存文件以及HTTP或FTP協議這樣的特殊數據.不過,這種虛擬文件機制通常是只讀的,意味著你不可以修改其中的內容.wxWidgets提供的wxHtmlWindow類(用于提供 wxWidgets內部的HTML幫助文件的顯示)和wxWidgets的XRC資源文件機制都可以識別虛擬文件系統路徑格式.虛擬文件系統的使用比起前面介紹的zip文件流要簡單,但是后者可以更改zip文檔的內容.除了內部都使用了流機制以外,這兩者其實沒有任何其它的聯系. 各種不同的虛擬文件系統類都繼承自wxFileSystemHandler類,要在應用程序中使用某個特定實現,需要在程序的某個地方 (通常是OnInit函數中)調用wxFileSystem::AddHandler函數.使用虛擬文件系統通常只需要使用那些定義在 wxFileSystem對象中的函數,但是有些虛擬文件系統的實現也提供了直接給用于使用的函數,比如wxMemoryFSHandler's的 AddFile和RemoveFile函數. 在我們介紹怎樣通過C++函數訪問虛擬文件系統之前,我們先看看怎樣在wxWidgets提供的其它子系統中使用虛擬文件系統.下面的例子演示了怎樣在用于在wxHtmlWindow中顯示的HTML文件中使用指定虛擬文件系統中的路徑: ``` <img src="file:myapp.bin#zip:images/logo.png"> ``` "#"號前面的部分是文件名,后面的部分則是虛擬文件系統類型以及文件在虛擬文件系統中的路徑. 類似的,我們也可以在XRC資源文件中使用虛擬文件系統: ``` <object class="wxBitmapButton"> <bitmap>file:myapp.bin#zip:images/fuzzy.gif</bitmap> </object> ``` 在上面的這些用法中,操作虛擬文件系統的代碼被隱藏在wxHtmlWindow和XRC系統的實現中.如果你希望直接使用虛擬文件系統, 通常你需要通過wxFileSystem和wxFSFile類.下面的代碼演示了怎樣從虛擬文件系統中加載一幅圖片,當應用程序初始化的時候,增加一個 wxZipFSHandler類型的虛擬文件系統處理器.然后創建一個wxFileSystem的實例,這個實例可以是臨時使用也可以存在于整個應用程序的生命周期,這個實例用來從zip文件myapp.bin中獲取logo.png圖片.wxFSFile對象用于返回這個文件對應的數據流,然后通過流的方式創建wxImage對象.在這個對象被轉換成wxBitmap格式以后,wxFSFile和wxFileSystem對象就可以被釋放了. ``` #include "wx/fs_zip.h" #include "wx/filesys.h" #include "wx/wfstream.h" // 這一行代碼只應該被執行依次,最好是在應用程序初始化的時候 wxFileSystem::AddHandler(new wxZipFSHandler); wxFileSystem* fileSystem = new wxFileSystem; wxString archive = wxT("file:///c:/myapp/myapp.bin"); wxString filename = wxT("images/logo.png"); wxFSFile* file = fileSystem->OpenFile( archive + wxString(wxT("#zip:")) + filename); if (file) { wxInputStream* stream = file->GetStream(); wxImage image(* stream, bitmapType); wxBitmap bitmap = wxBitmap(image); delete file; } delete fileSystem; ``` 注意要使用wxFileSystem:: OpenFile函數,其參數必須是一個URL而不能是一個絕對路徑,其格式應該為"file:/&lt;主機名&gt;//&lt;文件名&gt;", 如果主機名為空,則使用三個"/"符號.你可以使用wxFileSystem::FileNameToURL函數獲取某個文件對應的URL,也可以用 wxFileSystem::URLToFileName函數將某個URL轉換成對應的文件名. 下面的例子演示了怎樣獲取虛擬文件系統中獲取一個文本文件的內容,并將其存放在某個wxString對象中,所需參數為zip文件路徑以及zip文件中的虛擬文件的路徑: ``` // 從zip文件中加載一個文本文件 bool LoadTextResource(wxString& text, const wxString& archive, const wxString& filename) { wxString archiveURL(wxFileSystem::FileNameToURL(archive)); wxFileSystem* fileSystem = new wxFileSystem; wxFSFile* file = fileSystem->OpenFile( archiveURL + wxString(wxT("#zip:")) + filename); if (file) { wxInputStream* stream = file->GetStream(); size_t sz = stream->GetSize(); char* buf = new char[sz + 1]; stream->Read((void*) buf, sz); buf[sz] = 0; text = wxString::FromAscii(buf); delete[] buf; delete file; delete fileSystem; return true; } else return false; } ``` wxMemoryFSHandler允許你將數據保存在內存中并且通過內存協議在虛擬文件系統中使用它.顯然在內存中存放大量數據并不是一個值得推薦的作法,不過有時候卻可以給應用程序提供一定程序的靈活性,比如你正在使用只讀的文件系統或者說使用磁盤文件存在性能上的問題的時候.在 DialogBlocks軟件中,如果用戶提供的自定義圖標文件還不具備,DialogBlocks仍然可以通過下面的XRC文件顯示一個內存中的圖片, 這個圖片并不存在于任何的物理磁盤中. ``` <object class="wxBitmapButton"> <bitmap&gt;memory:default.png</bitmap> </object> ``` wxMemoryFSHandler的AddFile函數可以使用的參數包括一個虛擬文件名和一個wxImage, wxBitmap, wxString或void*數據. 如果你不再使用某個內存虛擬文件了,可以通過RemoveFile函數將其刪除.如下所示: ``` #include "wx/fs_mem.h" #include "wx/filesys.h" #include "wx/wfstream.h" #include "csquery.xpm" wxFileSystem::AddHandler(new wxMemoryFSHandler); wxBitmap bitmap(csquery_xpm); wxMemoryFSHandler::AddFile(wxT("csquery.xpm"), bitmap, wxBITMAP_TYPE_XPM); ... wxMemoryFSHandler::RemoveFile(wxT("csquery.xpm")); ``` wxWidgets支持的第三種虛擬文件系統是wxInternetFSHandler,它支持FTP和HTTP協議.
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看