2011年4月7日 星期四

C# .Net 與 Google Map 靜態地圖擷取

string strResult = "fail";
FileStream fileStream = null;
//設定圖片長寛
int mapWidth = Convert.ToInt16(System.Configuration.ConfigurationManager.AppSettings["MapImageWidth"]);
int mapHeight = Convert.ToInt16(System.Configuration.ConfigurationManager.AppSettings["MapImageHeight"]);
//設定GoogleMapKey
string apikey = System.Configuration.ConfigurationManager.AppSettings["GoogleMapKey"].ToString();
string url = "http://maps.google.com.tw/staticmap?center=" + Latitude + "," + Longitude + "&zoom=16&size=" + mapWidth.ToString() + "x" + mapHeight.ToString() + "&maptype=roadmap&markers=" + Latitude + "," + Longitude + "&key=" + apikey + "&sensor=false";
WebRequest myrequest = WebRequest.Create(url);
WebResponse mywebresponse = myrequest.GetResponse();
//讀取地圖靜態圖片資料
Stream mystream = mywebresponse.GetResponseStream();

string gifFile = string.Format("{0}\\{1}\\{2}\\Map.gif", System.Configuration.ConfigurationManager.AppSettings["ImagesFolder"], StoreID, ObjectID);

if (!System.IO.File.Exists(gifFile))
{
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(gifFile));
}

fileStream = File.Create(gifFile);
byte[] buffer = new byte[102400];
int bytesRead;
while (true)
{
//開始將資料流寫入到disk
bytesRead = mystream.Read(buffer, 0, buffer.Length);
if (bytesRead == 0)
break;
fileStream.Write(buffer, 0, bytesRead);
strResult = "OK";
}

C# .Net 與 Google Map 地址定位取回經緯度

//設定 GoogleMapKey
string apikey = System.Configuration.ConfigurationManager.AppSettings["GoogleMapKey"].ToString();
string url = "http://maps.google.com.tw/maps/geo?q=" + Address + "&output=xml&key=" + apikey + "&sensor=false";
WebRequest myrequest = WebRequest.Create(url);

System.Net.WebResponse mywebresponse = myrequest.GetResponse();
Stream mystream = mywebresponse.GetResponseStream();
//讀取定位結果資料
StreamReader sr = new System.IO.StreamReader(mystream, System.Text.Encoding.UTF8);
string XmlText = sr.ReadToEnd();
int index1 = XmlText.IndexOf("coordinates");
int index2 = XmlText.IndexOf("</coordinates>");
string Point = XmlText.Substring(index1 + 12, index2 - index1 - 12);
//解析出 Longitude
Longitude = Point.Substring(0, Point.IndexOf(","));
//解析出 Latitude
Latitude = Point.Substring(Point.IndexOf(",") + 1, Point.LastIndexOf(",") - Point.IndexOf(",") - 1);

using (SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["RMSDBConnection"].ToString()))
{
con.Open();
//更新Map_X , Map_Y
using (SqlCommand commandU = new SqlCommand("Update Object Set Map_X = @Map_X, Map_Y = @Map_Y where ObjectID = @ObjectID", con))
{
commandU.Parameters.Add(new SqlParameter("Map_X", Longitude));
commandU.Parameters.Add(new SqlParameter("Map_Y", Latitude));
commandU.Parameters.Add(new SqlParameter("ObjectID", ObjectID));
commandU.ExecuteNonQuery();
}
con.Close();
}

臺灣六法全書 iPhone 程式上架囉


臺灣六法全書 iPhone 程式 / 檔案很大, 37mb , 請耐心下載
支援 iOS 4.0以上, 但iPhone 3G實測因資料量太大有記憶體不足而無法開啟問題,
iPhone 3Gs/ iPhone 4 / iPad / iPad2 / iPod touch 4 以上均實測無問題
2011/4/15前免費下載http://itunes.apple.com/us/app/id425669996
中華民國六法全書,臺灣六法全書,中華民國法規資料
Laws & Regulations Data of The Republic of China
整理完整離線版中華民國法規資料查詢 且含部分英文法規
目前整理最完整的中華民國法規資料
將提供不定期更新法規資料

[敬請期待新功能:法規查詢,書韱功能,大法官解釋文 與iPad HD版推出]

廢除的條款也查得到喔




英文版的民法耶 >o<


首席室內設計iPhone程式上架囉

幫朋友做的iPhone程式

有iPhone的朋友們可以下載玩玩看

http://itunes.apple.com/us/app/id425665406

點選"我的位置" 會開啟雷達指引功能喔 (Augmented Reality + Location base service)










2011年2月7日 星期一

Objective-C 字串append與記憶體管理的奧義

首先要說明一下NSString與 NSMutableString
在Objective-C中 NSString是一種不可變更的字串物件,而且是以unicode編碼的字串與一般C/C++中的 Char* 字元陣列所組成的字串不同. 最大的不同點在於每一個字所使用的byte數 ; 而NSMutableString就是一種可變更的字串物件. 說到這一定一堆人會提出很多的程式語法說明NSStrig是可變更的物件,如:
NSString *str = @"string 1";
str = [str StringByAppendingString:@":string 2"];
//此時str內容即為 @"string 1:string2"

是的以上語法沒有錯, str內容也確實為二個字串的合併. 對於Objective-C的記憶體管理還沒有深入瞭解的人們地確會認為“NSString怎麼會是不可變更的字串物件呢?” ,這個問題對於筆者來說也一樣的有過問號,但是查遍了相關的書籍,問過無數次google大神.始終沒有得到一個很好的答案.

就在我不想理會這個問題,而在設計”iPhone 六法全書“之時出現一個相當怪的麻煩:民法有1225條款而使用StringByAppendingString 太多次會(約100次)在Device 中當掉,但在模擬器中確不會有這個問題.
這下可好,這種模擬器與實機測試的結果不同相當難處理,問過google大神後,得知也有人遇到此問題但是沒人解答出來,我只好摸著頭進行Device Debug . 結果是在相當程度的loop使用StringByAppendingString後,原本的字串會突然變為“nil”. 接下來就完全不知如何解決哩.

此時我在想會不會是iPhone SDK目前的bug,於是我換一個function試試看,我改用"stringByAppendingFormat",這個function比“ StringByAppendingString”好使用多了,程式碼 也減少許多.但仍然在Device 會當掉.

於是我開始想著有沒有可能是記憶體管理的問題呢?在一本“Programming in Objective-C 2.0”, 2nd Edition 的某章節中有一小段寫著大致內容為”StringByAppendingString 會建立一個由二字串字合併組成的新字串物件“(非原文引用),所以說以剛才的程式為例
str = [str StringByAppendingString:@":string 2"];
//此時str為一個新的字串物件,那原本的字串物件呢?
原兇出現了, 就是“原本的字串物件呢?”, 此時有人會說Objective-C 有autorelease的機制. 沒錯是有autorelease機制,但此時並沒有被relase掉喔.(本篇並不討論release問題,請各自詳讀Objective-C的記憶體管理)因此有太多的字串物件沒有被立即release而導致程式crash.

解說到此希望有人看得慬我所要說明的,而且能瞭解NSString是不可變更的字串物件.

所以我的問題就得請出原本一直以為是多餘的一個字串物件NSMutableString,即所謂的可變更的字串物件.而修改後的程式大致如下:
NSMutableString *str = [[NSMutableString alloc] init];
while(...) {
[str appendFormat:@"..."]; // 不需回傳,因為是原串字直接append
}

如此一來就不會一直create一堆沒用的NSString在記憶體內啦.

此事讓我對除了Pascal 以外第二個欣賞的語言就是Objective-C