2010年11月29日 星期一

演算法 - 背包問題

包問題在演算法中為一經典題型,是一種最佳化的問題,而解決最佳化的問題,就需要用到「動態規劃」來解決,它是利用遞迴特性來拼湊出最佳解答。

以下就用 ACM 624 作為範例題目( 中文翻譯 ACM 624 ),提供解法並且解釋它是如何解決問題。

input:
5 3 1 3 4
10 4 9 8 4 2
20 4 10 5 7 4
90 8 10 23 1 2 3 4 5 7
45 8 4 10 44 43 12 9 8 2

output:
1 4 sum:5
8 2 sum:10
10 5 4 sum:19
10 23 1 2 3 4 5 7 sum:55
4 10 12 9 8 2 sum:45

不過這裡將題目改一改,不是 CD 的問題,將 CD 改為背包,而每首歌的時間長度改為物品的公斤重,在背包最大限制重量下,最多能拿幾公斤。

以下為 C# 程式碼,首先需要宣告幾個全域變數:
static int[] item_kg_array; // 每件物品的公斤重
static bool[] record_item_isTake_array; // 紀錄臨時物品是否拿取
static bool[] best_item_isTake_array; // 紀錄最佳物品是否拿取
static int max_kg; // 背包公斤限制
static int item_count; // 物品數量
static int record_max_kg; // 紀錄目前最大公斤數
在程式開頭,讀取相關資料:
string line = Console.ReadLine();
string [] value = line.Split(new string[]{" "},
StringSplitOptions.RemoveEmptyEntries );

max_kg = Convert.ToInt32(value[0]);
item_count = Convert.ToInt32(value[1]);

item_kg_array = new int[item_count];
record_item_isTake_array = new bool[item_count];
best_item_isTake_array = new bool[item_count];

for (int i = 2; i < item_count + 2; i++)
item_kg_array[i - 2] = Convert.ToInt32(value[i]);

record_max_kg = 0;
接著就是重點程式碼,以下程式碼為一函式,函式傳入索引 index 與目前公斤重 now_kg,函式一開始就先判斷 now_kg 是否大於目前最大公斤重 record_max_kg 且 now_kg 小於背包公斤限制 max_kg,如果條件成立,則紀錄 record_max_kg 為 now_kg 且紀錄最佳拿取方式 best_item_isTake_array 為 record_item_isTake_array。
再來判斷 index 使否小於物品數量 item_count,如條件成立,則先將目前索引是否拿取設置成 true 後再次呼叫自己傳入索引值加 1 及目前公斤數加上物品在索引值位置的公斤重兩數,如不成立,將目前索引是否拿取設置成 false 後再次呼叫自己傳入索引值加 1 及目前公斤數。如此一來,程式就會像「二元樹」一樣,依照 index 索引值分別來展開拿與不拿此物品的樹,而答案就會呼之欲出了。
static void knapsack(int index, int now_kg)
{
if (now_kg <= max_kg && now_kg > record_max_kg)
{
record_max_kg = now_kg;
for (int j = 0; j < index; j++)
best_item_isTake_array[j] = record_item_isTake_array[j];
}
if (index < item_count)
{
record_item_isTake_array[index] = true;
knapsack(index + 1, now_kg + item_kg_array[index]);
record_item_isTake_array[index] = false;
knapsack(index + 1, now_kg);
}
}
最後在主程式最後呼叫並且印出:
knapsack(0, 0);
for (int i = 0; i < item_count; i++)
if (best_item_isTake_array[i]) Console.Write("{0} ", item_kg_array[i]);
Console.WriteLine("sum:{0}", record_max_kg);


回首頁

2010年11月24日 星期三

演算法 - 老鼠走迷宮

鼠走迷宮為演算法中較基本的題型,給一迷宮圖形,畫出起點到終點的解法與解法數量,亦或是算出解法步數,都可以利用以下程式算出。

與大部分的演算法相同,老鼠走迷宮是利用遞迴的特性,使得老鼠能判斷上下左右是否有路,並且走到死路能回頭再找別的路走。
以下例子為左上走到右下的迷宮。
input:
8 7
..XXXXXX
X......X
X.X.XX.X
X.X.X..X
XXX.XXXX
X......X
XXXXXX..

output:
--XXXXXX
X---...X
X.X-XX.X
X.X-X..X
XXX-XXXX
X..----X
XXXXXX--

以C#為例子,用String.Split讀取 row 與 col:
string line = Console.ReadLine();
string[] value = line.Split(new string[]{" "},
StringSplitOptions.RemoveEmptyEntries);
int col = Convert.ToInt32(value[0]);
int row = Convert.ToInt32(value[1]);
接著宣告一個 char 二維陣列,讀入迷宮的資料:
int eRowIndex = row - 1;
int eColIndex = col - 1;

char[,] maze = new char[row, col];
for (int i = 0; i < row; i++)
{
char[] mazeTmp = Console.ReadLine().ToCharArray();
for (int j = 0; j < mazeTmp.Length; j++)
maze[i, j] = mazeTmp[j];
}
Console.WriteLine();
接下來是遞迴函式就是在模擬老鼠走法,每一步老鼠會做記號 ( 改為 '-' ) 並且判斷是否已經到了終點,如果未到終點,老鼠會嘗試上下左右是否有路,如果有路,接著往有路的方向呼叫函式;如果沒有路,就將此點記號取消 ( 改為 '.' ),如此一來,所有走到死路的走法都會回頭到岔路繼續往別的方向嘗試,最後,就會走到終點。
static void visit(int nRI, int nCI, int eRI, int eCI, char[,] maze)
{
maze[nRI, nCI] = '-';
if (nRI == eRI && nCI == eCI)
print(maze);

if (!(nRI - 1 < 0) && maze[nRI - 1,nCI] == '.') // 上
visit(nRI - 1, nCI, eRI, eCI, maze);
if (!(nCI - 1 < 0) && maze[nRI, nCI - 1] == '.') // 左
visit(nRI, nCI - 1, eRI, eCI, maze);
if (nRI + 1 <= eRI && maze[nRI + 1, nCI] == '.') // 下
visit(nRI + 1, nCI, eRI, eCI, maze);
if (nCI + 1 <= eCI && maze[nRI, nCI + 1] == '.') // 右
visit(nRI, nCI + 1, eRI, eCI, maze);

maze[nRI, nCI] = '.';
}

static void print(char[,] maze)
{
for (int i = 0; i < maze.GetLength(0); i++)
{
for (int j = 0; j < maze.GetLength(1); j++)
Console.Write(maze[i, j]);
Console.WriteLine();
}
Console.WriteLine();
}
最後,只要傳入起點位置與終點位置與迷宮陣列,即能將解法輸出:
visit(0, 0, eRowIndex, eColIndex, maze);

回首頁

2010年11月19日 星期五

XSS 跨站指令碼 ( Cross-Site Scripting )

XSS 為跨站指令碼,針對任何網站出現的安全性漏洞加以攻擊,小從惡作劇大到個人資料外洩,駭客 ( hacker ) 更可能取得管理者的權限,做出一些不可預期的事情。

一般論壇、留言板、...等,都有可能會產生這種情況。假設駭客 ( hacker ) 在某論壇上留了一篇文章並且有一段 script 碼導向到他的網頁,駭客的網頁是分析 cookie 內資訊並且紀錄。而網友甲在打上帳號和密碼登入某論壇,注意了,只要是保持登入狀態就會記錄 cookie。而網友甲瀏覽到駭客的文章並且點擊駭客的連結,此時網友甲的 cookie 會被帶到駭客的網頁,如此一來,網友甲的資料就會被竊取。

其實只要能讓駭客在文章上留下 script 碼,接下來就是等網友點擊,最後駭客所該做的就是分析 cookie 內的資訊,再來只能任他為所欲為了。

回首頁

2010年11月15日 星期一

Button Click 進行導向 ( Direct ) 頁面

篇教大家「如何按下按鈕後,查詢所輸入資料,並且導向到詳細資料頁面。」,查詢介面為 Default.aspx,而導向頁面為 Default2.aspx。






Default.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>輸入姓名</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="txtName" runat="server"></asp:TextBox>
<asp:Button ID="btnConfirm" runat="server" Text="確定" /><br/>
<font color="red"><asp:Label ID="lblMessage" runat="server" Text=""></asp:Label></font>
</div>
</form>
</body>
</html>
Default.aspx.vb
Imports System.Data.SqlClient

Partial Class _Default
Inherits System.Web.UI.Page

Protected Sub btnConfirm_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnConfirm.Click

Dim Name As String = txtName.Text

If String.IsNullOrEmpty(Name) <> True Then

Dim connString As String = ConfigurationManager.ConnectionStrings("dbMember").ConnectionString
Dim connection As New SqlConnection(connString)
Dim command As New SqlCommand("SELECT * FROM Member WHERE Name='" + Name + "'", connection)

connection.Open()
Dim reader As SqlDataReader = command.ExecuteReader()

If (reader.Read()) Then
Response.Redirect("Default2.aspx?ID=" + Convert.ToString(reader.GetInt32(0)))
Else
lblMessage.Text = "Not Find!"
End If
connection.Close()

End If

End Sub
End Class


而 Member 資料表內資料如下圖:
Default2.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default2.aspx.vb" Inherits="Default2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>導向頁面</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lblID" runat="server" Text="-"></asp:Label> /
<asp:Label ID="lblName" runat="server" Text="-"></asp:Label>
</div>
</form>
</body>
</html>
Default2.aspx.vb
Imports System.Data.SqlClient

Partial Class Default2
Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

Dim ID As String = Request.QueryString("ID")
If String.IsNullOrEmpty(ID) <> True Then

Dim connString As String = ConfigurationManager.ConnectionStrings("dbMember").ConnectionString
Dim connection As New SqlConnection(connString)
Dim command As New SqlCommand("SELECT * FROM Member WHERE MemberID=" + ID, connection)

connection.Open()
Dim reader As SqlDataReader = command.ExecuteReader()

If (reader.Read()) Then
lblID.Text = Convert.ToString(reader.GetInt32(0))
lblName.Text = Convert.ToString(reader.GetString(1))
End If
connection.Close()

End If
End Sub
End Class
執行後如下兩圖:

回目錄
回首頁

2010年11月14日 星期日

Regular Expression 與 C# Regex 教學

Regular Expression 稱為「正規表達式」,但我都稱它為「字串篩選條件」,Regular 有「正規」、「常態」之意,在此處為「規則」的意思。它為敘述一句符合某段句法規則之字串的字串,通常用來找尋與驗證或替換符合規則的字串,是個強大的字串匹配的類別。

Visual C# 中為 Regex 類別,在此就使用它為基礎做介紹。

Regex 建構函式有二:
  • Regex regex = new Regex(string pattern);
  • Regex regex = new Regex(string pattern, RegexOptions options);

以上 string pattern 為規則字串,RegexOptions options 為字串比對選項,是一個列舉型別,以下為它所有列舉值的成員與說明:
編號成員名稱說明
1Compiled指定規則運算式要編譯為組件,這將產生較快速的執行,但會增加啟動時間。
2CultureInvariant指定忽略語言中的文化差異。
3ECMAScript啟用運算式的 ECMAScript 相容行為,這個值只能結合 IgnoreCase、Multiline 和 Compiled 值使用,將這個值與任何其他值一起使用都將導致例外狀況。
4ExplicitCapture指定唯一有效的擷取為明確命名的或編號的,格式為 (?…) 的群組。這允許未命名的括號充當非擷取群組,而避免運算式 (?:…) 的語法不便。
5IgnoreCase指定區分大小寫的比對。
6IgnorePatternWhitespace從模式排除未逸出的泛空白字元 (White Space),並啟用以 # 標記的註解。不過,IgnorePatternWhitespace 值不會影響或排除字元類別中的泛空白字元。
7Multiline多行模式,變更 ^ 和 $ 的意義以致它們分別在任何一行的開頭和結尾做比對,而不只是整個字串的開頭和結尾。
8None指定無選項設定。
9RightToLeft指定搜尋將由右至左,而非由左至右。
10Singleline指定單行模式,變更點 (.) 的意義以至於它符合一切字元 (而不是 \n 之外的一切字元)。
以上表格轉自:http://msdn.microsoft.com/zh-tw/library/system.text.regularexpressions.regexoptions%28v=VS.80%29.aspx

通常我用 1、5、10 就夠了,其他的列舉成員我鮮少在用。
所以宣告時,要加入這些比對選項的列舉值,可以如以下宣告 ( pattern 為規則字串 ):
  • 單一比對列舉值宣告 - Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
  • 多個比對列舉值宣告 - Regex regex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline );

接下來就開始介紹 Regular Expression 的語法規則:
































編號字元描述
1\將下一個字元標記為一個特殊字元、或一個原義字元、或一個向後參照、或一個八進制轉義符。例如,「n」匹配字元「n」。「\n」匹配一個換行符。序列「\\」匹配「\」而「\(」則匹配「(」。
2^匹配輸入字串的開始位置。如果設定了RegExp物件的Multiline屬性,^也匹配「\n」或「\r」之後的位置。
3$匹配輸入字串的結束位置。如果設定了RegExp物件的Multiline屬性,$也匹配「\n」或「\r」之前的位置。
4*匹配前面的子運算式零次或多次。例如:Gooo*gle 能匹配 Google、Goooooogle。* 等於 {0,}。
5+匹配前面的子運算式一次或多次。例如:Gooo+gle 能匹配 Gooogle、Goooooogle,但不能匹配 Google。+ 等於 {1,}
6?匹配前面的子運算式零次或一次。例如:Gooo?gle 只能匹配 Gooogle 和 Google。? 等於 {0,1}
7{n}n是一個非負整數。匹配確定的n次。例如:o{3} 能匹配 Gooogle 的 ooo,但不能匹配 Google。
8{n,}n是一個非負整數。至少匹配n次。
9{n,m}m和n均為非負整數,其中n<=m。最少匹配n次且最多匹配m次
10?當該字元緊跟在任何一個其他限制符(*,+,?,{n},{n,},{n,m})後面時,匹配範式是非貪婪的。非貪婪範式儘可能少的匹配所搜尋的字串,而預設的貪婪範式則儘可能多的匹配所搜尋的字串。
11.匹配除「\n」之外的任何單個字元。要匹配包括「\n」在內的任何字元,請使用像「[.\n]」的範式。
12(pattern)匹配pattern並獲取這一匹配。( ... ) 有群組的意思。例如:(ab) 能匹配 abc 中的 ab,但不能匹配 acc。
13(?:pattern)匹配pattern但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行儲存供以後使用。例如:run(?:n|ning) 能匹配 running 整個字串,並且從此字串後繼續比對。
13(?=pattern)正向預查,在任何匹配pattern的字串開始處匹配尋找字串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如:Office(?=2003|2007|2010) 能匹配 Office2003 中的 Office,但不能匹配 Office2005 中的 Office,而從 Office 字串後繼續比對。
14(?!pattern)負向預查,在任何不匹配pattern的字串開始處匹配尋找字串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如:Office(?!2003|2007|2010) 能匹配 Office2005 中的 Office,但不能匹配 Office2010 中的 Office,而從 Office 字串後繼續比對。
15x|y匹配x或y。
16[xyz]字符集合。匹配所包含的任意一個字元。
17[^xyz]負值字符集合。匹配未包含的任意字元。
18[a-z]字元範圍。匹配指定範圍內的任意字元。
19[^a-z]負值字元範圍。匹配任何不在指定範圍內的任意字元。
20\b匹配一個單詞邊界,也就是指單詞和空格間的位置。
21\B匹配非單詞邊界。
22\cx匹配由x指明的控制字元。例如,\cM匹配一個Control-M或Enter符。x的值必須為A-Z或a-z之一。否則,將c視為一個原義的「c」字元。
23\d匹配一個數位字元。\d 等於[0-9]。
24\D匹配一個非數位字元。\D 等於[^0-9]。
25\f匹配一個換頁符。\f 等於\x0c和\cL。
26\n匹配一個換行符。\n 等於\x0a和\cJ。
27\r匹配一個Enter符。\r 等於\x0d和\cM。
28\s匹配任何空白字元,包括空格、製表符、換頁符等等。\s 等於[\f\n\r\t\v]。
29\S匹配任何非空白字元。\S 等於[^\f\n\r\t\v]。
30\t匹配一個製表符。\t 等於\x09和\cI。
31\v匹配一個垂直製表符。\v 等於\x0b和\cK。
32\w匹配包括底線的任何單詞字元。\w 等於「[A-Za-z0-9_]」。
33\W匹配任何非單詞字元。\W 等於「[^A-Za-z0-9_]」。
34\xn匹配n,其中n為十六進制轉義值。十六進制轉義值必須為確定的兩個數位長。例如,「\x41」匹配「A」。「\x041」則等價於「\x04&1」。正則運算式中可以使用ASCII編碼。
35\num匹配num,其中num是一個正整數。對所獲取的匹配的參照。例如,「(.)\1」匹配兩個連續的相同字元。
36\n標識一個八進制轉義值或一個向後參照。如果\n之前至少n個獲取的子運算式,則n為向後參照。否則,如果n為八進制數位(0-7),則n為一個八進制轉義值。
37\nm標識一個八進制轉義值或一個向後參照。如果\nm之前至少有nm個獲得子運算式,則nm為向後參照。如果\nm之前至少有n個獲取,則n為一個後跟文字m的向後參照。如果前面的條件都不滿足,若n和m均為八進制數位(0-7),則\nm將匹配八進制轉義值nm。
38\nml如果n為八進制數位(0-3),且m和l均為八進制數位(0-7),則匹配八進制轉義值nml。
39\un匹配n,其中n是一個用四個十六進制數位表示的Unicode字元。例如,\u00A9匹配版權符號(©)。
以上表格轉自:http://zh.wikipedia.org/zh-tw/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F

小弟所寫的另一篇文章 Regular expression 常用驗證 中有常用的驗證規則字串,供大家參考。

以下為一 Regex 使用的方法:
string input = "The men's soft tennis team captured the first gold medal for Taiwan " + 
"yesterday in the 2010 Asian Games in Guangzhou, China, while their " + 
"female counterparts garnered a silver for Taiwan, which is competing " + 
"as Chinese Taipei at the regional sport games."; // 原始字串
string pattern = @"(?<word>\sc[\w]*)"; // 規則字串
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase); // 宣告 Regex 忽略大小寫
MatchCollection matches = regex.Matches(input); // 將比對後集合傳給 MatchCollection
int index = 0;
foreach (Match match in matches) // 一一取出 MatchCollection 內容
{
// 將 Match 內所有值的集合傳給 GroupCollection groups
GroupCollection groups = match.Groups;
// 印出 Group 內 word 值
Console.WriteLine( ++ index + ": " + groups["word"].Value.Trim()); 
}
上面程式碼執行結果為下:
1: captured
2: China
3: counterparts
4: competing
5: Chinese

回目錄
回首頁

2010年11月11日 星期四

Google 關鍵字監控工具

近為了測試某網站針對指定關鍵字的排名,而關鍵字有 33000 多筆,馬上我就寫了一個工具去找尋 ( 利用小弟寫的一篇文章 模擬人為使用搜尋引擎 的概念 ) 所有指定關鍵字的排名。






不過執行不久便出現以下畫面:其實這對時常在網頁探勘的人已經見怪不怪了,除此之外,google 還會請你輸入驗證碼,證明「你是人,不是機器」。

哇銬,這都被它發現了,這樣我還玩個屁阿!

後來發現,每做一個網頁轉換的動作太快了,所以我每做一個網頁轉換的動作會停個兩秒,果然,目前做了兩個小時多都沒被擋下來,哈哈,又有得玩了。

而我 google 了一下,找到一個工具也是與我寫的工具做類似的事情,在此就稍微介紹一下那個工具。
Free Monitor for Google ,字面上的意思就是 免費 Google 監控,不過它就是如同我的工具所說,找出「某網站針對指定關鍵字的排名」。( 網址有提供下載點,可先下載並照以下步驟使用 )

  • 安裝步驟請照以下框紅線按鈕點擊。

  • 開啟工具若是第一次使用就會請你決定基本設定。Search Depth 即表示網站要搜尋到第幾排名為止。

  • 開啟工具後,可以找到新增網址的地方,如圖新增

  • 再來編輯關鍵字,如圖新增

  • 最後只需按下右上搜尋鈕,稍等一會兒,就會找出搜尋結果,列出網站在關鍵字下最好的排名。



回首頁

2010年11月10日 星期三

javascript 子視窗關閉,重新整理母視窗

於資料更新的關係,不得不利用子視窗來幫忙新增一筆資料,再將母視窗的資料更新。
母視窗為查詢介面,而由母視窗開啟子視窗後,子視窗新增一筆資料後關閉,隨即重新整理母視窗查詢資料。

其實程式碼也只有少少幾行,卻好像被我說的很複雜,這表示我說屁話的功力更上一層樓。

只適用於 GET 傳遞參數網頁。
只要在子視窗下加上一段 javascript:
<script type="text/javascript">
function unLoad()
{
window.opener.location.href = window.opener.location.href;
}
</script>
如果此時使用 window.opener.location.reload(),可能會跳出詢問視窗。
最後,在 body tag 加上 onunload="unLoad();",就可以在關閉子視窗後重新整理母視窗。

回目錄
回首頁

2010年11月9日 星期二

javascript 取得參數值

利用以下程式碼加入 header 區塊,再去呼叫 QueryString 函式,即可取得參數值。
<script type="text/javascript">
function QueryString(item){
var svalue = location.search.match(new RegExp("[\?\&]" + item + "=([^\&]*)(\&?)","i"));
return svalue ? svalue[1] : svalue;
}
</script>


回目錄
回首頁

ASP.NET 留言版 寄送Email (VB)

先,建好一個留言版的表格,按下送出Button,將填寫內容寄發Email送到管理者信箱,告知是誰來留言了。

建立四個TextBox,分別代表 暱稱, email, 主題, 內容,最後在加上一個Button為送出,如下圖所示:



程式碼如下:
Imports System.Net.Mail
Partial Class contacts
Inherits System.Web.UI.Page

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim strName As String = TextBox1.Text
Dim strEmail As String = TextBox2.Text
Dim strSub As String = TextBox3.Text
Dim strBody As String = TextBox4.Text

Dim eMail As New MailMessage()
Dim mSender As New MailAddress(strEmail, strName)'strEmail=email帳號本身, strName=在email帳號上顯示的文字

eMail.From = mSender'寄件者
eMail.To.Add("abc@aaa.com")'收件者
eMail.Subject = strSub'寄送email主旨
eMail.Body = strBody'寄送email內容
eMail.IsBodyHtml = True
Dim smtp As New System.Net.Mail.SmtpClient()
smtp.Host = "127.0.0.1"
smtp.Port = 25
smtp.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.PickupDirectoryFromIis
smtp.Send(eMail)
End Sub


回目錄
回首頁

JQuery 讀取 ASP.NET 傳遞 Json 格式資料

JSON (JavaScript Object Notation) 為一傳遞資料的格式,ajax 傳遞資料皆使用 Json 格式,維基 (wiki) 上稱它為一種輕量級的資料交換語言,易於閱讀。與 xml 最大的不同就是,xml 有絕佳的延展性,Json 目的在於資料的交換。




若 xml 資料為以下結構:
<item>
<ID>1</ID>
<Name>DavidKuo</Name>
</item>
而Json 資料結構就為:
{
item:{
id:1,
name:'DavidKuo'
}
}
提供大家一個 xml 轉換 Json 的網址 http://www.thomasfrank.se/xml_to_json.html
此次要提供的就是「從資料表製作一個 Json 格式資料,使用 JQuery 函式 .getJSON() 讀取回傳資料並顯示在網頁上」。基於 google 搜尋引擎的幫助,很快就找到了參考網址,約略1 ~ 2小時漸有融會貫通的感覺,這表示我網頁爬文功力更上一層樓。
  • 首先,網頁只需留下<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> 等字樣,其餘皆不要存在。

  • 下達 SQL 查詢指令將資料塞進 DataTable,並將 DataTable 轉換成 Json 字串。
    假設資料庫為有下圖資料:而程式碼中,ID 為參數,若無參數,則全部列出:
    using System;
    using System.Data;
    using System.Configuration;
    using System.Data.SqlClient;
    using System.Text;

    public partial class _Default : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    string connString = ConfigurationManager.ConnectionStrings["Member.Properties.Settings.ConnectionString"].ConnectionString;
    DataTable dt = new DataTable();

    if (!string.IsNullOrEmpty(Request.QueryString["id"]))
    {
    string id = Request.QueryString["id"];
    SqlDataAdapter adapter = new SqlDataAdapter(new SqlCommand("SELECT * FROM Member WHERE id=" + id, new SqlConnection(connString)));
    adapter.Fill(dt);
    }
    else
    {
    SqlDataAdapter adapter = new SqlDataAdapter(new SqlCommand("SELECT * FROM Member", new SqlConnection(connString)));
    adapter.Fill(dt);
    }

    Response.Write(DataTableToJsonString(dt));
    }

    public string DataTableToJsonString(DataTable dt)
    {
    StringBuilder JsonString = new StringBuilder();

    if (dt != null && dt.Rows.Count > 0)
    {
    JsonString.Append("{");
    JsonString.Append(@"""item"":[");

    for (int i = 0; i < dt.Rows.Count; i++)
    {
    JsonString.Append("{");
    for (int j = 0; j < dt.Columns.Count; j++)
    {
    JsonString.Append(string.Format(@"""{0}"":""{1}""", dt.Columns[j].ColumnName, Convert.ToString(dt.Rows[i][j])));
    if (j != dt.Columns.Count - 1) JsonString.Append(",");
    }
    JsonString.Append("}");
    if (i != dt.Rows.Count - 1) JsonString.Append(",");
    }
    JsonString.Append("]}");
    }
    return JsonString.ToString();
    }

    }
    網頁開啟後如同下圖:
  • 最後建立另依 *.apsx 頁面,匯入 jquery 的 js 檔,使用 .getJSON() 函式將資料一筆一筆讀出。程式碼如下:
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
    <title>未命名頁面</title>
    <script type="text/javascript" src="jquery-1.4.3.min.js"></script>
    <script type="text/javascript" src="App_Data/jquery-1.2.6.pack.js"></script>
    <script type="text/javascript">
    $(document).ready(function() {
    $.getJSON("Default.aspx?id=1",
    function(data){
    $.each(data.item, function(i,item){
    $("#member").append(item.ID + ' / ' + item.Name + '<br />');

    });
    });
    });

    </script>
    </head>
    <body>
    <form id="form1" runat="server">
    <div id="member"></div>
    </form>
    </body>
    </html>
    最後執行後頁面圖:

參考網址:http://chrisbalboa.pixnet.net/blog/post/30161616
http://zh.wikipedia.org/zh/JSON

回目錄
回首頁

2010年11月4日 星期四

DataTable 轉換成 CSV 與 CSV 轉換成 DataTable

取資料庫內的資料,可能希望匯出成檔案方便記錄與查詢。以下就提供以 DataTable 轉成 CSV 檔,以及用 OleDb 套件讀取 CSV 轉成 DataTable。
DataTable 轉成 CSV 檔函式程式碼如下:
public void CreateCSVFile(DataTable dt, string strFilePath) // strFilePath 為輸出檔案路徑 (含檔名)
{
StreamWriter sw = new StreamWriter(strFilePath, false);

int intColCount = dt.Columns.Count;

if (dt.Columns.Count > 0)
sw.Write(dt.Columns[0]);
for (int i = 1; i < dt.Columns.Count; i++)
sw.Write("," + dt.Columns[i]);

sw.Write(sw.NewLine);
foreach (DataRow dr in dt.Rows)
{
if (dt.Columns.Count > 0 && !Convert.IsDBNull(dr[0]))
sw.Write(Encode(Convert.ToString(dr[0])));
for (int i = 1; i < intColCount; i++)
sw.Write("," + Encode(Convert.ToString(dr[i])));
sw.Write(sw.NewLine);
}
sw.Close();
}

public string Encode(string strEnc)
{
return System.Web.HttpUtility.UrlEncode(strEnc);
}
讀取 CSV 轉成 DataTable 函式程式碼如下:
public DataTable ReadCSVFile(string strFilePath, string strFileName) // strFilePath 為檔案所在資料夾,strFileName 為檔案名稱
{
OleDbConnection connection = new OleDbConnection(string.Format(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}; Extended Properties=""text;HDR=Yes;FMT=Delimited"";", strFilePath));
OleDbCommand command = new OleDbCommand("SELECT * FROM " + strFileName, connection);
OleDbDataAdapter adapter = new OleDbDataAdapter(command);
DataTable dt = new DataTable();

adapter.Fill(dt);

return dt;
}


回目錄
回首頁