2016年9月10日 星期六

Unity內使用WebClient和Stream方式來下載遠端檔案

一般Unity下載遠端檔案,大家都是用WWW的方式來做;但是WWW的結果是將下載的檔案直接匯入到Unity內,沒有辦法放在外面,要放在外面還得自己事後存出去,像是文檔或圖片等,那如果下載的是AssetBundle怎麼辦?光想就覺得很麻煩......

當然Unity有WWW.LoadFromCacheOrDownload這樣的方式,但我想要的是更直接地把下載檔案放在外部,之後自己比對是否需要再次下載覆蓋或可直接本地端匯入,因此就來尋找了一般的下載方式。

找到的有WebClient和Stream兩種方式。WebClient很簡單,可說是一口氣就能搞定的輕鬆方式,但是如果是在Unity內用的話,當下載檔案的量大時,程式就會卡在那沒法做其它事了,所以我個人會比較傾向使用Stream的方式,只是程式碼就沒那麼簡便了。

--------------------------------------------------------------------------------------------------------

WebClient:
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Net;
  4.  
  5. public class WebClientController : MonoBehaviour {
  6.  
  7.     void Start ()
  8.     {
  9.         WebClient webClient = new WebClient();
  10.  
  11.         try
  12.         {
  13.             webClient.DownloadFile( "http://localhost:8080/xxx.assetbundle", "D:/xxx.assetbundle" );
  14.         }
  15.         catch( Exception ex )
  16.         {
  17.             Debug.Log( ex );
  18.         }
  19.     }
  20. }
雖然我想一併使用下載過程的檢視,但是這部分的效果就是出不來,只好先記錄程式碼,日後有空再來試。
  1. webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler( WebClient_DownloadProgressChanged );
  2. webClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler( WebClient_DownloadDataCompleted );
  3.  
  4. void WebClient_DownloadProgressChanged( object sender, DownloadProgressChangedEventArgs e )
  5. {
  6.     Debug.Log( "下載" + e.ProgressPercentage + "%" );
  7. }
  8.  
  9. void WebClient_DownloadDataCompleted (object sender, DownloadDataCompletedEventArgs e)
  10. {
  11.     Debug.Log( "下載完成" );
  12. }
--------------------------------------------------------------------------------------------------------

Stream:
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Net;
  4.  
  5. public class WebClientController : MonoBehaviour {
  6.  
  7.     HttpWebRequest httpWebRequest;
  8.     HttpWebResponse httpResponse;
  9.     System.IO.Stream dataStream;
  10.     byte[] buffer = new byte[8192];
  11.     int size = 0;
  12.     float downloadMemory = 0;
  13.     bool completeCheck = false;
  14.  
  15.     void Start ()
  16.     {
  17.         try
  18.         {
  19.             httpWebRequest = (HttpWebRequest)WebRequest.Create( "http://localhost:8080/xxx.assetbundle" );
  20.             httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
  21.             dataStream = httpResponse.GetResponseStream();
  22.             fileStream = new FileStream( "D:/xxx.assetbundle", FileMode.Create, FileAccess.Write );
  23.  
  24.             downloadMemory = 0;
  25.         }
  26.         catch( Exception e )
  27.         {
  28.             Debug.Log( e );
  29.         }
  30.     }
  31.  
  32.     void Update ()
  33.     {
  34.         if( completeCheck == false )
  35.         {
  36.             try
  37.             {
  38.                 size = dataStream.Read( buffer, 0, buffer.Length );
  39.  
  40.                 if( size > 0 )
  41.                 {
  42.                     fileStream.Write( buffer, 0, size );
  43.                     downloadMemory += size;
  44.                     Debug.Log( "正下載 " + ( downloadMemory / 1048576 ).ToString( "f1" ) + "MB / " +
  45.                                 ((float)httpResponse.ContentLength / 1048576 ).ToString( "f1" ) + "MB == " +
  46.                                 (( downloadMemory / (float)httpResponse.ContentLength ) * 100 ).ToString( "f1" ) + "%" );
  47.                 }
  48.                 else
  49.                 {
  50.                     fileStream.Close();
  51.                     httpResponse.Close();
  52.                     buffer = new byte[8192];
  53.  
  54.                     Debug.Log( "下載完成!" );
  55.  
  56.                     completeCheck = true;
  57.                 }
  58.             }
  59.             catch( Exception ex )
  60.             {
  61.                 Debug.Log( ex );
  62.             }
  63.         }
  64.     }
  65. }
--------------------------------------------------------------------------------------------------------

Unity內用WWW載入AssetBundle

大家都知道,AssetBundle是Unity用來打包資源的方式。
大家也知道,AssetBundle對於Script的不方便,一定要在Project內事先放入相同的Script,才能讓AssetBundle上的Script相對應到。

但這都不是重點,本篇的重點是將AssetBundle匯入到Unity程式內使用。
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class AssetBundleLoadController : MonoBehaviour {
  5.  
  6.     void Start ()
  7.     {
  8.         StartCoroutine( LoadAssetBundle() );
  9.     }
  10.  
  11.     private IEnumerator LocalLoad()
  12.     {
  13.         WWW fileBundle = new WWW( "file://D:/xxx.assetbundle" );
  14.         yield return fileBundle;
  15.  
  16.         GameObject tempObject = null;
  17.         yield return tempObject = Instantiate( fileBundle.assetBundle.mainAsset ) as GameObject;
  18.         tempObject.name = tempObject.name.Replace( "(Clone)", string.Empty );
  19.  
  20.         fileBundle.assetBundle.Unload( false );
  21.         Resources.UnloadUnusedAssets();
  22.     }
  23. }
這樣就能使用AssetBundle的內容物了。

2016年9月2日 星期五

開發時,Java的版本設定......

在使用Eclipse、Tomcat等時,很怕Java的JDK、JRE等版本不相對,或是出現"Unsupported major.minor version 52.0"之類的訊息,這時就得去挖所有相關的環境設定,我也被這情況弄過幾次,所以在此記錄一下。

確認執行Tomcat的電腦使用的Java版本,通常可以從控制台的解除安裝程式來看,但是也許你會安裝好幾個版本的Java版本在裡面,所以用CMD來看比較妥當,這樣才能確認電腦到底是使用哪個版本的Java,分別輸入"java -version"和"javac -version",就可以看到結果:


再來是Eclipse內,一般大家都知道的是Project內的Library引用設定,在Project上用滑鼠右鍵開起選單,選擇"Properties":


然後在左邊選擇"Java Build Path",來觀看Libraries內的JRE版本:


但其實還有其它地方也和Java版本有關係,一個是"Java Complier"的"Compiler compliance level":


另一個是"Project Facets"的設定,這些都和Java版本有關:


以後應該不會再被Java版本這種設定給弄到了。


2016年8月29日 星期一

使用Java取得當前JSP的名稱

我需要取得JSP、當前網頁的名稱,因此搜尋了一下做法;原先以為有this之類的方式可取得,結果是使用request取得網址,再過濾出名稱。
  1. String uri = request.getRequestURI();
  2. String pageName = uri.substring( uri.lastIndexOf( "/" ) + 1 );
這樣就可取得網址和過濾後的網頁名稱,蠻好用的。

2016年8月25日 星期四

Javascript內使用PostMessage在網頁間傳輸資料

目前我知道三種在網頁間傳輸資料的方式:jsp:include的jsp:param、iframe本身的傳值、和PostMessage,當然還有很多其他傳輸的方式。PostMessage看起來受到的限制最少,也可以在很多不同情況下運用,所以現下會使用它。

假設有兩個網頁:aaa.jsp和bbb.jsp,然後從AAA.jsp傳輸資料到BBB.jsp內。

--------------------------------------------------------------------------------------------------------

aaa.jsp的內容:
  1. <%@ page language="java" contentType="text/html; charset=BIG5" pageEncoding="BIG5"%>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  3. <html>
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=BIG5">
  6. <title>AAA</title>
  7. </head>
  8. <script type="text/javascript">
  9.  
  10.     function sendMessage()
  11.     {
  12.         var menu = document.getElementById( "bbbID" ).contentWindow;
  13.  
  14.         menu.postMessage( document.getElementById( "messageID" ).value, 'http://localhost:8080' );
  15.     }
  16.  
  17. </script>
  18. <body>
  19.     <iframe src = "bbb.jsp" id = "bbbID" frameborder = "1" scrolling = "auto"></iframe>
  20.  
  21.     <form>
  22.         <input type = "text" id = "messageID" value = "">
  23.         <input type = "button" value = "傳送訊息給bbb" onclick = "sendMessage()">
  24.     </form>
  25. </body>
  26. </html>
--------------------------------------------------------------------------------------------------------

bbb.jsp的內容:
  1. <%@ page language="java" contentType="text/html; charset=BIG5" pageEncoding="BIG5"%>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  3. <html>
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=BIG5">
  6. <title>Insert title here</title>
  7. </head>
  8. <script type="text/javascript">
  9.  
  10.     function getMessage( event )
  11.     {
  12.         if( event.origin != 'http://localhost:8080' )
  13.         {
  14.             alert( event.origin );
  15.  
  16.             return;
  17.         }
  18.  
  19.         document.getElementById( "receiveID" ).innerHTML = event.data;
  20.     }
  21.  
  22.     if( typeof window.addEventListener != 'undefined' )
  23.     {
  24.         window.addEventListener( 'message', getMessage, false );
  25.     }
  26.     else if( typeof window.attachEvent != 'undefined' )
  27.     {
  28.         window.attachEvent( 'onmessage', getMessage );
  29.     }
  30.  
  31. </script>
  32. <body>
  33.     <h1>這是bbb!</h1>
  34.     <div id = "receiveID">等待接收訊息!</div>
  35. </body>
  36. </html>
--------------------------------------------------------------------------------------------------------

aaa.jsp內的postMessage有兩個參數,前面是要夾帶的資料,後面是傳送的網域;然後在bbb.jsp內可以用event.origin來判斷網域是否相符,是個保險機制。如果不需要這層保險機制,可以將後面的參數設為'*',這樣接收端也可以不用進行檢查。

例如在aaa.jsp內將
  1. menu.postMessage( document.getElementById( "messageID" ).value, 'http://localhost:8080' );
改為
  1. menu.postMessage( document.getElementById( "messageID" ).value, '*' );

然後在bbb.jsp內將
  1. function getMessage( event )
  2. {
  3.     if( event.origin != 'http://localhost:8080' )
  4.     {
  5.         alert( event.origin );
  6.  
  7.         return;
  8.     }
  9.  
  10.     document.getElementById( "receiveID" ).innerHTML = event.data;
  11. }
改為
  1. function getMessage( event )
  2. {
  3.     document.getElementById( "receiveID" ).innerHTML = event.data;
  4. }
--------------------------------------------------------------------------------------------------------

而之所以會同時使用addEventListener和attachEvent,是因為以前各大瀏覽器不一定會支援addEventListener,現在如何我是不知道啦......因此先檢查addEventListener能不能用,不行再用attachEvent。

網路上可找到許多關於addEventListener和attachEvent的詳細解釋,不需要我這個外行人做粗淺的說明了。

2016年8月2日 星期二

在Java和JavaScript內的HashMap用法

HashMap在寫程式時很常使用,還有一種兼具順序的LinkedHashMap存在;這邊要講的是在Java和JavaScript內要使用時,兩者不一樣的地方。

在Java內:
  1. HashMap<String, String> testHashMap = new HashMap<>();
  2.  
  3. testHashMap.put( "1", "Kim" );
  4. testHashMap.put( "2", "Dick" );
  5.  
  6. for( String key : testHashMap.keySet() )
  7. {
  8.     System.out.println( key + " = " + testHashMap.get( key ) );
  9. }
--------------------------------------------------------------------------------------------------------
在JavaScript內:
  1. var testHashMap= {};
  2.  
  3. testHashMap['1'] = 'Kim';
  4. testHashMap['2'] = 'Dick';
  5.  
  6. for( var key in testHashMap )
  7. {
  8.     alert( key + ' = ' + testHashMap[key] );
  9. }

2016年8月1日 星期一

在HTML內,不受CSS影響的Style設定方式

這個我還沒弄懂,是因為工作上碰到,然後同事提供了解法;所以先記錄在此,日後再研究。主要是把<select>的顯示和尺寸可以獨立在CSS之外:
  1. <style>
  2.  
  3.     #selectForm
  4.     {
  5.         width:200px !important;
  6.         height:auto !important;
  7.     }
  8. </style>
  9.  
  10. <select id = "selectForm" size = "4" multiple="multiple">
  11.     <option>1......</option>
  12.     <option>2......</option>
  13.     <option>3......</option>
  14.     <option>4......</option>
  15. </select>

HTML內下拉式選單的大小、單選和複選

在HTML內,常用<select>來製作下拉式選單,而這邊對於選單的顯示尺寸、單選和複選設定來說明。

顯示尺寸的部分,並不是要講Width和Height,而是設定可以一次性地顯示幾個選項:
  1. <select size = "3">
  2.     <option value = "1">第1個</option>
  3.     <option value = "2">第2個</option>
  4.     <option value = "3">第3個</option>
  5.     <option value = "4">第4個</option>
  6.     <option value = "5">第5個</option>
  7. </select>
size可以設定一次出現幾個選項在畫面上。
--------------------------------------------------------------------------------------------------------
然後是一般的單選,在HTML的部分:
  1. <select name = "list" size = "3">
  2.     <option value = "1">第1個</option>
  3.     <option value = "2">第2個</option>
  4.     <option value = "3">第3個</option>
  5.     <option value = "4">第4個</option>
  6.     <option value = "5">第5個</option>
  7. </select>
在JAVA的部分:
  1. String listValue = request.getParameter( "list" );
--------------------------------------------------------------------------------------------------------
最後是複選,在HTML的部分:
  1. <select name = "list" size = "3" multiple="multiple">
  2.     <option value = "1">第1個</option>
  3.     <option value = "2">第2個</option>
  4.     <option value = "3">第3個</option>
  5.     <option value = "4">第4個</option>
  6.     <option value = "5">第5個</option>
  7. </select>
在JAVA的部分:
  1. String[] listValueList = request.getParameterValues( "list" );

2016年7月28日 星期四

JavaScript內判斷String是否為有效數字

當使用者表單內輸入時,也許有的資料是只能輸入數字,因此就有必要在送出前檢查那些使用者輸入的String是否可轉換為有效數字;isNaN()便可以用來檢查,只是isNaN()原本是用來檢查String是否為純文字,如果有數字的話便會返回為false,所以運用時要注意。

HTML處的內容:
  1. <form action = "#" onsubmit = "return check();">
  2.     <input type = "text' id = "age" value = "">
  3. </form>
JavaScript處的內容:
  1. <script type="text/javascript">
  2.  
  3.     function check()
  4.     {
  5.         var age = document.getElementById( "age" ).value;
  6.  
  7.         if( isNaN(  age) )
  8.         {
  9.             alert( '該資料不可包含文字!' );
  10.         }
  11.     }
  12.  
  13. </script>

Java內判斷String是否為有效數字的方式

通常要把String轉換為Integer時,都得先知道String的內容是不是純數字,這樣轉換才會正確;所以找了一下判斷的方式,有NumberUtils.isNumber()、StringUtils.usNumeric()和StringUtils.isNumericSpace()三種,要使用這些方法的話,必需要下載Apache Commons Lang的封包檔,並匯入到Project內。

Apache Commons Lang可去其官網處下載:
http://commons.apache.org/proper/commons-lang/download_lang.cgi

像我便是下載commons-lang3-X.X-bin.zip,解壓縮後把其中的jar檔匯入到Eclipse的Project內。

接著撰寫程式:
  1. import java.util.*;
  2. import org.apache.commons.lang3.math.NumerUtils;
  3.  
  4. public class XXX {
  5.  
  6.     public static void main(String[] args)
  7.     {
  8.         String testString = "A1";
  9.  
  10.         System.out.rintln( NumberUtils.isNumber( testString ) );
  11.     }
  12. }
是文字便為false,是數字便為true。

2016年7月21日 星期四

HTML內顯示和隱藏指定的元件

在HTML內,也許會有一些要先隱藏後顯示的按鈕、輸入框或選項存在,這時就可以藉由使用者點擊按鈕、或是達成某項條件而改變;這邊來寫一個按鈕,點擊後可以改變隱藏的輸入框為顯示狀態。
--------------------------------------------------------------------------------------------------------
HTML處的寫法:
  1. <a href = "javascript:showPasswordInput()">重置密碼</a>
  2.  
  3. <tr id = "passwordRow" style = "display:none">
  4.     <input type = "text" name = "password" id = "passwordID" value = "">
  5. </tr>
--------------------------------------------------------------------------------------------------------
JavaScript處的寫法:
  1. <script type="text/javascript">
  2.  
  3. function showPasswordInput()
  4. {
  5.     var passwordRow = document.getElementById( 'passwordRow' );
  6.  
  7.     passwordRow.style.display = "";
  8. }
  9.  
  10. </script>
--------------------------------------------------------------------------------------------------------
一開始<tr>那行內的密碼輸入框是隱藏的,接著點擊按鈕後在Function內重新設定style.display成顯示狀態。

style.display有很多屬性,比較常用的有:
style.display = "none"
style.display = "block"
style.display = "inline"......等

這邊是很無厘頭的寫style.display = ""。

使用Javascript來取得、更改HTML中的值

這看起來似乎是基本中的基本,寫網頁十一定要懂的東西;但很抱歉,我在寫網頁這領域就是這麼菜,所以趕快來記下這必備的基本用法。

假設HTML處有一個輸入框:
  1. <form name = "userDataEdit">
  2. <input type = "text" name = "username" id = "usernameID" value = "">
接著在Javascript處,有兩種寫法,利用<form>的name和該id,以及直接找該id的寫法。
--------------------------------------------------------------------------------------------------------
在Javascript處,利用<form>的name和該id的寫法:
  1. <script type="text/javascript">
  2.  
  3. var username = document.userDataEdit.usernameID.value;
  4.  
  5. document.userDataEdit.usernameID.value = "Kimdick";
  6.  
  7. </script>
--------------------------------------------------------------------------------------------------------
在Javascript處,直接找該id的寫法:
  1. <script type="text/javascript">
  2.  
  3. var username = document.getElementById( 'usernameID' ).value;
  4.  
  5. document.getElementById( 'usernameID' ).value = "Kimdick";
  6.  
  7. </script>
--------------------------------------------------------------------------------------------------------

重點就是利用設定id名稱,來讓Javascript尋找並更改其數值。

2016年7月20日 星期三

HTML和Javascript之間互相傳值

在一個JSP內,通常會用到HTML、Javascript和Java語言,而HTML和Javascript間會有需要傳遞數值資料的情況發生;雖然對於那些寫網頁的老手可能是基本中的基本,但對於我這個根本沒碰過寫網頁的外行人則是困難重重,所以這邊特別記錄一下好提醒往後的自己。
--------------------------------------------------------------------------------------------------------
HTML傳值到JavaScript內:
    HTML的寫法:
  1. <input type = "button" name = "test" value = "test" onclick = "showAlert( 'test' );">
    主要是用Function的方式夾帶數值過去

    JavaScript的寫法:
  1. <script type="text/javascript">
  2.  
  3. function showAlert( lockTime )
  4. {
  5.     alert( message );
  6. }
  7.  
  8. </script>
--------------------------------------------------------------------------------------------------------
JavaScript傳值到HTML內:
    JavaScript的寫法:
  1. <script type="text/javascript">
  2.  
  3. function showAlert()
  4. {
  5.     if( confirm( '你確定要傳送此數值嗎?' ) )
  6.     {
  7.         document.getElementById( 'dataID' ).value = 'Yes';
  8.     }
  9. }
  10.  
  11. </script>
    主要是使用document.getElementById().value來設定該指定id的value

    HTML的寫法:
  1. <input type = "hidden" name = "data" id = "dataID" value = "No">
    主要是設定id後,讓JavaScript可以依照先前找到的id,把新數值設定在value內

2016年7月13日 星期三

Java內控制資料庫的AutoCommit、Commit和Rollback

在控制資料庫的執行時,一般在Eclipse內是設定為自動Commit的;可是如果遇到需要transaction的情況,就不能把環境設定為自動Commit,而得用手動的方式Commit出去;如果遇到錯誤的話,還得Rollback回來之前所有已執行的動作。

所以來列出這三個API:
  1. import java.sql.*;
  2.  
  3. public class XXX {
  4.  
  5.     public static void main(String[] args)
  6.     {
  7.         Connection connection;
  8.  
  9.         try
  10.         {
  11.             connection.setAutoCommit( false );
  12.             connection.commit();
  13.             connection.rollback();
  14.         }
  15.         catch( Exception)
  16.         {
  17.             e.printStackTrace();
  18.         }
  19.     }
  20. }
這三個API必需要在Try-Catch內才能執行

Java的Try-Catch錯誤表現方式

在使用Java的Try-Catch,有個很好用的錯誤表現方式:
  1. Integer x = 1;
  2.  
  3. try
  4. {
  5.     if( x > 0 )
  6.     {
  7.         throw new Exception( "錯誤" );
  8.     }
  9. }
  10. catch (Exception e)
  11. {
  12.     e.printStackTrace();
  13. }
這樣透過throw new Exception(),就會跳到catch()的部分,並且會在console上出現訊息。

HTML回到上一頁的方式

在撰寫HTML時,碰到要告知錯誤結果時,會需要再接一個回到上一頁的動作,這樣感覺才會連貫,所以查了一下,主要是JavaScript的history.back()這個API,就可執行返回上一頁的功能。

這裡用在一個按鈕上:
  1. <button onclick = "window.history.back();">返回前一頁</button>

HTML內,不會因為Enter按鍵而觸發Submit的方式

在撰寫HTML時,會使用<form>來執行動作,例如以下情況就很常見:
  1. <form action="XXXServlet" method = "post">
  2.     <input type = "text" name = "username" value = "">
  3.     <input type = "text" name = "password" value = "">
  4.     <input type = "submit" name = "login" value = "登入" >
  5. </form>
原本的目標是希望使用者輸入完帳號和密碼後,再按下登入的按鈕來進入系統;可是因為輸入的行為也在<form>內,因此在任何一個輸入框內按下Enter鍵的話,就會等於submit,還沒按下按鈕就會執行action。

但是一般在輸入過程中,人們有時會按下Enter,例如中文輸入法等等的情況,也許你正填寫一大堆的資料,結果在第一個輸入格時按下Enter,然後就自動執行action了......

查了一下,基本上歸納出有兩大類手段可解決:使用JavaScript的Listener來監聽按鈕事件,和使用HTML的onkeypress功能來過濾。我首先試了JavaScript的Listener,但怎麼試都不成功,並且這個方式還須寫不少程式碼,所以我選擇使用HTML的onkeypress功能,只需一行就可搞定,並且可寫在你所需要的地方。

所以將程式改為下面的情況,就不會再因為Enter鍵而觸發action了:
  1. <form action="XXXServlet" method = "post" onkeypress="return event.keyCode != 13;>
  2.     <input type = "text" name = "username" value = "">
  3.     <input type = "text" name = "password" value = "">
  4.     <input type = "submit" name = "login" value = "登入" >
  5. </form>
也就是在第一行後面加上onkeypress="return event.keyCode != 13 你也可以視情況,寫在<input>、<select>等內。

簡單又好用,我最喜歡這種的了......

2016年6月30日 星期四

Eclipse內創造註解和一般方法

在Eclipse內寫程式時,可以為自創的Function加上適當的註解,也可以自動產生一般方法而免去手動撰寫。

例如先創造一個Bean:






再用滑鼠右鍵選單選擇【Generate Element Commet】和【Generate Getters and Setters】,便會有相對應的結果出現:













在點擊【Generate Getters and Setters】後,會出現要針對哪些變數來自動產生方法:
























註解寫好後,以後只要將滑鼠移動到該程式碼上,便會出現一般我們所常看到的Tip了:

2016年6月29日 星期三

PostgreSQL的更改欄位類型方式

話說PostgreSQL的Console讓我覺得有一些地方不方便,創造欄位後便不可以介面式的移動位置、更改欄位類型等諸多限制,尤其是當我想要二次更改時,就只好刪除重建,但是這樣一來位置又會走掉,所以常常會為了更改一個欄位,就毀掉大半表格又重建(當然,實際上欄位位置不重要,一樣可以使用,但我就是希望看得舒服@@)。

所以搜尋和嘗試了一小段時間,找到了可以用SQL語法變更欄位類型的方式。

例如,在名為"test"的schema內,將一個名為"check_time"的欄位更改為"時間且不含時區"的格式:
ALTER TABLE msoc.test
ALTER COLUMN check_time TYPE timestamp without time zone
USING check_time::timestamp without time zone

例如,在名為"test"的schema內,將一個名為"id"的欄位更改為"字串"的格式:
ALTER TABLE msoc.test
ALTER COLUMN id TYPE varchar
USING id::varchar

主要是參考下列網址內的資訊:
https://www.postgresql.org/docs/9.1/static/sql-altertable.html

TYPE的部分,有時會和在介面內創造時的名稱不一樣,例如在介面內是"character varying",在SQL語法內是"varchar",所以要改變類別時,最好去上列網址內看看想要改變的類別在TYPE處該怎麼寫。

2016年6月27日 星期一

Java的現在時間取法,和延遲用法

首先是我需要使用Java來取得現在時間,Java裡和時間相關的Class有好幾個,看了看網上的資訊後我決定使用java.time來實作。
  1. import java.time.*;
  2.  
  3. public class MainProcess{
  4.  
  5.     public static void main(String[] args)
  6.     {
  7.         LocalDateTime currentDateTime = LocalDateTime.now();
  8.  
  9.         System.out.println( currentDateTime );
  10.     }
  11. }

要注意的是,currentDateTime只是儲存了LocalDateTime.now()所取得的時間值,故一會兒後再使用currentDateTime的話,裡面的時間值可不會自動改變喔。每次要取得最新的"現在時間值"的話,就必須反覆使用LocalDateTime.now()。

LocalDateTime的結果並不包含時區,如果要直接取得時間 + 時區的結果,可以使用ZonedDateTime的Class。
  1. import java.time.*;
  2.  
  3. public class MainProcess{
  4.  
  5.     public static void main(String[] args)
  6.     {
  7.         ZonedDateTime currentDateTime = currentZoneTime.now();
  8.  
  9.         System.out.println( currentZoneTime );
  10.     }
  11. }

如果是想要單純取得時區,可以使用ZonedDateTime下的一些方法,通常可以取得的結果有兩種:時區的區域名稱,和時區的時差數值。
  1. import java.time.*;
  2.  
  3. public class MainProcess{
  4.  
  5.     public static void main(String[] args)
  6.     {
  7.         ZonedDateTime currentDateTime = currentZoneTime.now();
  8.  
  9.         System.out.println( currentZoneTime.getZone() );
  10.         System.out.println( currentZoneTime.getOffset() );
  11.     }
  12. }

然後是如果執行程式時需要延遲一會兒,有Thread.sleep()和TimeUnit.sleep這兩個用法,這邊我選擇TimeUnit.sleep,因為有比較完整的用法,還可分為從TimeUnit.DAYS到TimeUnit.NANOSECONDS各種不同時間單位的使用方式,這邊使用TimeUnit.SECONDS來實作。
  1. import java.time.*;
  2. import java.util.*;
  3. import java.util.concurrent.*;
  4.  
  5. public class MainProcess{
  6.  
  7.     public static void main(String[] args) throws InterruptedException
  8.     {
  9.         for( int i = 0; i < 10; i++ )
  10.         {
  11.             TimeUnit.SECONDS.sleep( 1 );
  12.  
  13.             System.out.println( LocalDateTime.now() );
  14.         }
  15.     }
  16. }

2016年6月16日 星期四

在Eclipse內使用PostgreSQL資料庫

最近工作需要在Eclipse內和PostgreSQL資料庫相連,因此這邊記錄一下使用方式,免得自己以後要用時又得東找西找的。

首先將PostgreSQL的JAR檔匯入到Eclipse內:


接著在Eclipse內撰寫:
  1. import java.sql.*;
  2.  
  3. public class MainProcess {
  4.  
  5.     public static void main(String[] args)
  6.     {
  7.         Connection tempConnection = null;
  8.         Statement tempStatement = null;
  9.         ResultSet tempResultSet = null;
  10.         String tempAction = "";
  11.         String tempSentence = "";
  12.  
  13.         switch( tempAction )
  14.         {
  15.             case "Select":
  16.                 tempSentence = "SELECT * FROM Schemas.Tables WHERE account = 'Kimdick' AND password = '123'";
  17.  
  18.                 break;
  19.             case "Insert":
  20.                 tempSentence = "INSERT INTO Schemas.Tables ( account, password ) VALUES ( 'Kimdick', '123' )";
  21.  
  22.                 break;
  23.             case "Update":
  24.                 tempSentence = "Update Schemas.Tables SET password = '123', email = 'Kimdick@mail' WHERE account = 'Kimdick'";
  25.  
  26.                 break;
  27.             case "Delete":
  28.                 tempSentence = "DELETE FROM Schemas.Tables WHERE account = 'Kimdick'";
  29.  
  30.                 break;
  31.         }
  32.  
  33.         try
  34.         {
  35.             Class.forName( "org.postgresql.Driver" );
  36.             tempConnection = DriverManager.getConnection( "jdbc:postgresql://127.0.0.1:5432/datastream", "postgres", "1234" );
  37.             tempStatement = tempConnection.createStatement();
  38.             tempStatement.executeQuery( tempSentence );
  39.  
  40.             if( tempResultSet != null )
  41.             {
  42.                 tempResultSet.close();
  43.                 tempResultSet = null;
  44.             }
  45.  
  46.             if( tempStatement != null )
  47.             {
  48.                 tempStatement.close();
  49.                 tempStatement = null;
  50.             }
  51.  
  52.             if( tempConnection != null )
  53.             {
  54.                 tempConnection.close();
  55.                 tempConnection = null;
  56.             }
  57.         }
  58.         catch( Exception e )
  59.         {
  60.             e.printStackTrace();
  61.         }
  62.     }
  63. }

  1. DriverManager.getConnection( "jdbc:postgresql://127.0.0.1:5432/datastream", "postgres", "1234" );
這裡是DriverManager.getConnection( "jdbc:postgresql://資料庫IP:Port/Database", 帳號, 密碼 );

2016年6月14日 星期二

C#的拆解字串

在Unity內、使用C#時,有時會需要拆解字串和重組字串,字串的拆解通常都是訂定拆解字元來執行,但有時也會需要訂定拆解字串來執行。
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public class MainProcess : MonoBehaviour {
  6.  
  7.     private string data = "ABCDEFGH";
  8.     private string[] splitSeparators = new string[]{ "DEF" };
  9.  
  10.     void Start ()
  11.     {
  12.         Debug.Log( data.split( 'D' )[0] );
  13.         Debug.Log( data.split( 'D' )[1] );
  14.  
  15.         Debug.Log( data.split( splitSeparators, System.StringSplitOptions.None )[0] );
  16.         Debug.Log( data.split( splitSeparators, System.StringSplitOptions.None )[1] );
  17.     }
  18. }

2016年6月13日 星期一

C#的Dictionary之取得資料

Dictionary是類似Hashtable的架構,用Key和Value的方式來相對應。
而要來依序取得裡面的資料時,foreach裡引用的架構和一般有點不同,主要是keyValuePair。
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public class MainProcess : MonoBehaviour {
  6.  
  7.     private Dictionary<int, string> tempDictionary = new Dictionary<int, string>();
  8.  
  9.     void Start ()
  10.     {
  11.         tempDictionary.Add( 1, "XXX" );
  12.         tempDictionary.Add( 2, "YYY" );
  13.         tempDictionary.Add( 3, "ZZZ" );
  14.  
  15.         foreach( KeyValuePair<int, string> x in tempDictionary )
  16.         {
  17.             Debug.Log( x.Key + " = " + x.Value );
  18.         }
  19.     }
  20. }

Unity內轉換Direction和EulerAngles為Quaternion

一般在3D間內有三種可表現方向的方式:
Direction:向量方式,例如( 1, 0, 0 )表示面向正左方。
EulerAngles:尤拉角(由拉角、歐拉角)方式,例如( 0, 180, 0 )表示面向正後方。
Qaternion:四元數。

Direction和EulerAngles都很好理解,而Qaternion即使我能理解它的原理,但還是不擅使用。
偏偏有不少關於方向的使用都得是Qaternion型式,所以轉換就很重要。

Direction轉換成Qaternion,可以使用Qaternion.LookRotation:
  1. Qaternion LookRotation( Vector3 forward, Vector3 upwards = Vector3.up );
例如Qaternion rotation = Qaternion.LookRotation( new Vector3( 1, 0, 0 ), Vector3.up );

EulerAngles轉換成Qaternion,可以使用Qaternion.Euler:
  1. Quaternion Euler( float x, float y, float z );
例如Quaternion rotation = Quaternion.Euler( 0, 30, 0 );

這樣當需要使用Quaternion時,我就可以用這些方式去轉換了。

2016年6月8日 星期三

Unity內偵測有否點擊到UGUI作出來的介面

Unity現在可使用方便的UGUI功能作介面,而當要操控2D介面或是作3D物件控制時,都是使用滑鼠左鍵;所以一般邏輯為當滑鼠初次點擊在2D介面上時,就不會啟動3D物件控制功能,因此需要偵測滑鼠是否點擊在任何UGUI作出來的2D介面上。

UGUI在創建時,會自動在【Hierarchy】下產生Canvas』和EventSystem』兩個物件,EventSystem』便是用來處理點擊等事件的存在,所以會使用它來得知是否有滑鼠點擊任何UGUI物件,並可取得所點擊的介面物件。


  1. using UnityEngine;
  2. using System.Collections;
  3. using UnityEngine.EventSystems;
  4.  
  5. public class MainProcess : MonoBehaviour {
  6.  
  7.     void Update ()
  8.     {
  9.         if( Input.GetMouseButtonDown( 0 ) )
  10.         {
  11.             if( EventSystem.current.IsPointerOverGameObject() )
  12.             {
  13.                 Debug.Log( "有介面被點擊到!" );
  14.                 Debug.Log( EventSystem.current.currentSelectedGameObject );
  15.             }
  16.         }
  17.     }
  18. }

2016年6月7日 星期二

C#的尋找在List內之Structure資料

在Unity內、使用C#時,創造包含Structure的List,然後用條件尋找的方式。
先在List內找到符合條件的該筆資料Index,再用Index去調出要尋找的該筆資料其他部分:
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public class MainProcess : MonoBehaviour {
  6.  
  7.     private List<tempStructure> tempStructureList = new List<tempStructure>();
  8.  
  9.     private struct tempStructure
  10.     {
  11.         public int tempNumber;
  12.         public string tempName;
  13.     }
  14.  
  15.     void Start ()
  16.     {
  17.         tempStructure xxx = new tempStructure();
  18.         tempStructure yyy = new tempStructure();
  19.  
  20.         xxx.tempNumber = 1;
  21.         xxx.tempName = "XXX";
  22.         yyy.tempNumber = 2;
  23.         yyy.tempName = "YYY";
  24.  
  25.         tempStructureList.Add( xxx );
  26.         tempStructureList.Add( yyy );
  27.  
  28.         tempIndex = tempStructureList.FindIndex( z => z.tempName == "XXX" );
  29.  
  30.         Debug.log( tempStructureList[tempIndex].tempNumber );
  31.     }
  32. }

C#的Structure

在Unity內、使用C#時,創造並使用Structure的方式:
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class MainProcess : MonoBehaviour {
  5.  
  6.     private struct tempStructure
  7.     {
  8.         public int tempIndex;
  9.         public string tempName;
  10.     }
  11.  
  12.     void Start ()
  13.     {
  14.         tempStructure xxx = new tempStructure();
  15.  
  16.         xxx.tempIndex = 1;
  17.         xxx.tempName = "Name";
  18.  
  19.         Debug.log( xxx.tempIndex  );
  20.         Debug.log( xxx.tempName );
  21.     }
  22. }

這就是Google的Blogger @@

在很久很久以前,有使用過Yahoo的部落格,玩了一下就沒繼續了。

過了很久,現在是個程式工程師的我,常常會在網路上尋找很多資訊。有自己會用到的資訊時,便會把網頁給整個儲存起來,可是東西一多了之後,往往會很不好找。

這時靈光一閃,有看過一些人會把自己使用到的資訊,記錄在網誌上,讓我萌起了這個也想做看看的念頭。

接下來,就看我有沒有恆心來玩囉......