熱門文章

2010年8月25日 星期三

BigPlanet SQLite Database Merger 0.1


前幾天有網友問說能不能將兩個 BigPlanet SQLite (*.sqlitedb) 離線地圖資料庫直接合併,由於 Mobile Atlas Creator 沒有這個功能,所以 Dr. TYT 寫了一個名為 BigPlanetSQLiteMerger 0.1 版的 Java 程式,讓大家可以直接合併兩個資料庫的內容。

[BigPlanetSQLiteMerger 快速上手]
  1. 下載 BigPlanetSQLiteMerger 0.1.zip 並解壓縮至某目錄下,例如 C:\BigPlanetSQLiteMerger\
  2. 將欲合併的兩個 BigPlanet SQLite (*.sqlitedb) 離線地圖資料庫移至 C:\BigPlanetSQLiteMerger\ 目錄內,也就是說和 BigPlanetSQLiteMerger.jar 位於同一個目錄。
  3. 將欲合併的兩個離線地圖資料庫改名為 source.sqlitedb 及 target.sqlitedb
  4. 點兩下執行 start.bat,將 source.sqlitedb 的內容合併至 target.sqlitedb 內。
    • 假如 source.sqlitedb 內有 10,000 個地圖圖檔,target.sqlitedb 內有 20,000 個地圖圖檔,而且這兩個資料庫共有 2000 個地圖圖檔重複,則執行 start.bat 進行合併後,source.sqlitedb 內容不變,還是有 10,000 個地圖圖檔,target.sqlitedb 則會有 20,000+(10,000-2,000) = 28,000 個地圖圖檔。
    • 如果您需要保留合併前的 target.sqlitedb (內有 20,000 個地圖圖檔),則請在合併之前先備份 target.sqlitedb

[BigPlanetSQLiteMerger.jar 進階參數說明]
共三個參數,第三個為選擇性參數。
sourceSQLiteDB targetSQLiteDB [BatchSize=1000]
* 一般使用:
---------------------------------------------- 
java -Djava.library.path=lib -jar BigPlanetSQLiteMerger.jar source.sqlitedb target.sqlitedb
----------------------------------------------
以上指令將 source.sqlitedb 內容合併至 target.sqlitedb,預設每 1000 筆資料合併一次。
* 進階版 (每 10,000 筆資料合併一次): 
----------------------------------------------
java -Xms64M -Xmx768M -Djava.library.path=lib -jar BigPlanetSQLiteMerger.jar source.sqlitedb target.sqlitedb 10000
----------------------------------------------
一旦 BatchSize 設越大,理論上合併速度越快,但執行時需要用越多記憶體,所以必須調整此參數 -Xmx768M,此參數表示 JVM 最多使用 768 MB 的記憶體,若這個數字不夠大,就有可能出現 Out Of Memory (記憶體不足) 的錯誤。


[BigPlanetSQLiteMerger.jar 執行過程]

以下為執行
java -Xms64M -Xmx768M -Djava.library.path=lib -jar BigPlanetSQLiteMerger.jar Google.Maps.Taiwan.sqlitedb Google.Maps.Japan.sqlitedb 10000
後,Windows 的命令提示字元 (Console) 顯示的內容。
======================================
=     BigPlanetSQLiteMerger v0.1     =
=  Powered by Dr. TYT's Android Map  =
=  http://android-map.blogspot.com/  =
======================================
--------------------------------------
Google.Maps.Taiwan.sqlitedb: 690672 KB
Google.Maps.Japan.sqlitedb: 1170577 KB
--------------------------------------
Total 195295 map tiles in Google.Maps.Taiwan.sqlitedb
adding map tiles 1~10000 of total 195295
adding map tiles 10001~20000 of total 195295
adding map tiles 20001~30000 of total 195295
adding map tiles 30001~40000 of total 195295
adding map tiles 40001~50000 of total 195295
adding map tiles 50001~60000 of total 195295
adding map tiles 60001~70000 of total 195295
adding map tiles 70001~80000 of total 195295
adding map tiles 80001~90000 of total 195295
adding map tiles 90001~100000 of total 195295
adding map tiles 100001~110000 of total 195295
adding map tiles 110001~120000 of total 195295
adding map tiles 120001~130000 of total 195295
adding map tiles 130001~140000 of total 195295
adding map tiles 140001~150000 of total 195295
adding map tiles 150001~160000 of total 195295
adding map tiles 160001~170000 of total 195295
adding map tiles 170001~180000 of total 195295
adding map tiles 180001~190000 of total 195295
adding map tiles 190001~195295 of total 195295
Total 407.031 seconds to add/ignore 195295 map tiles into Google.Maps.Japan.sqlitedb
--------------------------------------
Google.Maps.Taiwan.sqlitedb: 690672 KB
Google.Maps.Japan.sqlitedb: 1860343 KB
--------------------------------------

32 則留言:

  1. Dr. TYT 您好
    非常感謝您介紹這麼好用的軟體
    但是我在使用上出現了下面情形
    Unable to load sqlite_jni: java.lang.UnsatisfiedLinkError: C:\Users\tim\Desktop\
    BigPlanetSQLiteMerger 0.1\lib\sqlite_jni.dll: Can't load IA 32-bit .dll on a AMD
    64-bit platform
    是因為我是安裝64位元的系統所以無法執行合併嗎?
    有無辦法解決呢?

    回覆刪除
    回覆
    1. 另一個解決方法就是再安裝一個 x86 的 JRE,然後修改批次檔,指定使用 x86 的 java.exe

      刪除
  2. Hi, 番薯,

    BigPlanetSQLiteMerger 0.1.zip 壓縮檔內的 lib\sqlite_jni.dll 是給 32 位元 Windows 作業系統,且安裝 32 位元 Java 執行環境(JRE 或 JDK)的電腦使用的。
    您的情形應該是安裝了 64 位元 Java 執行環境,故請更換為 64 位元用的 sqlite_jni.dll
    跟當初幫 Mobile Atlas Creator 1.7 更換 sqlite_jni.dll 的方法是一樣的。
    您可以拿 Mobile_Atlas_Creator_1.7_SQLite.zip 檔案內的 Win x64 (64bit)/sqlite_jni.dll 來做替換。

    回覆刪除
  3. 先謝謝你的這些文章 ,有很完整的離線地圖資訊。
    另外請問一下,這個 合併的 java ,能不能換什麼 lib 讓 mac 可以執行?
    謝謝。

    回覆刪除
  4. Hi, sskes,

    MacOS 需要 sqlite.jar 搭配 sqlite_jni.jnilib

    TrekBuddy Atlas Creator 1.6.x 對應各種OS平台的 SQLite Native Libraries

    文章裡面有別人已經編譯好的檔案,你可以先試試看能不能用,不行的話我還有比較麻煩的備案。
    sqlite_jni_osx_10.4.tar.gz - Mac OS X 10.4

    回覆刪除
  5. Hi, tytung 你好,
    如蕃薯的問題,我已確定是64位元Windows用的sqlite_jni.dll,可是我仍然得到個錯誤訊息而無法合併,請問是我哪裡弄錯嗎?錯誤訊息如下,謝謝。
    Unable to load sqlite_jni: javalang.UnsatisfiedLinkError: D:\...\sqlite_jni.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform

    回覆刪除
  6. Hi, SHEVEN,

    你的作業系統曾經安裝過vcredist_2008嗎?
    http://android-map.blogspot.com/2010/02/mobile-atlas-creator-17.html?showComment=1280736985710#c2036935489835939843

    若沒有的話,請參考 "新版離線地圖製作軟體 Mobile Atlas Creator 1.7" 的[問題集錦],去下載安裝 vcredist_x64.exe

    回覆刪除
  7. 想請問一下版主,不知版主是否清楚RMaps單檔最大可到幾G,煩請解惑 多謝

    回覆刪除
  8. SD 卡為 FAT32 檔案格式,而這種檔案格式單一檔案最大只能 4GB
    至於 RMaps 能讀取多大的檔案,我想是取決於每隻手機的效能吧!

    回覆刪除
  9. 感謝作者的辛勞為大家寫了好用的離線程式
    想請問一下,我在室內不開啟GPS的環境下居然看不到地圖
    一定要使用GPS定位才看的到地圖嗎?已有自製Google maps
    並copy進去了

    回覆刪除
  10. Hi, 世啟,

    你下載的地圖範圍一定不夠大。
    加上沒有開啟GPS,手機不知道你的位置,所以不可能移動地圖到你所在位置。
    請下載世界地圖0~7,然後手動移動到你所在位置,再放大地圖。

    註:這篇標題是 BigPlanet SQLite Database Merger 0.1,跟離線地圖程式無關,下次請到正確的文章下發問,謝謝。

    回覆刪除
  11. 您好, 我想請問這個方式跟您之前在『新版離線地圖製作軟體 Mobile Atlas Creator 1.7
    』中所說的"2. 假設義大利離線地圖資料庫檔名為 Google.Maps.Italy.sqlitedb,請改名為 BigPlanet_maps.sqlitedb 並移回 \atlases\ 目錄裡,再次圈選 0-7 的世界地圖並執行 Create atlas,世界地圖就會合併至 BigPlanet_maps.sqlitedb,需要的話再改名回 Google.Maps.Italy.sqlitedb,這份資料庫就包含義大利與世界地圖了。"這兩種方式。
    有何不同?

    回覆刪除
  12. 另外,我執行這個start.bat後,出現了
    Exception in thread "main" java.lang.OutOfMemoryError: java heap space
    at SQLite.Vm.step(Native Method)
    at SQLite.Database.get_table(Database.java:367)
    at SQLite.JDBC2x.JDBCStatement.executeQuery(JDBCStatement.java:102)
    at SQLite.JDBC2x.JDBPreparedStatement.executeQuery(JDBCPreparedStatement.java:115)
    at tyt.sqlite.BigPlanetSQLiteMerger.a(Unknown Source)
    at tyt.sqlite.BigPlanetSQLiteMerger.main(Unknown Source)

    請問我該怎麼處理呢?
    感謝您的解答!再次感謝!

    回覆刪除
  13. Hi, 阿怪,

    使用 MOBAC 是只有一個 sqlitedb 檔,透過 MOBAC 新增地圖圖檔進去。

    這裡的 BigPlanetSQLiteMerger 是將兩個 sqlitedb 檔案合併,因此可以分別在不同電腦下載後再合併,不需要用到 MOBAC.

    OutOfMemoryError 表示記憶體不足,文章內已解釋過如何處理了。

    回覆刪除
  14. 您好,請問合併時如果重複的圖檔中其實是不同、有更新過的地圖,這樣是否不會更新為最新的圖檔。舉例來說,googlemap之前沒有蘆洲線的捷運,最近才把蘆洲線放上去了,請問我該怎麼更新地圖呢?是要全部重新下載,還是有其他替換的方法?我今天試了下載新的地圖,並讓sqlitedb檔名跟之前的檔名一樣(據說這樣可以只下載新的範圍),但是檔案放入手機後,還是地圖上沒有蘆洲線耶。不知道您是否知道原因?謝謝!

    回覆刪除
  15. sqlitedb地圖資料庫沒有紀錄時間,同一塊地圖圖檔,程式無法判別新舊,故還是要重新產生sqlitedb

    你下載過的捷運蘆洲線新地圖,則會暫存在 Mobile Atlas Creator 的tilestore\db-Google Maps 目錄,所以只需要重新產生包含蘆洲線的新sqlitedb,不需要再次下載蘆洲線。

    Mobile Atlas Creator 運作原理可參考 http://android-map.blogspot.com/2010/02/mobile-atlas-creator-17.html

    回覆刪除
  16. tytung您好,我看了您寫的運作原理,但可能我還是不太懂。您說「所以只需要重新產生包含蘆洲線的新sqlitedb,不需要再次下載蘆洲線」,然後我要怎麼辦呢?我目前的情況是半年前我已經下載好台北的地圖,也把sqlitedb放到手機裡了,運作一切正常。現在我為了把之前沒在地圖出現的蘆洲線放到地圖上,所以我圈選了台北蘆洲線的區域, 然後我把舊的sqlitedb檔名更名成新的,以讓新增的部分可以直接從舊的sqlitedb中新增,以免重複下載。結果sqlitedb容量的確比之前多了(我假設它有新增地圖進去了),但把這個sqlitedb放進手機後,卻還是沒有蘆洲線。我不知道我哪個步驟做錯了?煩請指教,謝謝!

    回覆刪除
  17. 只要你沒刪除 tilestore\db-Google Maps 目錄,半年前下載的地圖會存一份(假設500MB)在 db-Google Maps 目錄。

    你最近下載的蘆洲線會合併儲存至 db-Google Maps 目錄內(假設變510MB)

    你現在要做的就是移除 \atlases\BigPlanet_maps.sqlitedb 檔案。
    重新選好範圍,點 Create atlas,這時候 MOBAC 會產生新的 BigPlanet_maps.sqlitedb,並直接從 db-Google Maps 目錄(510MB)轉存地圖至 BigPlanet_maps.sqlitedb

    回覆刪除
  18. 您好,我下載地圖沒問題,但合併地圖時卻沒反應。我用win7(x64),也換過64 位元用的 sqlite_jni.dll,但按start.bat後,視窗顯示「java不是內部或外部命令、可執行的程式或批次檔,請按任意鍵繼續」。按了鍵之後視窗就結束了。請問,這需要怎麼解決呢?

    回覆刪除
  19. Hi, Mingdaa L,

    解決方法有二,擇一即可:一是設定環境變數,二是修改start.bat填入完整java路徑。

    1.設定環境變數。
    http://www.wretch.cc/blog/RYOUKA/12177229
    只要在Path"新增"你的Java安裝路徑即可。
    PS:千萬不要刪除Path裡原有字串,否則會造成無法開機。

    2.用記事本開啟start.bat,在java前面補上你的Java安裝路徑,例如C:\Program Files\Java\jdk1.6.0_26\bin\java

    回覆刪除
  20. 您好,我用第二種方法,start.bat裡最後一行改成C:\Program Files (x86)\Java\jre6\bin\java -Xms64M -Xmx512M -Djava.library.path=lib -jar BigPlanetSQLiteMerger.jar %SOURCE% %TARGET% pause。但是出現跟之前類似的文字:「'C:program'不是內部或外部命令、可執行的程式或批次檔,請按任意鍵繼續」。請問,這需要怎麼解決呢?感謝!

    回覆刪除
  21. 不能有空格,所以加雙引號即可。
    "C:\Program Files (x86)\Java\jre6\bin\java"

    回覆刪除
  22. 您好~
    merge 的時候完全沒有問題
    但是開啟的時候出現: "Error:disk I/O error: CREATE TABLE IF NOT EXISTS into AS SELECT MIN(z) AS minzoom, MAX(z) AS maxzoom FROM tiles"
    請問該如何解決?

    回覆刪除
    回覆
    1. 是否合併後的檔案太大呢?
      這個應該是RMaps更新索引(index)出現的錯誤。
      您試過BigPlanetTracks嗎?

      刪除
    2. 謝謝大大的回覆
      我的確是用RMaps開啟時遇到問題。
      而我用Samsung Galaxy Note 找 PlayStore
      找不到 BigPlanetTracks。
      請問是不是只提供給 iPhone使用者呢?
      還有請問如果使用RMaps的話,
      單檔最大允許容量為多少呢?

      刪除
    3. BigPlanetTracks沒上傳至GooglePlayStore,請直接從本站下載。
      http://android-map.blogspot.com/2011/07/big-planet-tracks-21-gps.html

      單檔最大允許容量取決於手機性能。
      有人測試說2GB是上限,但後來我實際用 HTC HD2 (1GB CPU)測試,3.9GB大的檔案在BigPlanetTracks及RMaps都可順利執行。

      RMaps首次載入新離線地圖時,需要建立索引會比較耗時。

      刪除
  23. 您好

    很感謝您寫了這個程式。在製作離線地圖時利用它真是方便太多了。

    不過,我碰到以下的問題:

    我分別下載了全世界(zoom level 0-7)和台灣8-14的兩個地圖
    然後用您的程式合併
    source是全世界,target是台灣
    結果在Android的RMaps上看時,一切正常
    但到了iOS的Galileo一看就不對了,只有target的tiles,看不到source的東西
    於是我把source和target對調,結果一樣是只看得到target

    我嘗試用去看sqlite裏面的table,有了有趣的發現:
    我一共用Mobile Atlas Creator下載了三個檔案(另有花蓮15-18)
    對每一個檔案都下這兩個sql指令
    select minzoom, maxzoom from info;
    select min(z), max(z) from tiles;
    結果如下表

    file minzoom maxzoom min(z) max(z)
    世界(0-7) 10 17 10 17
    台灣(8-14) 3 9 3 9
    花蓮(15-18) -1 2 -1 2

    顯然info.minzoom要等於tiles.min(z), 而info.maxzoom要等於tiles.max(z)
    但是minzoom如何對應到實際上的最小zoom level
    maxzoom如何對應到實際上的最大zoom level
    這我就看不出來了

    再開啟您的程式合併後的sqlitedb來看
    可以發現info中的minzoom, maxzoom都是取target檔合併前的值
    所以我就大膽把它手動改成minzoom=min(z), maxzoom=max(z)
    果然在Galileo中也可以正確顯示了

    回覆刪除
    回覆
    1. 謝謝您的測試並分享您找出的解決方法。
      當初 BigPlanetSQLiteMerger.jar 是寫給 BigPlanetTracks 用的,而 BigPlanetTracks 使用的 .sqlitedb 不需要 info 資料表內的 minzoom, maxzoom 欄位。

      換句話說,雖然 BigPlanetTracks 與 RMaps 共用 .sqlitedb,但只有 RMaps 需要 info 資料表,而當時開發 BigPlanetSQLiteMerger 時沒考慮 info 資料表。 (我也忘了 info 資料表何時被加進 RMaps)

      有空時我會加進 info 相關 SQL 指令,更換 libs 以支援各個作業系統,並釋出 BigPlanetSQLiteMerger 0.2 版。

      刪除
  24. 感謝版主的提供,這個程式真的太好用了...但現在我遇到一個問題了,就是合併完後發現,檔案太大了,請問版主有分割的程式嗎?謝謝囉!

    回覆刪除
    回覆
    1. 沒有,分割太複雜了,每個 SQLite 資料庫內的地圖範圍、縮放層級都不同,可以說是不可能分割的。

      刪除
    2. 喔喔,了解了...感恩囉!!

      刪除