[Windows Phone] 开发宜兰县政府数据开放平台应用程序 (2) 将下载的 CSV 数据保存到 Isolated Storage 提供下次进入应用程序时载入

在先前的文章 透过 Google Drive 放置宜兰县政府数据开放平台 CSV 文件进行读取 从 Google Drive 下载 CSV 数据,分析后显示在画面中。但每次都从网络下载 CSV 文件,会导致应用程序执行时,需要有一段下载数据的时间,才能载入数据,因此本文提供作法,将下载后的 CSV 文件保存到 Isolated Storage 中,当 Isolated Storage 存在 CSV 文件时,则读取该数据,如果没有的话,才从网络下载 CSV 文件。


前言

在先前的文章 透过 Google Drive 放置宜兰县政府数据开放平台 CSV 文件进行读取 从 Google Drive 下载 CSV 数据,分析后显示在画面中。但每次都从网络下载 CSV 文件,会导致应用程序执行时,需要有一段下载数据的时间,才能载入数据,因此本文提供作法,将下载后的 CSV 文件保存到 Isolated Storage 中,当 Isolated Storage 存在 CSV 文件时,则读取该数据,如果没有的话,才从网络下载 CSV 文件。

实践

请先下载先前文章 透过 Google Drive 放置宜兰县政府数据开放平台 CSV 文件进行读取 的范例,我们先撰写两个方法来读取和保存 CSV 文件。

读取

        /// 
        /// 从 Isolated Storage 读取 CSV 文件数据
        /// 
        /// CSV 文件名称
        /// 文件内容字符串
        private string ReadCsvFormIsolated(string isoStorageFileName)
        {
            string strCsvData = string.Empty;
            using (IsolatedStorageFile isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (isolatedStorageFile.FileExists(isoStorageFileName))
                {
                    IsolatedStorageFileStream fileStream = isolatedStorageFile.OpenFile(isoStorageFileName, FileMode.Open, FileAccess.Read);
                    using (StreamReader streamReader = new StreamReader(fileStream))
                    {
                        strCsvData = streamReader.ReadToEnd();
                    }
                }
            }
            return strCsvData;
        }

保存

        /// 
        /// 保存 CSV 数据到 Isolated Storage
        /// 
        /// CSV 文件名称
        /// CSV 字符串内容
        private void SaveCsvToIsolatedStorage(string isoStorageFileName, string strCsv)
        {
            using (IsolatedStorageFile isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (isolatedStorageFile.FileExists(isoStorageFileName))
                {
                    isolatedStorageFile.DeleteFile(isoStorageFileName);
                }
                using (var stream = isolatedStorageFile.CreateFile(isoStorageFileName))
                {
                    using (StreamWriter streamWriter = new StreamWriter(stream))
                    {
                        streamWriter.WriteLine(strCsv);
                    }
                }
            }
        }

在 GetHttpDocumentCallback() 方法中,将处理 CSV 字符串的部分的程序选取,按鼠标右键,选择 [重构] / [撷取方法],撷取方法为名称 ProcessCsvStream 的方法,将处理 CSV 数据的部分选起来。

image

新方法名称为 ProcessCsvData,按 [确定]。

SNAGHTML252e304[7]

ProcessCsvData 方法的程序:

        /// 
        /// 处理 CSV 字符串
        /// 
        /// CSV 字符串内容
        private void ProcessCsvData(string strCsvData)
        {
            using (TextReader textReader = new StringReader(strCsvData))
            {
                using (var reader = new CsvReader(textReader))
                {
                    reader.ReadHeaderRecord();

                    while (reader.HasMoreRecords)
                    {
                        var record = reader.ReadDataRecord();
                        Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            this.Items.Add(new ItemViewModel()
                            {
                                LineOne = record.GetValueOrNull("中文名称"),
                                LineTwo = record.GetValueOrNull("联络电话"),
                                LineThree = record.GetValueOrNull("民宿中文地址")
                            });
                        }));
                    }
                }
            }
        }

在 GetHttpDocumentCallback() 方法中,加入先前撰写的方法 SaveCsvToIsolatedStorage 做 [将下载后的 CSV 文件保存到 Isolated Storage 中]。最后 GetHttpDocumentCallback 的程序:

        /// 
        /// 异步网络资源要求与下载
        /// 
        /// 
        private void GetHttpDocumentCallback(IAsyncResult iAsyncResult)
        {
            HttpWebRequest httpWebRequest = (HttpWebRequest)iAsyncResult.AsyncState;
            HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.EndGetResponse(iAsyncResult);
            using (StreamReader responseStream = new StreamReader(httpWebResponse.GetResponseStream()))
            {
                string strCsvData = responseStream.ReadToEnd();
                if (string.IsNullOrEmpty(strCsvData))
                {
                    return;
                }

                // 处理 CSV 字符串数据
                ProcessCsvData(strCsvData);

                // 保存 CSV 数据到 Isolated Storage
                SaveCsvToIsolatedStorage("HomeStay.csv", strCsvData);
            }
        }

接着我们在 Load 方法,撰写逻辑 [当 Isolated Storage 存在 CSV 文件时,则读取该数据,如果没有的话,才从网络下载 CSV 文件。]。

        /// 
        /// 建立并加入一些 ItemViewModel 对象到 Items 集合。
        /// 
        public void LoadData()
        {
            // 当 Isolated Storage 存在 CSV 文件,则读取该数据
            string strCsvData = ReadCsvFormIsolated("HomeStay.csv");
            if (string.IsNullOrEmpty(strCsvData) == false)
            {
                // 处理 CSV 数据
                ProcessCsvData(strCsvData);
            }
            else  // 如果没有的话,才从网络下载 CSV 文件
            {
                HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("https://docs.google.com/uc?export=download&id=0B34Keu0W_LIJODdEYUhVSDZIS28");
                httpWebRequest.BeginGetResponse(new AsyncCallback(GetHttpDocumentCallback), httpWebRequest);
            }         

            this.IsDataLoaded = true;
        }

执行程序,透过以下影片录制模拟器运行应用程序时的过程,第一次时由于 Isolated Storage 不存在文件,因此会从网络下载 CSV 文件进行分析与显示数据,显示数据时间很慢。当离开应用程序并且再次执行应用程序时,由于先前已经下载过数据并且保存到 Isolated Storage 中,直接读取其中的内容,因此速度会快很多。


将下载的 CSV 数据保存到 Isolated Storage 提供下次进入应用程序时载入

范例下载

HomeStayApp.zip

课后作业

加入一个 Applcation Bar 按钮,功能是让使用者点选后,从网络下载 CSV 进行解析并且更新画面数据,并且保存文件至 Isolated Storage 中。