2012年11月12日 星期一

改變Ubuntu中使用者家目錄下的預設資料夾名稱

忘記從哪一版的Ubuntu開始,只要選擇安裝繁體中文版的Ubuntu,則使用者的家目錄(/home/[user id])裡的預設資料夾,如「影片」「圖片」等,都會以中文名稱建立...從GUI介面來操作可能還不是大問題,但是如果是從console操作,就變得很麻煩了....

之前版本的Ubuntu還可以透過更改語系(繁體中文<->英文)的方式,觸發一個GUI程式,詢問是否改變這些預設資料夾的名稱。只要先切換到英文語系,就會詢問是否改成英文名稱,此時選擇「是」;然後再切換回繁體中文語系,一樣會再次詢問,此時只要選擇「保留舊名稱」,就可以在繁體中文環境裡有英文的預設資料夾名稱了

但是這招在Ubuntu卻不管用了...還好透過Google search,找到解決方法,而且感覺也蠻簡單的。步驟如下:

  1. 打開console視窗,先使用以下指令確認目前語系:echo $LANG
  2. 然後輸入export LANG=en_US,將語系變更為「英文」
  3. 接著輸入xdg-user-dirs-gtk-update,此時就會出現前述所提到的GUI的資料夾更名程式,然後選擇「更名」,就可以將預設資料夾改為英文
  4. 完成更名後,在console視窗中輸入export LANG=[步驟1記下的語系設定],然後再做一次步驟3,此時要選擇「保留舊名稱」,這樣就大功告成了!

2012年9月7日 星期五

Mac OSX Mountain Lion 使用心得與小抱怨

上個月升級到mountain lion,感覺是還不錯。不過似乎偶爾還是會有怪怪的情況。最讓我不滿的是發生過兩次莫名其妙的畫面錯亂,以及一次的整個系統無反應,最後這兩種情況都只能透過強制硬體重開機來回復。

另外,一點讓我覺得很討厭的,是在部分軟體升級版本之後,在Finder右鍵選單中的「打開檔案的應用程式」,會出現重複的項目。一直覺得很困擾,但是終於找到解法了。
方法就是在「終端機」裡執行以下命令:

/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -r -domain local -domain system -domain user

然後重啟Finder即可

不過對這次Mountain Lion其實還是有點失望,不是對功能失望,而是對穩定性方面感覺沒有之前Lion來的好。希望Apple再加油了!

2011年8月28日 星期日

JMX & Spring

用Spring要產生一個MBean並且註冊到MBeanServer是蠻容易的。基本上,幾乎只要使用XML設定就可以了。作法如下:
  1. 確定有使用context的XML schema。在XML設定檔中加入
    <context:mbean-server id="mbeanServer">
    , 其中id是用來表示該mbean server。這個xml tag是Spring 2.5以後多的,可以簡化設定。當然也可以用傳統的spring bean的定義方式:
    <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
  2. 加入RMI registry的宣告,一般來說使用JMX的remoting,在沒特別處理的情況,都是以RMI protocol來做通訊:
    <bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"><property name="port" value="1099"/></bean>
  3. 宣告MBean的connector server,這是用來讓外部可以連線到MBeanServer:
    <bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean">
    <property name="threaded" value="true"/>
    <property name="objectName" value="connector:name=rmi"/>
    <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi"/>
    </bean>
    ,其中,service url的定義跟JMX的定義跟格式是一樣的。
  4. 最後就是宣告MBeanExporter,然後指定要export的bean跟ObjectName:
    <bean id="mbeanExporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
    <property name="server" ref="mbeanServer"/>
    <property name="registrationBehaviorName" value="REGISTRATION_REPLACE_EXISTING"/>
    <property name="beans">
    <map>
    <entry key="heero:name=msService" value-ref="mobileSuitService"/>
    </map>
    </property>
    </bean>
而連線的方式,可以用一般標準的JMX client連線方式,或是使用Spring的方式。Spring的方式就是透過MBeanProxyFactoryBean來產生MBean的proxy。
最後,有幾點注意:
  1. mbean server的宣告,如果不是使用<context:mbean-server/>,則如果再產生mbean server發現已經有同id的server存在時,還是會繼續產生。所以可能會造成混淆。所以必須額外加上
    <property name="locateExistingServerIfPossible" value="true"/>
  2. 在實際上使用發現,如果有使用Hibernate跟Spring JMX support,則用傳統bean定義的方式產生mbean server,會一直警告該server已經存在。
  3. 經測試發現,當mbean server啟動時,立刻去連線會失敗,但是若是等待幾秒則OK
  4. 根據Spring文件,MBeanExporter是不可以lazy initialization的。所以必須設定為lazy-init="false"
這是最簡單容易的作法之一,在幾乎不改code的情況下就可以產生JMX的支援。當然Spring也有其他的作法,像是使用annotation。詳情就參考Spring文件。

Property file & Spring

Spring設定除了透過annotation跟xml之外,也可以透過property file來讀取。SpringFramework有提供這樣的機制。
首先,定義設定檔內容,例如:
(jmx.properties)
jmx.host=localhost
jmx.port=1099

然後在spring的xml設定檔內,先加入PropertyPlaceholderConfigurer的定義:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jmx.properties"/>
</bean>
其中,location是指要讀取的設定檔檔名與位置。範例中的寫法是指在classpath內找尋jmx.properties。
然後在需要使用的spring xml設定檔中,使用${property name}的方式即可。例如:
<bean id="example" class="...">
<property name="host" value="${jmx.host}"/>
<property name="port" value="${jmx.port}"/>
</bean>

2011年2月16日 星期三

Objective-C的類別初始化

在Java中,要對class variable作初始化,可以透過static method或是static block;而在Objective-C則是必須透過initialize。

在Objective-C中,物件的預設建構式為init,是用來對類別的單一物件作初始化。而除了這個method,其實還有另一個預設的初始化method,叫做"initialize"。這是一個static method,所以是針對class variable來做初始化的。

但是有幾點跟Java比較不同的:
  • Java的類別初始化,若是透過static method,則必須做明確的呼叫;但是Objective-C的initialize,則是會在該類別第一次載入時被自動呼叫(跟Java的static block較類似)。
  • Java的static block僅會被執行一次;Objective-C的initialize則是在父類別與子類別被載入時,會分別個執行一次。(若是實際上只有子類別被使用,則實際的載入動作會先載入父類別並執行initialize,然後再載入子類別與執行initialize)
因此,在使用initialize應該特別注意是否會被子類別進行重複呼叫。解決方法是在initialize執行時,檢查當時的類別是否為父類別或是特定類別,範例程式如下:
+ (void)initialize {
if(self == [XXXX class]) {
// initialize class variables here
}
}
其中,XXXX指的是父類別名稱。

Create an UUID by using Objective-C

許多computer language都有方法可以產生UUID,所以Objective-C當然也不例外。目前查詢到而且驗證過可用的方法有兩種:
  • 使用C function:使用以下程式碼即可
- (NSString *)createUUID{
// Create universally unique identifier (object)
CFUUIDRef uuidObject = CFUUIDCreate(kCFAllocatorDefault);
// Get the string representation of CFUUID object.
NSString *uuidStr = [(NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuidObject) autorelease];
CFRelease(uuidObject);
return uuidStr;
}

  • 使用NSProcessInfo 類別:使用以下程式碼即可
    NSString *uuid = [[NSProcessInfo processInfo] globallyUniqueString];
兩種方法都可以產生UUID,但是長度不一樣。NSProcessInfo因為參考比較多資訊來產生,所以產生的長度會比較長,為58個字元長度

Improve data upload speed on iPhone (for using ASIHTTPRequest)

在先前的文章就曾經介紹過使用在先前的文章就曾經介紹過使用ASIHTTPRequest來開發iOS上的HTTP通訊應用。它也的確讓coding變得比較簡單容易。不過,最近在實務上,卻碰到一個問題,就是當上傳大檔案或大量資料時,傳輸速率似乎不是很理想。經過一番股溝之後,發現在ASIHTTPRequest本身的API中,有相關設定可以改善。那就是透過static method
[ASIHTTPRequest setShouldThrottleBandwidthForWWAN:YES]
,來對流量作限制。事實上,該method的原意,似乎是在3G/GPRS網路下作流量管控的,不過API的說明也提到,對於大資料的上下傳也會有速度改善的效果。

但是,在不是很嚴謹的測試之後,發現該method的效果在大資料上傳才會比較明顯。對於下載,似乎不但沒有改善的效果,反而會減慢。而API文件也提到,使用該API應該盡量在需要的情況在開啟,否則平時應該是要設定在NO的狀態。但是,由於該method的設定效果是針對整個ASIHTTPRequest的,而非針對單一request物件,因此在不需要的情況下,必須明確的使用
[ASIHTTPRequest setShouldThrottleBandwidthForWWAN:NO]
來關閉功能。