Amazon Ads

2015年4月28日 星期二

【分享】解決MacBook Pro 開機、關機變慢的問題

開機變慢


好像在上周更新過OS X Yosemite之後,開機就明顯變得很慢:


這裡無法確認更新是否為確切造成開機變慢的原因,只是剛好在此時間點後,狀況變得明顯。

一開始在網路上找到的解法,不外乎是「修復磁碟權限」、把不必要的「登入項目」關閉,或是清除桌面等,該試的都試過了,拜歐一開機等白蘋果出來前,還是要望著非常久的黑螢幕,想著為何會變這麼慢。

後來找到這串討論串:請問各位大哥 為什麼MBP 開機會變慢,六樓朋友的回應,解決了拜歐開機速度慢的問題。

拜歐是這樣做的,先到【系統徧好設定】,在下方倒收第二排有個【啟動磁碟】:


點進去後,在「請選擇要用來開機的系統」中,選擇要開機的硬碟後,再重新開機:


上面的做法解決了拜歐的問題,不禁猜想,會不會是兒子三不五時,找到機會就偷敲鍵盤造成設定跑掉的,XD

關機變慢


Google上打了「macbook pro 關機變慢」的關鍵字,第一筆出現這一篇:解決升上Yosemite-OS X10.10關機速度慢的問題,這位樓主分享了一篇在Apple Support Communities上討論到Slow shutdown on Yosemite的問題。

這個提到MacBook Pro會變慢的原因,可能是有裝舊版本的Parallels Desktop,受其影響的關係,拜歐的MacBook Pro也有裝,心想,有可能是這個原因。

其解決方法提到,要到~/Library/LaunchAgents~/Library/LaunchDaemons把有「parallels」字眼的檔案都清掉,在拜歐的電腦中只找到~/Library/LaunchAgents這個資料夾,而就索性把~/Library/LaunchAgents裡面的檔案全刪了,果然,關機就感覺有恢復跟原來一樣的速度,而Parallels Desktop也能正常運作。

請注意,這解決了拜歐的問題,不一定適用看倌您的情境,請在刪不知用途的檔案前,請三思而後行XDD

討論串中還有一位仁兄提到~/Library/Preferences這個資料夾中和「parallels」有關的檔案也要刪,這裡面的拜歐沒動,就不知道有沒有助益了。


2015年4月25日 星期六

【筆記】在PHP中太長的數字以科學符號(scientific notation)顯示的解決方案

寫過PHP的人一定遇到,過長的數字echo出來後,非所預期地以科學符號顯示的問題,如:
$f1 = 201504242111234; 
$f2 = 201504191213211;

echo $f1 . ',' . $f2;
一般預期的結果應該為:
201504242111234,201504191213211
但實際上,結果可能為:
2.0150424211123E+14,2.0150419121321E+14
這時若只是要在網頁上顯示所要的格式,可以使用printf(文件)這個方法,它的用法是:
int printf ( string $format [, mixed $args [, mixed $... ]] )
其中,第一個參數為要印出的格式設定,詳細說明可以參考這裡

據此,可以把上面echo的這一行替換成下面程式:
printf('%.0f,%.0f', $f1, $f2);
這裡%.0f的意思是說,以浮點數的格式去顯示後面傳入的參數,在其中的0是指小數點後要顯示的位數為「0」。

另外,因為%.0f有兩個,後面要傳入對應的兩個浮點數。

有時,在一些情況下需要在程式中將兩個浮數數串在一起,好讓後面的程式使,這時就要使用到sprintf(文件)這個方法:
string sprintf ( string $format [, mixed $args [, mixed $... ]] )
從上面可以看到,它回傳的是一個字串,所以可以這樣使用:
$s1 = sprintf('%.0f', $f1);
$s2 = sprintf('%.0f', $f2);

$s3 = $s1 . ',' . $s2;

//$s3有可能有其他如做為SQL的運用
//這裡僅把它印出來
echo $s3;

【分享】學習正規表示式(Regular Expression)的資源

Regular Expression翻做中文為正規表示式,又稱正則表達式、正規表示法、正規運算式、規則運算式、常規表示法(wiki),在此拜歐習慣使用正規表示式這個翻譯,因為它唸起來最順,XD。

之前斷斷續續地涉略或鑽研正規表示式的用法,期間也找到一些在網路上覺得不錯的資源,因此在此記錄與分享。

OCPSoft


OCPSoft是一群喜好開放原始碼開發者的組織,在它的網站上找到兩篇講述Java和正規表示式的教學資源。

Guide to Regular Expressions in Java (Part 1)


Guide to Regular Expressions in Java (Part 2)

2015年4月24日 星期五

【筆記】在JavaScript中使用正規表示式擷取目標字串

(function(){

 var input = '1990Mar02Taipei35';

 var num = /(\d+)\D+(\d+)(\D+)(\d+)/g;
 
 var result = num.exec(input);

  console.log(RegExp.$1 + ' 年在 ' + RegExp.$3 + ' 的數值是: ' 
              + RegExp.$4);

})();

【筆記】在Java中使用正規表示式(Regular Expression)切割字串

在工作上若碰到要在一行字串去擷取資料時,如下面記錄某年某月某日某地區的某個數值:
1990Mar02Taipei28
常是以substring算好位置去截取各個資料,若有時可能應程式更新造成了一些例外,如上面的月份是英文簡寫,但程式更新後,記錄月份的方式變成:
1991March03Tainan35
這時若再用substring來切字串,就可能要做一些判斷來算位置。

當每一行資料的模式都是一樣時,如上面兩筆資料,都是數字、英文字、數字、英文字、數字時,就可以使用Pattern(文件)搭配Matcher(文件),以正規表示式來切字串:
package idv.jk.util.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MatcherTest
{
    public static void main(String[] arv)
    {
        String input = "1990Mar02Taipei28\r\n1991March03Tainan35";
        Pattern pattern = Pattern.compile("(\\d+)(\\D+)(\\d+)(\\D+)(\\d+)",
                                            Pattern.MULTILINE);

        Matcher matcher = pattern.matcher(input);

        while(matcher.find())
        {
            System.out.println("The value at " + matcher.group(4) +
                                    " in " + matcher.group(2) +
                                    " " + matcher.group(1)+
                                    " is " + matcher.group(5));
        }
    }
}
結果為:
The value at Taipei in Mar 1990 is 28
The value at Tainan in March 1991 is 35
上面範例用簡單的資料,來說明正規表示式的功用,在現實的工作上,資料模式通常都複雜許多,但若能熟悉正規表示式並應用得當,在檔案處理上必能得心應手。

若想進一步鑽研,可以考慮這一本:


它也有中文版,XD

2015年4月22日 星期三

【筆記】在Ubuntu 14.04.2 Server安裝Redis(版本3.0.0)

Redis目前官方有支援的版本就是Linux-based的作業系統,在這裡拜歐是在Ubuntu 14.04.2 Server安裝Redis,版本為3.0,先到這裡下載Redis

在終端機中,輸入下列指令下載:
wget http://download.redis.io/releases/redis-3.0.0.tar.gz
下載完成後,將其解壓縮:
  
tar xzv -f redis-3.0.0.tar.gz
進入redis-3.0.0目錄中執行make指令:
 
cd redis-3.0.0
make 
若顯示找不到make指令的訊息,請執行下列指令進行安裝:
 
sudo apt-get install make
再來若遇到下列錯誤訊息:
/bin/sh: 1: cc: not found
make[1]: *** [adlist.o] Error 127
make[1]: Leaving directory `/home/javakid/tools/nosql/redis-3.0.0/src'
make: *** [all] Error 2
這裡要注意的是第一行的訊息,若是出現這個訊息,請執行下列指令進行安裝:
 sudo apt-get install build-essential
若有什麼檔案找不到的,如下列訊息:
In file included from adlist.c:34:0:
zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory
 #include <jemalloc/jemalloc.h>
                               ^
解決辦法只要去把缺的檔案make出來:
cd deps 
make jemalloc
然後再回到redis-3.0.0目錄,再執行make

若是有再遇到下列訊息:
cc: error: ../deps/hiredis/libhiredis.a: No such file or directory
cc: error: ../deps/lua/src/liblua.a: No such file or directory
make[1]: *** [redis-server] Error 1
make[1]: Leaving directory `/home/javakid/tools/nosql/redis-3.0.0/src'
make: *** [all] Error 2
一樣先到deps執行,把缺的檔案make出來:
cd deps
make hiredis lua jemalloc linenoise
完成後,再回到上一層再執行make
cd ../
make
make執行完畢後,執行下列指令,開始執行指令啟動Redis
 src/redis-server

2015年4月15日 星期三

【筆記】在Java中爬取網頁內容-使用jsoup來做html parser

日前因工作上的需要,寫Java程式去爬網頁,爬回來的網頁要去解析出要用的資料,拜歐發現jsoup這個函式庫非常好用,在這裡簡單介紹一下。

在這裡,拜歐要把Google新聞首頁的標題都爬回來,先找到包含標題的HTML標籤裡,可以辨別的屬性,如:


從上面可以看到要包著標題的是span標籤,而且它有一個名為titletextCSS類別,所以使用jsoup函式,可以這樣做:
package idv.jk.web.parser;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.Iterator;

/**
 * Created by Javakid on 2015/4/14.
 */
public class HtmlParserMain
{
    public static void main(String[] argv)
    {
        String url = "https://news.google.com.tw/news";
        try {
            Document doc = Jsoup.connect(url).get();
            System.out.println(doc.title());
            Elements h1s = doc.select("span.titletext");

            Element thisOne = null;
            for(Iterator it = h1s.iterator(); it.hasNext();)
            {
                thisOne = (Element)it.next();
                System.out.println(thisOne.html());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

上面的程式碼中,在第20行先把該網址的網頁內容取回,並且將其封裝成一個org.jsoup.nodes.Document類別的物件。

在第21行呼叫title方法,將該頁的抬頭(title)印出來。

在第22行使用選擇器查詢(selector query)來挑出所要的元素,這裡span.titletext挑選的出來的是class屬性為titletextspan標籤。

撰擇器的語法可以參考這裡,若是熟悉jQuery,一定會覺得一模一樣XD。

然後在第28行把其內含的HTML內容印出來。

結果如下:
Google 新聞
毛揆:尊嚴、公平是加入亞投行最高原則| 聯合影音
入亞投行金額朱立倫:非台灣說了算
加入亞投行毛揆:決定權仍在我方
毛治國:亞投行創始章程無法容納台灣
肺癌躍居10大癌症第二女性患者激增
大腸癌7度居冠子宮頸癌首脫離十大排行
每5分26秒就有1人罹癌大腸癌連7年居首位
十大癌症排行!腸癌7度奪冠最兇猛女性肺癌變多
博科聖地猖狂綁架逾2000女性
被博科聖地擄走50少女據報仍生存
(以下省略)

2015年4月9日 星期四

【筆記】在Java中去除字串的空白字元(字串去空白)

Java若只是要去除字串前後的空白,最簡單的方式就是呼叫String類別中trim這個方法:
String input = " Hello World ";
input = input.trim();
System.out.println(input);
但若是字串中的空白字元呢?

有用Java處理過字串的人,都應該有使用String類別中replaceAll這個方法,來替換字串中的某些字元,其實去仔細看它的API文件後,可以看到傳入這個方法的第一個參數是一個正規表示式,所以可以用正規表示式的來尋找要替換的部份。

所以若在要在 Java程式中把所有的空白字元,包含\t\n\x0B\f\r或空格等空白字元去除,比如現在有個字串如下:
String oldString = " Hello\t\tHello\r\nWorld";
System.out.println(oldString);
則輸出結果為:
  Hello      Hello
World
可以使用如下的正規表示式把上列字串中的空白字元去掉:
String newString = oldString.replaceAll("\\s+", "");
System.out.println(newString);
則輸出結果為:
HelloHelloWorld
而再次看到文件中的說明,其實上列replaceAll這個方法的結果,就跟下列方式相同:
String oldString = " Hello\t\tHello\r\nWorld";
String newString = Pattern.compile("\\s+").matcher(oldString)
                       .replaceAll("");
System.out.println(newString);

【筆記】PHP去除字串的空白字元(字串去空白)

PHP中,是有內建一個trim的方法來去除頭尾的空白,但若要去除字串中的空白呢?這時通常會用字串替換的方式把空白替換成空字串,如下:
//H之前空一格,o與W之間有兩個空格,在d後面又有一個空格
$str = ' Hello  World ';
echo 'head' . str_replace(' ', '', $str) . 'tail';
結果為:
headHelloWorldtail
由上面的結果可知,若在PHP中只是要去掉空格,使用str_replace就夠了,但若在字串中除了空格,還有其他如\t\v\n等的空白字元呢?如下:
//H前面一個空格,但o與W之間還有d後面是Tab
$str = ' Hello World ';
echo 'head' . str_replace(' ', '', $str) . 'tail';
若依str_replace的方法,這裡只能把空白去掉,而其他字元仍會留著,如下面結果:
headHello World tail
這時,要使用preg_replace來搭配正規表示式去除:
echo 'head' . preg_replace('/\s+/', '', $str) . 'tail';
結果為:
headHelloWorldtail
上列的\s+表示只要是有一個以上的空白字元就符合被替換的條件,其意義和符合的字元,可以參考這裡

參考資料

2015年4月8日 星期三

【雜志】人的格局


一個人的格局,決定一個人的世界有多高、多廣。

放大格局,別在意小事。

也別去批判別人的小格局。

也許,別人的格局是不同形狀,

而我只是站在比較窄的這邊看過去。

2015年4月7日 星期二

【筆記】解決Android Studio中Gradle DSL method not found: 'runProguard()'的錯誤

今天開啟好久沒用的Android Studio再更新後,引入一個之前練習用的專案,突然出現下列的錯誤訊息:


於是用下面的片段當關鍵字去搜尋解法:
Gradle DSL method not found: 'runProguard()'
發現原來是Gradle版本的關係,因為runProguard這個方法從Gradle版本0.14.0後,就改名為minifyEnabled

解決方法就是先開啟build.gradle這個檔案:


開啟後,找到下列程式碼:
runProguard false
把他改成
minifyEnabled false

參考資料

【筆記】使用Commons lang中的StringUtils來處理字串

Apache Commons是一個專注於提供可重覆利用的Java元件,其中,好幾個元件在拜歐在工作中開始用Java開發專案,就常用到。

其中 Commons Lang這一元件中,針對了字串、數值,還有物件建立與序列化等等,提供了更多的方法,以補足標準java.lang API的不足之處。

好像不管使用什麼語言,在程式要處理字串的地方,是常常看到的,在 JavaString類別本身就提供了很多來處理字串的方法,但在使用這些方法時,也常都要先判斷String物件是否為null再做呼叫,有時會程式失去的易讀性,如要判斷一個String物件是否為空白字串(""),一般會這樣寫:
if(input != null && input.equals(""))
        
//OR
if("".equals(input))
但若使用StringUtils類別的話,可以呼叫isEmpty這個方法來判斷:
if(StringUtils.isEmpty(input))
//StringUtils.isEmpty(null) 回傳true
//StringUtils.isEmpty("")   回傳true
//StringUtils.isEmpty(" ")  回傳false
這樣不只省了一些程式碼,而且也大大地提升了程式的易讀性。

StringUtils類別中實作了很多方便用來處理字串的方法,這裡再介紹一個拜歐覺得用過來切分字串是非常方便的方法:splitByWholeSeparatorPreserveAllTokens,詳細的文件,可以參考這裡

1,2,,4,5,,若用,去切,在有些情況下,會希望結果是1、2、空白、4、5和空白,先用String的內建的split方法去切:
String input = "1,2,,4,5,";
String[] peices = input.split(",");
System.out.println("字串陣列的長度為: " + peices.length);
System.out.print("字串陣列內的元素為: ");
System.out.print(Arrays.asList(peices));
結果為
字串陣列的長度為: 5
字串陣列內的元素為: [1, 2, , 4, 5]
從上面來看,最後一個空白不見了,這不符合原先預期的結果。這時若使用splitByWholeSeparatorPreserveAllTokens這個方法去切:
String input = "1,2,,4,5,";
String[] peices = StringUtils.splitByWholeSeparatorPreserveAllTokens(input, ",");
System.out.println("字串陣列的長度為: " + peices.length);
System.out.print("字串陣列內的元素為: ");
System.out.print(Arrays.asList(peices));
結果就會如希望地呈現:
字串陣列的長度為: 6
字串陣列內的元素為: [1, 2, , 4, 5, ]
若對其實作有興趣,建議可以下載它的原始檔來瞧瞧。

在使用Commons Lang元件時,有一個小地方要注意的是,它到版本 3.0以後,在套件名稱上有點差異,在3.0以前,套件名稱為org.apache.commons.lang,而之後的套件名稱為org.apache.commons.lang3,這有時是為什麼明明有把函式庫引入,但卻編譯錯誤的原因!

2015年4月4日 星期六

【筆記】Java把長整數拆成一個一個數字

今天同事跑來問拜歐,如何把一個long型態的長整數,比如說,把5678拆成5678等四個數字要怎麼做,其實先把長整數使用String.valueOf轉成字串,再使用String類別中的charAt就可以輕鬆辦到。
package idv.jk.util.lang;

public class LongUtils
{
    public static int[] spitLongToIntArray(long inNumber)
    {
        String strNumber = String.valueOf(inNumber);

        int length = strNumber.length();
        int[] results = new int[length];

        for(int i = 0; i < length; i++)
        {
            results[i] = Character.getNumericValue( strNumber.charAt(i) );
        }

        return results;
    }

    //test
    public static void main(String[] argv)
    {
        for(int i : spitLongToIntArray(5678))
        {
            System.out.print(i + ",");
        }
    }
}
執行結果如下:
5,6,7,8,
這裡要注意的是,若傳入的是負數,字元-經由Character.getNumericValue,關於該方法更詳細的說明,可以參考Java文件,如傳入-5678,執行結果則為:
-1,5,6,7,8,
若有處理負數的需要,則需多加一些處理。

2015年4月1日 星期三

【筆記】在Linux中使用指令來查看資料夾與子資料夾中的檔案數量

Linux中,若要下指令去查看在某個目錄下的檔案,可以用findwc這個兩個指令搭配來達成。

比如說,現在有一個/home/javakid/temp/的資料夾,其中有一個名為6.txt的檔案,以及abc三個資料夾,分別各有2、2、1個檔案,如下圖所示:


開啟終端機後,輸入下列指令:
find /home/javakid/temp -type f
結果顯示如下:


檔案很少時,很容易看出來有幾個檔案,但其中包含的檔案很多時,在終端機一行一行地數,好像就不是很聰明的做法,還有很大的機會數錯。

那如果像下列指令一樣,先把結果輸出到檔案,再看檔案內的行數,好像又有一點點「搞剛」:
find /home/javakid/temp -type f > ../count.txt
拜歐查到最好的做法是,再搭配wc指令:
find /home/javakid/temp -type f | wc -l
上列的意思可以想像為,將find且用-type f找出目錄與子目錄下的檔案,再把輸出的結果,用|傳給wc這個指令,指定-l參數,表示僅列出行數。

若想進一步了解findwc的用法,可以輸入
find --help

wc --help
你也會發現鳥哥的教學網站是座寶山。

最後插一句,寫程式的要進一流的軟體公司,Linux shell是必學的,若真想學好,推薦這本:


參考資料