wxWidgest流操作(一)wxFileInputStream与wxFileOutputStream

还是保持一贯简单的用户界面,一个菜单条File->&Open和E&xit,&Help->&About,一个满屏的wxTextCtrl(把它拖到frame上的默认效果就是四向自动伸缩),勾选wxTE_PROCESS_ENTER和wxTE_MULTILINE。为了测试wxFileInputStream 和wxFileOutputStream流对中文读写的支持(要处理的文件即为本程序的源文件),特意为菜单项Open 和Exit 提供了中文提示(当鼠标指向这两个菜单项时,状态栏上会出现该提示)。

wxFileInputStream和wxFileOutputStream 头文件为<wx/wfstream.h>,其实使用是非常简单的。

构造一下input或output流只需将参数为wxString的文件名传递给要创建的流即可。

wxString filename(wxT("streamMain.cpp"));//输入文件名,此例为本程序源文件名
wxString dummyfile(wxT("dummy.cpp"));//输出文件名

wxFileInputStream inStream(filename);
wxFileOutputStream outStream(dummyfile);

确定输入流的长度用

int byteCount=inStream.GetLength();

从输入流读取数据前先要建一个临时存储缓存buffer,先设置该缓存大小为512 byte.

static unsigned char buffer[512];

也就是说,不管文件多大,每次最多读取512个字节。

size_t bytesToRead=wxMin((size_t)sizeof(buffer),byteCount);
...
byteCount-=bytesToRead;

bytesToRead是说每次实际读取了多少字节。这是怎么说呢。当文件没有512字节大时,当然不是每次读取512个字节,而是有多少读多少;同样适用于经过多次读取后,剩余未读取的文件已不足512字节了,那么这时就剩多少读多少了。

输入流wxFileInputStream读取数据的一个方法是wxFileInputStream.Read(void* buffer,size_t count),用GetLastError()来捕获错误。如果读取顺利,GetLastError()返回wxSTREAM_NO_ERROR.

我们试着将源文件streamMain.cpp的内容每次读取512个字节读到wxTextCtrl (text1) 及输出流输出新文件dummy.cpp. 合起来整个读取操作就是:

void StreamAppFrame::OnStreamClick(wxCommandEvent& event)
{
    wxString filename(wxT("streamMain.cpp"));
    wxString dummyfile(wxT("dummy.cpp"));

    wxFileInputStream inStream(filename);
    wxFileOutputStream outStream(dummyfile);


    int byteCount=inStream.GetLength();
    static char buffer[512];
    wxString content;

    while(byteCount>0)
    {

        size_t bytesToRead=wxMin((size_t)sizeof(buffer),byteCount);

        if(inStream.Read((void*)buffer,bytesToRead).GetLastError()==wxSTREAM_NO_ERROR)
        {
            if(outStream.Write((void*)buffer,bytesToRead).GetLastError()==wxSTREAM_NO_ERROR)
            {
                content=wxString::FromUTF8(buffer,bytesToRead);

                byteCount-=bytesToRead;
            }

            *text1<<content;
            wxLogStatus(wxT("Copy file successfully."));
        }
        else
        {
            wxLogStatus(wxT("Failed to copy file."));
        }
    }


    *text1<<wxT("\n文件读取成功!\n");
}

wxLogStatus(const char* formatString,...)是一个可以向状态栏传递消息的实用函数,使用起来也很方便,而且本身就支持格式化处理。

看到上图中状态栏提示文件已拷贝成功,你可以在工程根目录下找到一个名这dummy.cpp的文件,打开看看,它与源文件text1(wxTextCtrl)的内容有一点点不同哦,不用对比只通过仔细阅读源码看看能不能发现。

     需要注意的是读取流写入text1中时所用的字符串转换函数wxString::FromUTF8(const char* buffer,size_t len),它的作用是将以UTF8字符集保存的源文件(streamMain.cpp)的内容转化成Unicode编码的wxString。如果你用了其它的转换函数,可能text1的输出会出现各种各样的问题。边摸索边学习边进步,是吧^_^

    如果你的系统很牛,或者你只是想看看缓冲区设置的尽量大一些会有什么不同,比如把缓冲区设置为static char buffer[1024*1024*1024],因为你的文件很有可能没有1G这么大,所以不同的只是while循环其实只执行了一次就搞定。这样设置缓冲式来玩玩还可以,但使用流本身的一个目的就是节省资源,这个可不要忘了。

    前面提到使用wxFileInputStream流来读取文本文件有可能遇到的一个问题是多字节字符编码的字符可能乱码,也可能部分丢失(不信你可以用wxString类的另外一些与系统C字符转化的几个函数来试试,比如wxString(const char*,size_t len),或者直接*text1<<buffer试试)。对于文本文件,其实另一个流会更适合一些,wxTextInputStream和wxTextOutputStream.

    这部份就不上传源码了,只要用Code::Blocks内置的wxSmith新建一个窗体,照着一开始所描述的界面布局即可,至于测试文件,随便找一个有中文字符的文本文件放在工程根目录下,将上面的代码中wxString filename(wxT("streamMain.cpp")) 的内容换成你自己想要测试的文本文件即可。

posted @ 2011-04-22 18:08  高斯山  阅读(1681)  评论(0编辑  收藏  举报