2011年5月23日 星期一

千萬不要把空的SIM卡轉卡放到3G Data Card內

iPad & iPhone 4 都使用 Micro SIM 卡,


所以自從都換了 Micro SIM 卡後,因為懶惰,不想另外收納轉卡,


就這樣先放進 SIM 卡插槽再放進 3G Data Card 內,方便攜帶,



結果要拔起來時,把 Data Card 裡面的 SIM 卡接腳給... 扯斷了...



可能是因為轉卡是空的,有空隙卡住接腳,造成拔起來的時候,就順勢拉起並扯斷了。



送了兩次後,才發現是這個緣故,不過已經來不及了,


最後一次報價 $1,100.- ( >< 我在拍賣上看二手的也是這個價格 )


不曉得其它家的會不會這個樣子,還是小心點好,


反正 iPhone 4 有 Hotspot ,或者用 iShare MR-102N 也行,


應該用到 3G Data Card 的機會也不多了吧! ^^

2011年5月21日 星期六

出現 iTunes 無法從同步服務載入資料類別資訊 提示

想不到今天 Mac iTunes 一接上 iPhone / iPad 就給我出現這個訊息,



不管 iPhone / iPad 甚至是 Mac 重開都没有用,


只能同步不能備份 ( >< 挖勒,這樣我的遊戲永遠破不了關 )



好加在被我找到解決方法,差點就要給它 reset 下去了說,


可以參考


iTunes 10.2:安裝 Xcode 4 之後出現“iTunes 無法從同步服務載入資料類別資訊”提示


Windows 版 iTunes:“無法載入資料類別”或“無法載入供應商資料”同步服務提示


基本上重灌就好了,可能真的是受到安裝 xcode 4 的影響!


.

2011年5月15日 星期日

給穿了幫寶適的 iPhone4 可以輸出音樂

自從有了 iPhone 4 之後,第一件事就是給它穿上肖想很久的殼


Element CASE Vapor ,金屬的質感,讚!


不過也帶來了一些困擾,不只是 Element CASE,


應該有用 Bumper 式的保護套都會遇到這個問題,


就是除了原廠的傳輸線,其它比較大一點的線可能就無法使用了,


( 例如 VGA Adapter / Composite AV Cable )


所以透過 E7Buy 代購幫我在 日本 Yahoo 找到了 Dock 延長線,



2011年5月11日 星期三

讓 Oracle 透過 SMTP 元件發送 iPhone 看得懂的 eMail

系統透過 Oracle 發送郵件,原本是沒有特別指定什麼編碼什麼的,
Outlook 收信收的好好的,開放 Push Mail 後,User 開始用手機收信了,
但是透過 Oracle 發送出來的郵件,在 iPhone 上看,
在郵件清單預覽的時候,主旨跟內文兩行看起來是正常的,
但是點進去看郵件內文就變成全部亂碼了,
試了很多編碼組合,看起來用 base64 比較沒有問題,
內文除了 UTL_RAW.CAST_TO_RAW 外還需要轉成 base64編碼 UTL_ENCODE.BASE64_ENCODE
.
sample code

CREATE OR REPLACE PROCEDURE "SEND_MAIL" (
msg_to varchar2 :='',
msg_subject varchar2 :='',
msg_sender varchar2 :='',
msg_text varchar2 := '' )
IS
lv_conn UTL_SMTP.CONNECTION;
lv_server VARCHAR2(255) := 'SERVERIP';
lvmsg_to VARCHAR2(50) := '';
lv_encoded_subject VARCHAR2(255) := '';
BEGIN

lvmsg_to :=replace(msg_to,';','');
--建立連線
lv_Conn := UTL_SMTP.Open_Connection(lv_server, 25);
UTL_SMTP.Helo(lv_conn, lv_server);
UTL_SMTP.Mail(lv_conn, msg_sender);
UTL_SMTP.Rcpt(lv_conn, lvmsg_to);
UTL_SMTP.OPEN_DATA(lv_conn);

-- 主旨
UTL_smtp.write_raw_data(lv_Conn,utl_raw.cast_to_raw(convert('Subject: ' ||msg_subject||utl_tcp.crlf,'zht16big5')));

--設定編碼
UTL_SMTP.WRITE_DATA(lv_conn, 'Content-Type: text/html;charset=Big5' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(lv_conn, 'Content-Transfer-Encoding: base64'|| UTL_TCP.CRLF);
--寄送日期
UTL_SMTP.WRITE_DATA(lv_conn,'Date: ' || to_char(sysdate-1/3,'YYYY-MON-DD hh24:mi:ss','NLS_DATE_LANGUAGE=AMERICAN') ||UTL_tcp.CRLF);
--寄件人
UTL_SMTP.WRITE_DATA(lv_conn, 'From: ' || msg_sender || UTL_TCP.CRLF);
--收件人
UTL_SMTP.WRITE_DATA(lv_conn, 'To: ' || lvmsg_to || UTL_TCP.CRLF);

--一定要空一行開始傳送郵件內文
UTL_SMTP.WRITE_DATA(lv_conn, UTL_TCP.CRLF);
--內文編碼後輸出
UTL_SMTP.WRITE_DATA(lv_conn, UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(convert(msg_text,'ZHT16BIG5')))));

--關閉連線
UTL_SMTP.CLOSE_DATA(lv_conn);
UTL_SMTP.QUIT(lv_conn);

EXCEPTION
WHEN UTL_SMTP.INVALID_OPERATION THEN
dbms_output.put_line(' Invalid Operation in SMTP transaction.');
WHEN UTL_SMTP.TRANSIENT_ERROR THEN
dbms_output.put_line(' Temporary problems with sending email - try again later.');
WHEN UTL_SMTP.PERMANENT_ERROR THEN
dbms_output.put_line(' Errors in code for SMTP transaction.');
END;

解決使用 .Net AJAX 從Client回Server時,中文會出現亂碼的問題

情境是例如在前端有一個 TextBox 控制項,當輸入文字後要回 Server 端處理,再送資料到 Client 端。
因為不需要整頁全部送回 Server 端,所以會採用像 .Net 的 AJAX Control 來做,

<asp:UpdatePanel ID="UpdateDOCTypePanelTrigger" UpdateMode="always" runat="server">
<ContentTemplate>
<asp:TextBox ID="test" AutoPostBack="true" OnTextChanged="test_TextChanged" runat="server"></asp:TextBox>
<asp:Label ID="testInfo" runat="server"></asp:Label>
</ContentTemplate>
<Triggers>
<asp:AsyncPostbackTrigger ControlID="test" EventName="TextChanged" />
</Triggers>
</asp:UpdatePanel>

.
但是送中文字回 Server 會有亂碼,所以需要特別處理一下。
找到的解決方法大概有兩種:
.
第一種是

protected void test_TextChanged(object sender, EventArgs e)
{
byte[] buffer = System.Text.Encoding.Default.GetBytes(test.Text);
testInfo.Text += System.Text.Encoding.UTF8.GetString(buffer);
}

這一種有一個缺點,有時候用GetBytes會漏一個byte,
所以解出來還有可能會有一個字是亂碼。
.
另外一種

protected void test_TextChanged(object sender, EventArgs e)
{
string s = System.Text.Encoding.UTF8.GetString(Request.BinaryRead(Request.ContentLength));
System.Collections.Specialized.NameValueCollection form = HttpUtility.ParseQueryString(s);
testInfo.Text += form[test.UniqueID];
}

稍微複雜一點,但是可以正確解出來,
就用這個了吧!
.
還是有更好的解法呢?

2011年5月4日 星期三

我只是要在開車的時候聽音樂

前年開始用某電信的歡樂點換了 KKBox 幾個月之後,


隨時隨地都能輕鬆享受聽音樂的樂趣,


有 Jazz 、華語、西洋流行音樂,連妹妹要聽的兒歌或催眠曲都有 ^^


但是在開車的時候卻聽不到 ( 如果開長途會很無聊 & 後面還會給我睡成一遍 ),


因為...


Toyota 2008 年 Altis 原廠 6 片音響没有 Aux In ><


原廠要加裝 Aux In 線組 (多功能外接音源轉換器)


是利用USB連接線或耳機孔線來連接多樣可攜式外部裝置,


像是 USB 隨身碟、iPod ... 等等,


又還不想換影音主機或是換一台 Player,


所以只好找一些 Solution 了。


上了什麼都賣的網站,有賣家可以幫忙在原廠主機再加裝一條 Aux In 的線,


這樣起碼我除了 CD 外,還有另外一個 Input 了,



接上 iPhone 的耳機孔,開始播放音樂囉!


.


2011年5月3日 星期二

使用 Oracle SQL Loader 快速載入資料進 DB

一般寫程式遇到需要新增資料到 DB 中,大部分的寫法都是直接 Insert Into [TableName] ...

以 .Net 來說大概就是使用 ADO .Net 來處理,如


string sql="";
string connectionString =
"Data Source=[DB];" +
"User ID=[ACT];" +
"Password=[PWD];";
// Create Connection
OracleConnection dbcon = null;
dbcon = new OracleConnection (connectionString);
dbcon.Open();

// Generate Command Text
OracleCommand dbcmd = dbcon.CreateCommand();
......
// [先 Select 資料再跑迴圈產生 Insert Statement]
for (...)
{
......
dbcmd.CommandText = sql;
dbcmd.ExecuteNonQuery();
}

// Relese Resource
dbcmd.Dispose ();
dbcmd = null;
dbcon.Close ();
dbcon = null;


然後視情況看是一筆一筆 Commit 還是弄成一個 Transation ,全部完成之後再 Commit 。

但是當資料量大到一定程度的時候 ( 例如批次作業將大量Log資料新增進DB ) 就不一定可行。


另外一種方式就是把全部的 Insert Statement 一次產生出來放到 Text File,


...以上省略...

// 原本 For 迴圈變成僅產生 Insert Statement
StringBuilder mTextContent = new StringBuilder();
for (...)
{
......
mTextContent.Append(sql);
}

// 全部產生完後,放入 Text File 內
using (System.IO.StreamWriter sw = new System.IO.StreamWriter("[FileName]", false))
{
sw.Write(mAllContent);
sw.Close();
}

...以下省略...


然後從 Console 程式裡面多開一個 Process 呼叫 命令提示字元(Command Line) 來執行 SqlPlus 處理所產生的 Text File。


...
System.Diagnostics.ProcessStartInfo PSI = new System.Diagnostics.ProcessStartInfo("cmd.exe");
PSI.RedirectStandardInput = true;
PSI.RedirectStandardOutput = false;
PSI.RedirectStandardError = true;
PSI.UseShellExecute = false;
PSI.WorkingDirectory = [Path];
System.Diagnostics.Process p = System.Diagnostics.Process.Start(PSI);
p.Start();
// ConnectionString 來自 Web.Config 的連線字串 (格式調整成 ACT/PWD@DB_TNS 而已)
p.StandardInput.WriteLine("sqlplus " + ConnectionString + " @\"[FileName\" ");
p.StandardInput.WriteLine("exit");
p.WaitForExit();
p.Close();
p.Dispose();
...


一般只要資料量沒有太大,這個方式就可以處理了。

但是還有一個更快的方法,就是透過 SQL Loader (MS Server好像是 Data Transformation Services;DTS )

SQL Loader 是 Oracle 的資料匯入工具,通常用來將大量的資料新增進 Oracle 資料庫中。

基本上可以分成三個部份:


  • Control file (控制檔,定義匯入Table、欄位對應與分隔符號...等)

  • Data file (資料檔,格式須參照控制檔定義)

  • Sqlldr (執行檔,可搭配一些參數彈性使用)



◎ Control File

大致內容如下:













load data
infile '[資料檔名]'尚可指定 discardfile result.dsc badfile result.bad (沒有指定則同資料檔名)
append into table "[TableName]"預設為 Insert,可改為 Append/Truncate/Replace
fields terminated by X'09' Optionally enclosed by '"'欄位間用 Tab 作分隔 (X'09');而字串值用雙引號括起來 (")
(以下為對應的欄位定義
SID INTEGER EXTERNAL,數字欄位
SNO FLOAT,浮點數欄位
SNAME CHAR(4000),字串欄位
SDATE Date "yyyy/mm/dd hh24:mi:ss",日期欄位以及格式
EDATE Date "yyyy/mm/dd" NULLIF (EDATE="null")日期欄位,遇到空值則塞null值
)


◎ Data File

參照 Control File 後,大致內容會如下:(分隔是 Tab)
1 1.1 "名稱1" "2011/03/03 01:20:30" "2011/03/05"
2 2.1 "名稱2" "2011/04/03 12:24:00" "2011/04/05"
3 3.1 "名稱3" "2011/05/03 15:16:17" "2011/05/05"

◎ Sqlldr 的語法

sqlldr userid=[帳號]/[密碼]@資料庫名稱 control=[控制檔名] log=[產生的Log檔名]


可以加上兩個參數

Rows=300 (每 300 個一次載入到資料庫中)

errors=100 (遇到 100 個錯誤就終止執行)

.

Log 內容摘要
(大約19個欄位,88111筆資料,Txt檔案大小21mb,Remote執行-Data&Control File不在DB Server上)

表格 "TEST_LIST":
已順利載入 88111 資料列.
由於資料錯誤, 0 資料列 未被載入
因為所有的 WHEN 子句均不成立, 0 資料列 未被載入
因為所有的欄位均為 NULL, 0 資料列 未被載入


分配給連結陣列的空間: 246294 個位元組 (9 列)
讀取 緩衝區位元組: 1048576

略過的邏輯記錄總數: 0
讀取的邏輯記錄總數: 88111
拒絕的邏輯記錄總數: 0
刪除的邏輯記錄總數: 0

自 星期三 4月 20 22:37:22 2011 開始執行
於 星期三 4月 20 22:41:18 2011 結束執行

目前歷時: 00:03:56.20
CPU 時間為: 00:00:03.75

單純全部載入 88111 筆資料列只要 4 分鐘的時間。

所以搭配程式使用,先按照控制檔定義的格式,輸出要匯入資料文字檔
再調整把 sqlplus 換成 sqlldr 即可

...
p.StandardInput.WriteLine("sqlldr userid=" + ConnectionString + " control=[控制檔] log=[Log檔] rows=300 errors=100");
...