2016年9月10日 星期六

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

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

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

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

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

WebClient:
using UnityEngine;
using System.Collections;
using System.Net;

public class WebClientController : MonoBehaviour {

    void Start ()
    {
        WebClient webClient = new WebClient();

        try
        {
            webClient.DownloadFile( "http://localhost:8080/xxx.assetbundle", "D:/xxx.assetbundle" );
        }
        catch( Exception ex )
        {
            Debug.Log( ex );
        }
    }
}
雖然我想一併使用下載過程的檢視,但是這部分的效果就是出不來,只好先記錄程式碼,日後有空再來試。
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler( WebClient_DownloadProgressChanged );
webClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler( WebClient_DownloadDataCompleted );

void WebClient_DownloadProgressChanged( object sender, DownloadProgressChangedEventArgs e )
{
    Debug.Log( "下載" + e.ProgressPercentage + "%" );
}

void WebClient_DownloadDataCompleted (object sender, DownloadDataCompletedEventArgs e)
{
    Debug.Log( "下載完成" );
}
--------------------------------------------------------------------------------------------------------

Stream:
using UnityEngine;
using System.Collections;
using System.Net;

public class WebClientController : MonoBehaviour {

    HttpWebRequest httpWebRequest;
    HttpWebResponse httpResponse;
    System.IO.Stream dataStream;
    byte[] buffer = new byte[8192];
    int size = 0;
    float downloadMemory = 0;
    bool completeCheck = false;

    void Start ()
    {
        try
        {
            httpWebRequest = (HttpWebRequest)WebRequest.Create( "http://localhost:8080/xxx.assetbundle" );
            httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
            dataStream = httpResponse.GetResponseStream();
            fileStream = new FileStream( "D:/xxx.assetbundle", FileMode.Create, FileAccess.Write );

            downloadMemory = 0;
        }
        catch( Exception e )
        {
            Debug.Log( e );
        }
    }

    void Update ()
    {
        if( completeCheck == false )
        {
            try
            {
                size = dataStream.Read( buffer, 0, buffer.Length );

                if( size > 0 )
                {
                    fileStream.Write( buffer, 0, size );
                    downloadMemory += size;
                    Debug.Log( "正下載 " + ( downloadMemory / 1048576 ).ToString( "f1" ) + "MB / " +
                                ((float)httpResponse.ContentLength / 1048576 ).ToString( "f1" ) + "MB == " +
                                (( downloadMemory / (float)httpResponse.ContentLength ) * 100 ).ToString( "f1" ) + "%" );
                }
                else
                {
                    fileStream.Close();
                    httpResponse.Close();
                    buffer = new byte[8192];

                    Debug.Log( "下載完成!" );

                    completeCheck = true;
                }
            }
            catch( Exception ex )
            {
                Debug.Log( ex );
            }
        }
    }
}
--------------------------------------------------------------------------------------------------------

Unity內用WWW載入AssetBundle

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

但這都不是重點,本篇的重點是將AssetBundle匯入到Unity程式內使用。
using UnityEngine;
using System.Collections;

public class AssetBundleLoadController : MonoBehaviour {

    void Start ()
    {
        StartCoroutine( LoadAssetBundle() );
    }

    private IEnumerator LocalLoad()
    {
        WWW fileBundle = new WWW( "file://D:/xxx.assetbundle" );
        yield return fileBundle;

        GameObject tempObject = null;
        yield return tempObject = Instantiate( fileBundle.assetBundle.mainAsset ) as GameObject;
        tempObject.name = tempObject.name.Replace( "(Clone)", string.Empty );

        fileBundle.assetBundle.Unload( false );
        Resources.UnloadUnusedAssets();
    }
}
這樣就能使用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取得網址,再過濾出名稱。
String uri = request.getRequestURI();
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的內容:
<%@ page language="java" contentType="text/html; charset=BIG5" pageEncoding="BIG5"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=BIG5">
<title>AAA</title>
</head>
<script type="text/javascript">

    function sendMessage()
    {
        var menu = document.getElementById( "bbbID" ).contentWindow;

        menu.postMessage( document.getElementById( "messageID" ).value, 'http://localhost:8080' );
    }

</script>
<body>
    <iframe src = "bbb.jsp" id = "bbbID" frameborder = "1" scrolling = "auto"></iframe>

    <form>
        <input type = "text" id = "messageID" value = "">
        <input type = "button" value = "傳送訊息給bbb" onclick = "sendMessage()">
    </form>
</body>
</html>
--------------------------------------------------------------------------------------------------------

bbb.jsp的內容:
<%@ page language="java" contentType="text/html; charset=BIG5" pageEncoding="BIG5"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=BIG5">
<title>Insert title here</title>
</head>
<script type="text/javascript">

    function getMessage( event )
    {
        if( event.origin != 'http://localhost:8080' )
        {
            alert( event.origin );

            return;
        }

        document.getElementById( "receiveID" ).innerHTML = event.data;
    }

    if( typeof window.addEventListener != 'undefined' )
    {
        window.addEventListener( 'message', getMessage, false );
    }
    else if( typeof window.attachEvent != 'undefined' )
    {
        window.attachEvent( 'onmessage', getMessage );
    }

</script>
<body>
    <h1>這是bbb!</h1>
    <div id = "receiveID">等待接收訊息!</div>
</body>
</html>
--------------------------------------------------------------------------------------------------------

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

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

然後在bbb.jsp內將
function getMessage( event )
{
    if( event.origin != 'http://localhost:8080' )
    {
        alert( event.origin );

        return;
    }

    document.getElementById( "receiveID" ).innerHTML = event.data;
}
改為
function getMessage( event )
{
    document.getElementById( "receiveID" ).innerHTML = event.data;
}
--------------------------------------------------------------------------------------------------------

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

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

2016年8月2日 星期二

在Java和JavaScript內的HashMap用法

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

在Java內:
HashMap<String, String> testHashMap = new HashMap<>();

testHashMap.put( "1", "Kim" );
testHashMap.put( "2", "Dick" );

for( String key : testHashMap.keySet() )
{
    System.out.println( key + " = " + testHashMap.get( key ) );
}
--------------------------------------------------------------------------------------------------------
在JavaScript內:
var testHashMap= {};

testHashMap['1'] = 'Kim';
testHashMap['2'] = 'Dick';

for( var key in testHashMap )
{
    alert( key + ' = ' + testHashMap[key] );
}

2016年8月1日 星期一

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

這個我還沒弄懂,是因為工作上碰到,然後同事提供了解法;所以先記錄在此,日後再研究。主要是把<select>的顯示和尺寸可以獨立在CSS之外:
<style>

    #selectForm
    {
        width:200px !important;
        height:auto !important;
    }
 
</style>

<select id = "selectForm" size = "4" multiple="multiple">
    <option>1......</option>
    <option>2......</option>
    <option>3......</option>
    <option>4......</option>
</select>

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

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

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

2016年7月28日 星期四

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

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

HTML處的內容:
<form action = "#" onsubmit = "return check();">
    <input type = "text' id = "age" value = "">
</form>
JavaScript處的內容:
<script type="text/javascript">

    function check()
    {
        var age = document.getElementById( "age" ).value;

        if( isNaN(  age) )
        {
            alert( '該資料不可包含文字!' );
        }
    }

</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內。

接著撰寫程式:
import java.util.*;
import org.apache.commons.lang3.math.NumerUtils;

public class XXX {

    public static void main(String[] args)
    {
        String testString = "A1";

        System.out.rintln( NumberUtils.isNumber( testString ) );
    }
}
是文字便為false,是數字便為true。

2016年7月21日 星期四

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

在HTML內,也許會有一些要先隱藏後顯示的按鈕、輸入框或選項存在,這時就可以藉由使用者點擊按鈕、或是達成某項條件而改變;這邊來寫一個按鈕,點擊後可以改變隱藏的輸入框為顯示狀態。
--------------------------------------------------------------------------------------------------------
HTML處的寫法:
<a href = "javascript:showPasswordInput()">重置密碼</a>

<tr id = "passwordRow" style = "display:none">
    <input type = "text" name = "password" id = "passwordID" value = "">
</tr>
--------------------------------------------------------------------------------------------------------
JavaScript處的寫法:
<script type="text/javascript">

function showPasswordInput()
{
    var passwordRow = document.getElementById( 'passwordRow' );

    passwordRow.style.display = "";
}

</script>
--------------------------------------------------------------------------------------------------------
一開始<tr>那行內的密碼輸入框是隱藏的,接著點擊按鈕後在Function內重新設定style.display成顯示狀態。

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

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

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

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

假設HTML處有一個輸入框:
<form name = "userDataEdit">
<input type = "text" name = "username" id = "usernameID" value = "">
接著在Javascript處,有兩種寫法,利用<form>的name和該id,以及直接找該id的寫法。
--------------------------------------------------------------------------------------------------------
在Javascript處,利用<form>的name和該id的寫法:
<script type="text/javascript">

var username = document.userDataEdit.usernameID.value;

document.userDataEdit.usernameID.value = "Kimdick";

</script>
--------------------------------------------------------------------------------------------------------
在Javascript處,直接找該id的寫法:
<script type="text/javascript">

var username = document.getElementById( 'usernameID' ).value;

document.getElementById( 'usernameID' ).value = "Kimdick";

</script>
--------------------------------------------------------------------------------------------------------

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

2016年7月20日 星期三

HTML和Javascript之間互相傳值

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

    JavaScript的寫法:
<script type="text/javascript">

function showAlert( lockTime )
{
    alert( message );
}

</script>
--------------------------------------------------------------------------------------------------------
JavaScript傳值到HTML內:
    JavaScript的寫法:
<script type="text/javascript">

function showAlert()
{
    if( confirm( '你確定要傳送此數值嗎?' ) )
    {
        document.getElementById( 'dataID' ).value = 'Yes';
    }
}

</script>
    主要是使用document.getElementById().value來設定該指定id的value

    HTML的寫法:
<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:
import java.sql.*;

public class XXX {

    public static void main(String[] args)
    {
        Connection connection;

        try
        {
            connection.setAutoCommit( false );
            connection.commit();
            connection.rollback();
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }
    }
}
這三個API必需要在Try-Catch內才能執行

Java的Try-Catch錯誤表現方式

在使用Java的Try-Catch,有個很好用的錯誤表現方式:
Integer x = 1;

try
{
    if( x > 0 )
    {
        throw new Exception( "錯誤" );
    }
}
catch (Exception e)
{
    e.printStackTrace();
}
這樣透過throw new Exception(),就會跳到catch()的部分,並且會在console上出現訊息。

HTML回到上一頁的方式

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

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

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

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

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

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

所以將程式改為下面的情況,就不會再因為Enter鍵而觸發action了:
<form action="XXXServlet" method = "post" onkeypress="return event.keyCode != 13;>
    <input type = "text" name = "username" value = "">
    <input type = "text" name = "password" value = "">
    <input type = "submit" name = "login" value = "登入" >
</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來實作。
import java.time.*;

public class MainProcess{

    public static void main(String[] args)
    {
        LocalDateTime currentDateTime = LocalDateTime.now();

        System.out.println( currentDateTime );
    }
}

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

LocalDateTime的結果並不包含時區,如果要直接取得時間 + 時區的結果,可以使用ZonedDateTime的Class。
import java.time.*;

public class MainProcess{

    public static void main(String[] args)
    {
        ZonedDateTime currentDateTime = currentZoneTime.now();

        System.out.println( currentZoneTime );
    }
}

如果是想要單純取得時區,可以使用ZonedDateTime下的一些方法,通常可以取得的結果有兩種:時區的區域名稱,和時區的時差數值。
import java.time.*;

public class MainProcess{

    public static void main(String[] args)
    {
        ZonedDateTime currentDateTime = currentZoneTime.now();

        System.out.println( currentZoneTime.getZone() );
        System.out.println( currentZoneTime.getOffset() );
    }
}

然後是如果執行程式時需要延遲一會兒,有Thread.sleep()和TimeUnit.sleep這兩個用法,這邊我選擇TimeUnit.sleep,因為有比較完整的用法,還可分為從TimeUnit.DAYS到TimeUnit.NANOSECONDS各種不同時間單位的使用方式,這邊使用TimeUnit.SECONDS來實作。
import java.time.*;
import java.util.*;
import java.util.concurrent.*;

public class MainProcess{

    public static void main(String[] args) throws InterruptedException
    {
        for( int i = 0; i < 10; i++ )
        {
            TimeUnit.SECONDS.sleep( 1 );

            System.out.println( LocalDateTime.now() );
        }
    }
}

2016年6月16日 星期四

在Eclipse內使用PostgreSQL資料庫

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

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


接著在Eclipse內撰寫:
import java.sql.*;

public class MainProcess {

    public static void main(String[] args)
    {
        Connection tempConnection = null;
        Statement tempStatement = null;
        ResultSet tempResultSet = null;
        String tempAction = "";
        String tempSentence = "";

        switch( tempAction )
        {
            case "Select":
                tempSentence = "SELECT * FROM Schemas.Tables WHERE account = 'Kimdick' AND password = '123'";

                break;
            case "Insert":
                tempSentence = "INSERT INTO Schemas.Tables ( account, password ) VALUES ( 'Kimdick', '123' )";

                break;
            case "Update":
                tempSentence = "Update Schemas.Tables SET password = '123', email = 'Kimdick@mail' WHERE account = 'Kimdick'";

                break;
            case "Delete":
                tempSentence = "DELETE FROM Schemas.Tables WHERE account = 'Kimdick'";

                break;
        }

        try
        {
            Class.forName( "org.postgresql.Driver" );
            tempConnection = DriverManager.getConnection( "jdbc:postgresql://127.0.0.1:5432/datastream", "postgres", "1234" );
            tempStatement = tempConnection.createStatement();
            tempStatement.executeQuery( tempSentence );

            if( tempResultSet != null )
            {
                tempResultSet.close();
                tempResultSet = null;
            }

            if( tempStatement != null )
            {
                tempStatement.close();
                tempStatement = null;
            }

            if( tempConnection != null )
            {
                tempConnection.close();
                tempConnection = null;
            }
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }
    }
}

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#時,有時會需要拆解字串和重組字串,字串的拆解通常都是訂定拆解字元來執行,但有時也會需要訂定拆解字串來執行。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MainProcess : MonoBehaviour {

    private string data = "ABCDEFGH";
    private string[] splitSeparators = new string[]{ "DEF" };

    void Start ()
    {
        Debug.Log( data.split( 'D' )[0] );
        Debug.Log( data.split( 'D' )[1] );

        Debug.Log( data.split( splitSeparators, System.StringSplitOptions.None )[0] );
        Debug.Log( data.split( splitSeparators, System.StringSplitOptions.None )[1] );
    }
}

2016年6月13日 星期一

C#的Dictionary之取得資料

Dictionary是類似Hashtable的架構,用Key和Value的方式來相對應。
而要來依序取得裡面的資料時,foreach裡引用的架構和一般有點不同,主要是keyValuePair。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MainProcess : MonoBehaviour {

    private Dictionary<int, string> tempDictionary = new Dictionary<int, string>();

    void Start ()
    {
        tempDictionary.Add( 1, "XXX" );
        tempDictionary.Add( 2, "YYY" );
        tempDictionary.Add( 3, "ZZZ" );

        foreach( KeyValuePair<int, string> x in tempDictionary )
        {
            Debug.Log( x.Key + " = " + x.Value );
        }
    }
}

Unity內轉換Direction和EulerAngles為Quaternion

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

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

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

EulerAngles轉換成Qaternion,可以使用Qaternion.Euler:
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物件,並可取得所點擊的介面物件。


using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;

public class MainProcess : MonoBehaviour {

    void Update ()
    {
        if( Input.GetMouseButtonDown( 0 ) )
        {
            if( EventSystem.current.IsPointerOverGameObject() )
            {
                Debug.Log( "有介面被點擊到!" );
                Debug.Log( EventSystem.current.currentSelectedGameObject );
            }
        }
    }
}

2016年6月7日 星期二

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

在Unity內、使用C#時,創造包含Structure的List,然後用條件尋找的方式。
先在List內找到符合條件的該筆資料Index,再用Index去調出要尋找的該筆資料其他部分:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MainProcess : MonoBehaviour {

    private List<tempStructure> tempStructureList = new List<tempStructure>();

    private struct tempStructure
    {
        public int tempNumber;
        public string tempName;
    }

    void Start ()
    {
        tempStructure xxx = new tempStructure();
        tempStructure yyy = new tempStructure();

        xxx.tempNumber = 1;
        xxx.tempName = "XXX";
        yyy.tempNumber = 2;
        yyy.tempName = "YYY";

        tempStructureList.Add( xxx );
        tempStructureList.Add( yyy );

        tempIndex = tempStructureList.FindIndex( z => z.tempName == "XXX" );

        Debug.log( tempStructureList[tempIndex].tempNumber );
    }
}

C#的Structure

在Unity內、使用C#時,創造並使用Structure的方式:
using UnityEngine;
using System.Collections;

public class MainProcess : MonoBehaviour {

    private struct tempStructure
    {
        public int tempIndex;
        public string tempName;
    }

    void Start ()
    {
        tempStructure xxx = new tempStructure();

        xxx.tempIndex = 1;
        xxx.tempName = "Name";

        Debug.log( xxx.tempIndex  );
        Debug.log( xxx.tempName );
    }
}

這就是Google的Blogger @@

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

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

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

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