Skip to main content

3 posts tagged with "C#"

View All Tags

· 3 min read

Msn的log採用的格式是XML,隨便打開一個LOG後仔細檢視,可以發現msn log的訊息格式大概是採這樣

    <Message Date="2012/3/23" Time="下午 11:33:12" DateTime="2012-03-23T15:33:12.790Z" SessionID="1">
<From><User FriendlyName="邱 渣"/></From>
<To><User FriendlyName="XXX"/></To>
<Text>明天會到否</Text>
</Message>

每一則訊息,本身的屬性會包含該訊息的發送時間 ,有兩種格式,後面的790Z就不清楚是什麼意思了,SessionID這個屬性

也不是很清楚,但是這些都不重要

利用Date跟Time就可以取得基本時間了。

接者可以看到底下有三個屬性,代表訊息發送者,訊息接收者,以及發送的訊息為何

如果有啟動顏色跟字型的話,TEXT欄位就會變成下列樣子,會有屬性標示其顏色與字型

    <Text Style="font-family:Microsoft JhengHei; color:#000000; "> test </Text>

在C#中,我這次使用XmlElement來做為解析XML的工具,載入檔案後,因為我們只關心訊息的傳送,

所以先利用GetElementsByTagName("message")來取得所有Message有關的nodes

接者針對這個結點內的所有資料去進行資料抓取,我們的目標有 時間、發送者、傳送文字

先將XmlNode轉型為XmlElement的類型,這樣方便處理,然後利用GetAttribute來取得Message的屬性

我們就可以知道每個對話的Date跟Time。接者要存取其child(From,To,Text)這些的值

這邊比較要注意的是這兩種的差別

    <From>"邱渣"</From>
<From><User FriendlyName="邱渣"/></From>

以Type1來說,邱渣是From這個結點的值,可以利用childList[0].value 取得發送者的名稱

但是對Type2來說,邱渣是From這個結點底下的一個結點中的屬性,所以就要利用childList[0].FirstChild

的方式來取得<User>這個結點,再搭配Attributes[0].Value來取得第一個屬性的值,如此才可以取得"邱渣"的值

所以利用childList[2].FirstChild.Attributeds[0].Value就可以取得文字訊息了!

另外,如果要取得文字的顏色跟字型的話,利用

childList[2].GetAttribute("Style")

接者在去自己處理字串來取得字型跟顏色。

範例code如下

    xml = new XmlDocument();
xml.Load(filename);
XmlNodeList nodeList = xml.GetElementsByTagName("Message");
foreach (XmlNode parentNode in nodeList)
{

XmlElement element = (XmlElement)parentNode;
string Date = element.GetAttribute("Date");
string Time = element.GetAttribute("Time");
XmlNodeList childList = element.ChildNodes;
data += childList[0].FirstChild.Attributes[0].Value + " 說 (" + Time + ")\r\n";
}

· 4 min read

#[User]

不論是bash,tcsh,又或者是windows的cmd,都有一種叫做PIPE的功能

能夠將兩個獨立的程式給串接起來,把前面程式的輸出當作下一個程式的輸入

擁有這個指令,就能將本來當一功能的程式給組合起來變成複雜的工具了

舉例來說,我想要知道我當前目錄下有多少個檔案

就可以使用ls跟wc兩個指令合作完成,

使用 ls | wc 就會將ls的結果(檔案列表)當作輸入傳給wc這隻程式,然後就可以輕鬆地算出當前目錄的檔案數量

或者是有時候想要搜尋某些特定的字串,都會使用grep這個指令,譬如想要搜尋某個特定使用者正在執行的所有程序

ps auxww | grep username

所以pipe對於系統管理來說,是個非常重要的概念,能夠將每個獨立細小的程式給串接起來完成複雜的工作。

#[程式設計]

在FreeBSD(linux)上,shell能夠辦得到這樣的功能,實際上是利用了kernel中pipe的功能,這邊就已linux kernel 3.5.4為架構。

在程式中,pipe的概念就是一個水管,這個水管有兩個端口,一端負責寫資料到pipe,一端負責將資料從pipe中讀出來,所以我們可以做個簡單的測試。

int main(){
int rand1,rand2;
int fd[2];// declare a two-d array, store file_descriptor of the pipe (two side)
// fd[0] mease read side, fd[1] means write side
pid_t pid;//child process的pid
pipe(fd); //call system call (pipe) to create a pipe
//use fork to create a child process
//child process will wrtie data to pipe, and parent will read data from pipe
//child process
if((pid=fork())==0){
srand(getpid());
close(fd[READ_END]);//child won't use read size, so close it
rand1=rand()%RANGE; //create random number
write(fd[WRITE_END],&rand1,sizeof(rand1)); //write to pipe
close(fd[WRITE_END]);//close write side when write over
printf("%d has been created In Child Process \n",rand1);
exit(1);
}
else if(pid>0){
srand(getpid());
close(fd[WRITE_END]);//parent won't use write size, so close it。
rand2=rand()%RANGE;//create random number
read(fd[READ_END],&rand1,sizeof(rand1));//read the data from pipe
printf("%d has been created In Parent Process \n",rand2);
wait();
printf("Parent Process calulate sum is :%d \n",rand1+rand2);
close(fd[READ_END]);//close read side
exit(1);
}
return 0;
}

執行結果: 8 has been created In Child Process

5 has been created In Parent Process

Parent Process calulate sum is :13


3 has been created In Child Process

3 has been created In Parent Process

Parent Process calulate sum is :6

實際上,如果想要對同個端口去進行寫跟讀的動作,是行不通的,乍看之下會覺得PIPE只是一個

buffer,放置資料而已,實際上在kernel中,pipe被視為是一個file,當我們呼叫pipe時,真正最後會

呼叫到do_pipe這個function,在這個function中,會針對pipe的兩個端口分別去設定

O_RDONLY;O_WRONLY的標籤,這樣的設定使得pipe的端口就真的一邊只能讀,一邊只能寫。

有空在來講述一下file_descriptor file file_operation三者的關係,以及到底 file,socket,pipe...等這些device到底在kernel中如何運作。

· One min read

C++中,有所謂的顯性轉換跟隱性轉換

在宣告時,加入explicit 這個關鍵字,可以禁止使用顯性轉換,以下為例

    using namespace std;
class Stack {
public:
Stack(int a){};
};
void Test(Stack b){
}
int main()
{
Stack s1 = 1; //ok
Stack s2 = Stack(12); //ok
Stack s3(s1); //ok
Test(123); //ok
return 0;
}
    using namespace std;
class Stack {
public:
explicit Stack(int){};
};
void Test(Stack b){
}
int main()
{
Stack s1 = 123; //error
Stack s2 = Stack(123); //ok
Stack s3(s1); //ok
Test(123); // error
return 0;
}
Tags: