程式碼高𠅙

2018/08/07

Firefox 網頁黑化擴充套件

黑色主題 (或稱夜間模式、深色模式、暗黑模式等) 的網站不但可降低視覺壓力,減少裝置耗電,更能營造一股駭客風格,是近來使用介面設計的流行趨勢。較具代表性的,像是 Youtube 及 Twitter 就各自為自己的網站加入深色模式及夜間模式。

而對於那些沒有支援黑色主題的網站,則可使用本文介紹的瀏覽器擴充套件來達到網頁黑化效果。以下介紹一些筆者曾經使用或試用過的 Firefox 網頁黑化擴充套件。

Dark Reader






在 Windows 底下配色切換效果良好,幾乎大部分的網站不太需要調整就能正常顯示。

但在 Android 底下不知為何無法正常套用--Ok! 後來查出原因是因為筆者在 Android Firefox 中使用了 User Agent Switcher 套件,更改了瀏覽器的 user agent 字串,而與 Dark Reader 相沖突。不過其實好奇的是背景反黑為何要偵測 user agent 字串啊!

可以針對每個網站設定套用深色配色、淺色配色,或是不配色。

配色的演算法內建有三種,還有一種讓您可以對每個網站套用自己的 style,這個功能可用來取代 stylish/stylus 等自訂網頁樣式元件。

不過可惜的是它的網站客製化 style 只能套用到 domain 層級,似乎是沒法對每個網站的子目錄撰寫自訂樣式。

Dark Background and Light Text





在更換為 Dark Reader 之前,原本是用這個套件,配色切換的效果也是很好,甚至可能是同類套件中最好的。

它也能對每個網站選用以下方式客製化:

  • Disabled - 不使用
  • Stylesheet processor
  • Simple CSS
  • Invert
  • Default


因 Dark Reader 在 Android Firefox 上無法正常執行,目前 Android Firefox 上仍是使用這個外掛。

要論這個套件有什麼缺點 ,其一是在 Chrome 上沒有相對的元件。

而其二… 應該是這個元件的 UI 做的比較醜一些,這是比較可惜的地方。


Midnight Lizard – Add-ons for Android





這曾經是我的最愛。設定畫面漂亮,客製化功能最強的網站樣式修改元件。

可惜網頁載入速度慢,CPU loading 高,且程式碼 syntax 語法未正常高亮,google calendar 未正常顯示,所以還是捨棄!

Dark Mode (WebExtension)




這個套件提供很多配色方案讓人選擇,經測試,不同的方案只是呈現的字型或背景色調略有不同,轉換異常的地方,套用不同的配色方案後經常還是異常。

而且配色方案並不能針對各別網站進行配置,而是所有網站共用同一種。所以假定 A 網站適合用甲方案呈現,而 B 網站適合乙方案呈現,那當由 A 網站切換到 B 網站瀏覽時,還得自行切換相對應的樣式,使用相當不便。

這個套件提供白名單的機制,讓無法正常套用配色的網站避免反黑,針對個別網站的客製化能力,也僅止於此了!

結論

目前筆者在桌機上,是使用 Dark Reader,因其 UI 較美觀,轉換效果不錯。但網路上有用戶反應 Dark Reader 會影響網頁載入效能,筆者在使用時,偶爾的確也會遇到瀏覽器提示 Dark Reader 的 Javascript 影響網頁載入速度。但因尚可忍受,也就繼續使用了。Dark Reader 另有 Chrome 版本,是個跨瀏覽器的套件。

Android Firefox 可使用擴充套件,所以還是可以透過擴充套件使網頁黑化,這是 Chrome Android 版所沒有的功能。在 Android 上筆者是採用 Dark Background and Light Text 這個套件。相較 Dark Reader,它在 Android 中執行效能較高,黑化的效果與 Dark Reader 難分軒輊!

如果網友想在 Android Firefox 中想使用 Dark Reader 套件,那記得避免使用 User Agent Switch 相關套件,並將 Dark Reader 的預設主題生成模式改成 "過濾+",如此才能使 Dark Reader 正常運作,並得到較佳效能。

2014/09/03

原來使用 Postgresql 就可以直接查詢文字或 CSV 檔案

有些時候,我們會需要處理資料內容龐大的文字檔案,我們可能想要先略微檢視資料內容,了解資料分佈,或做些過濾查詢的動作,當然把資料先匯入 Database 再進行處理是一個可行的方案,但如果資料量龐大到數十 GB,那麼光是匯入資料的時間,以及資料匯入 DB 後產生的資料澎漲就足以令人怯步。

要想維持文字或 CSV 檔案的簡便性,又想擁有資料庫查詢的方便性,可以透過 Postgresql Foreign Table for File 的功能來達成。簡單來說,Postgresql 的 Foreign Data Wrappers 能讓您包裝其他資料來源,然後透過一個集中的資料庫來操作,而這也就是 Federated Database 的觀念。



當我們在 Federated Database 下達 SQL 指令時,中央控管的 SQL 會透過 ANSI SQL 2003 的標準 SQL/MED (Management of External Data),將 SQL 指令進行拆解,交付各個外部資料來源 (或資料庫) 來執行。最後再由中央控管的資料庫,將資料匯集起來傳給使用者。詳情可參考底下兩個連結:
Postgresql 的 Foreign Data Wrappers 實際上是 Postgresql 資料庫的 Extension,其中 file_fdw 在 Postgresql 9.1 之後的版本已內建,可讓我們把外部的文字或 CSV 檔案,變成是 Postgresql 的 FOREIGN TABLE。筆者進行測試的版本為 Postgresql 9.3 版。

為了示範,請到 http://data.gov.tw/node/8792 下載 "每日各站點進出站人數.csv" 檔案。完成下載後將檔名更改為 stationflow.csv。

接下來以 pgAdmin 執行以下 SQL:
CREATE EXTENSION file_fdw;
CREATE SERVER file_fdw_server FOREIGN DATA WRAPPER file_fdw;
CREATE FOREIGN TABLE stationflow (
yyyymmdd  char(8),
stationcode  integer,
stationname  varchar(5),
input   integer,
output   integer
) SERVER file_fdw_server
OPTIONS (format 'csv', header 'true', filename 'D:/testdata/stationflow.csv', delimiter ',', null '');
這裡 filename 參數用來指向我們剛剛下載、更名的 stationflow.csv,可能需要修正目錄的正確性。

注意,目前 pgAdmin 並不會把 FOREIGN TABLE 顯示在左方的樹狀節點中,因此若要查詢系統中有哪些 FOREIGN TABLE, 可以執行以下指令:

select * from information_schema.tables where table_type = 'FOREIGN TABLE'
如果在此時執行 SQL, 如:
select count(*) from stationflow;
那應該會收到 Postgresql 提示的 UTF8 編碼錯誤的訊息。這是因為檔案其實是以 Big5 編碼,我們可以使用以下指令修正 FOREIGN TABLE 的檔案編碼:
ALTER FOREIGN TABLE stationflow OPTIONS ( encoding 'Big5' ); 
完成之後,您便可以正常執行 SQL 操作:
select count(*) from stationflow;
select * from stationflow where stationname like '台東%'; 
如果你有內部資料表,甚至可以來個內外 Join, Union 或 Sub-Query 等等:
select * from stationflow where stationcode in (select id from stationlist ); 
測試完成後,可用以下指令刪除外部資料表:
drop FOREIGN table stationflow;
這篇文章僅展示了 Postgresql 查詢文字或 CSV 檔案的功能,事實上 Postgresql 可以外接的資料來源還很多,包括 SQL Database、NoSQL Database、Http、Twitter、Hadoop 等,有興趣的同學可以自行至 PostgreSQL Extension Network 下載編譯測試。

2014/06/18

Java: JSON Library

Below is a list of major JSON format processing libraries for java. Check it out.

  • JSON Processing
    • Summary
      • JSR 353: Java API for JSON Processing - Reference Implementation
    • Comment
      • the java version official implementation
  • JSON in Java (json.org)
    • Summary
      • json.org official implementation
    • Comment
      • The API requires you to load the entire document into a String. This is somewhat cumbersome to use and inefficient for large documents. But it's a DOM model so you can get a lot done with very little code. 
  • Jackson JSON Processor
    • Summary
      • High-performance JSON processor.
    • Comment
      • Jackson ones to be the fastest json processing library in the old age.
      • Has many features with modules approach.
      • Jackson has grown into a huge collection of data type processing library
  • Boon JSON
  • google-gson 
    • Summary
      • A Java library to convert JSON to Java objects and vice-versa
    • Feature
      • Provide simple toJson() and fromJson() methods to convert Java objects to JSON and vice-versa
      • Allow pre-existing unmodifiable objects to be converted to and from JSON
      • Extensive support of Java Generics
      • Allow custom representations for objects
      • Support arbitrarily complex objects (with deep inheritance hierarchies and extensive use of generic types)
  • json-simple
    • Summary
      • JSON.simple is a simple Java toolkit for JSON. You can use JSON.simple to encode or decode JSON text. 
    • Feature
      • Full compliance with JSON specification (RFC4627) and reliable (see compliance testing)
      • Provides multiple functionalities such as encode, decode/parse and escape JSON text while keeping the library lightweight
      • Flexible, simple and easy to use by reusing Map and List interfaces
      • Supports streaming output of JSON text
      • Stoppable SAX-like interface for streaming input of JSON text (learn more)
      • Heap based parser
      • High performance (see performance testing)
      • No dependency on external libraries
      • Both of the source code and the binary are JDK1.2 compatible
    • Comment
  • genson - A fast & extensible Java <> Json library
    • Summary
      • Genson is an open-source library doing conversion from Java to Json and Json to Java. Genson targets people who want an extensible but also configurable, fast, scalable and easy to use library. 
    • Feature
      • Easy to use, fast, highly configurable, lightweight and all that into a single small jar!
      • Full databinding and streaming support for efficient read/write
      • Support for polymorphic types (able to deserialize to an unknown type)
      • Does not require a default no arg constructor and really passes the values not just null, encouraging immutability. It can even be used with factory methods instead of constructors!
      • Full support for generic types
      • Easy to filter/include properties without requiring the use of annotations or mixins
      • You can apply filtering or transformation logic at runtime on any bean using the BeaView mechanism
      • Genson provides a complete implementation of JSR 353
      • Starting with Genson 0.95 JAXB annotations and types are supported!
      • Automatic support for JSON in JAX-RS implementations
      • Serialization and Deserialization of maps with complex keys
    •  Comment
      • Looks good!
 Want to use XPath with JSON? see below.
  • Commons JXPath
    • Summary
      • The org.apache.commons.jxpath package defines a simple interpreter of an expression language called XPath. JXPath applies XPath expressions to graphs of objects of all kinds: JavaBeans, Maps, Servlet contexts, DOM etc, including mixtures thereof.  
  • json-path 
    • Summary
      • Java JsonPath implementation

2014/03/27

Java Practice: Shutdown Hook

今日 Daily Java Practice 如下,請問其中 runTime.addShutdownHook 的作用。

public class Main implements Runnable {
    public void run() {
        System.out.println("Shutting down");
    }

    public static void main(String[] arg) {
        Runtime runTime = Runtime.getRuntime();
        Main hook = new Main();
        runTime.addShutdownHook(new Thread(hook));
    }
}

2014/03/24

Java Practice: Enum

今天來玩玩 enum, 以下透過一程式,說明 enum 如何把物件導向程式的三個特質封裝、繼承跟多型完美的結合在一起。
善用 enum,可以大幅減少程式碼。
以下請說明:
  • 程式輸出訊息。
  • 為何輸出此訊息。
  • S, M, L, XL ... 與 Size 的關係,是類別跟實體的關係,還是父類別跟子類別的關係?

public class SizeIterator {
    public static void main(String[] args) {
        Size[] sizes = Size.values();
        for (Size s : sizes) {
            s.showName();
            s.showType();
        }
    }
}

enum Size {
    S {
        @Override
        public void showName(){
            System.out.println("I am too small to show to others!");
        }
    }, M, L, XL, XXL, XXXL;
    public void showName() {
        System.out.println(this.name());
    }
    public void showType() {
        System.out.println(this.getClass().getName());
    }
}

2014/03/19

Java Practice: Object Serialization

今天的 Java Practice 如下, 請服用:
  1. Coper 類別的功用為何?
  2. Coper:: <T> copyInstance(T obj) 方法使用了 Java Generic 的技巧,請解釋這裡採用型別參數的好處?
  3. main 方法中印出的兩個 User 物件,內容是否相同? 若有差異,原因為何?
abstract class Copier {
    @SuppressWarnings("unchecked")
    public static <T> copyInstance(T obj) throws IOException,
            ClassNotFoundException {
        ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
        ObjectOutputStream outStream = new ObjectOutputStream(outBytes);
        outStream.writeObject(obj);
        outStream.close();
        ByteArrayInputStream inBytes = new ByteArrayInputStream(outBytes
                .toByteArray());
        ObjectInputStream inStream = new ObjectInputStream(inBytes);
        T copied = (T) inStream.readObject();
        inStream.close();
        return copied;
    }
}

class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private Date date = new Date();
    private String username;

    private transient String password;

    public User(String name, String pwd) {
        username = name;
        password = pwd;
    }

    public String toString() {
        String pwd = (password == null) ? "(n/a)" : password;
        return "logon info: \n   username: " + username 
            + "\n   date: " + date
            + "\n   password: " + pwd;
    }
}

public class CopierTest {
    /**
     * @param args
     * @throws Exception
     * @throws IOException
     */
    public static void main(String[] args) throws Exception {
        User jack = new User("Jack", "magic");
        System.out.println(jack);
        User copyOfJack = Copier.copyInstance(jack);
        System.out.println(copyOfJack);
    }
}  

2014/03/18

Java Practice: Random


練習一下使用 Java Random 類別。
以下題目,請試著寫出最後 min, max 印出來的最可能數值。
public class MathRandomTest {
 public static void main(String[] args) {
    Random rand = new Random();
   
   int n = 10;
    int min = Integer.MAX_VALUE;
    int max = Integer.MIN_VALUE;
   
    for(int i = 0; i < 100; i ++){
      int r = rand.nextInt(n + 1);
      min = Math.min(min, r);
      max = Math.max(max, r);
    }
    System.out.printf("Min = %d, Max = %d", min, max);
 }
}