Posts match “ java ” tag:

需求

  • 輸入日期字串(或java.util.Date),可以輸出對應是星期幾。
  • 輸出可以依照各程式的資料結構需求而改變,可以輸出字串、enum類別或其他自己定義的資料結構。
  • 例如:輸入「2014-03-17」,輸出將會是「星期一」或「1」。

思路

  • 善用java.text.DateFormatjava.util.Calendar兩個類別搭配服用即可達成。
  • 這邊因為輸出可以依照資料結構需求而變,所以使用最簡單的Integer來實作,資料結構轉換在client端實作。

程式碼

/**
 * 輸入日期,可以轉換成星期幾。
 * 
 * @param dateString日期字串
 * @return 星期幾
 * @throws ParseException 無法將字串轉換成java.util.Date類別
 */
public static String date2Day( String dateString ) throws ParseException
{
    SimpleDateFormat dateStringFormat = new SimpleDateFormat( "yyyy-MM-dd" );
    Date date = dateStringFormat.parse( dateString );

    SimpleDateFormat date2DayFormat = new SimpleDateFormat( "u" );
    return date2DayFormat.format( date );
}

實作說明

  • 第一個SimpleDateFormat是用來將字串轉換成java.util.Date物件,如果輸入是java.util.Date則可以不用做字串轉Date的轉換。
  • 第二個SimpleDateFormat就是用來將日期轉換成星期幾,在new SimpleDateFormat("u")u稱為日期時間的pattern,用來表示做日期格式化時分析時的樣式,而u pattern是用來表示一週的星期幾,並且以整數表示,1=星期一 ... 7=星期天。
  • 如果要直接轉換成「星期幾」而不是整數,則將pattern換成E即可。
  • 以上pattern的大小寫都要一樣!! 不一樣的大小寫在SimpleDateFormat會有不同的解讀,例如:大寫M表示月份,小寫m表示分鐘。

參閱更多

SimpleDateFormat

Socket是??

  • Socket最早緣起於Unix,而在Unix的檔案可以用開啟open -> 讀寫write/read -> 關閉close的模式來操作,所以Socket在Unix當中也遵循這樣的操作模式,算是一種文件,Socket所提供的API就是可以進行的操作(開啟/關閉、讀寫)。
  • 使用TCP/IP協定的程式都是採用Socket來進行連接傳輸的介面,最常見的例子就是網頁瀏覽器,底層都是用Socket去做連接通信的介面。
  • Socket架構圖解


Java Socket API

簡單了解Socket為何後,接著就要來看在Java當中程式怎麼寫了。Socket Programming採用Server/Client(以下簡稱S/C架構)的架構來實作,所以下面列出幾個簡單觀念先了解後會更快上手:

  • S/C架構下的程式進行通訊,Server端需要提供一個固定位置(一個IP:Port或Domain Name),Client要連接就要先知道這位置。
  • 在Java當中S/C架構就是對應到ServerSocketSocket兩個物件,Server端用ServerSocket.listen()來監聽Client端,Client端用Socket和Server端做連接,Server端用ServerSocket.accept()來取得和Client端連線的Socket物件。
  • 當Server和Client連接後,就可以用socket.getInputStream()socket.getOutputStream()來做資料的讀寫傳輸。
  • 最後資料傳遞完後,記得要呼叫socket.close()來關閉所有使用到的Sockets。

程式碼

Server端

public class Server
{
    public static final int LISTEN_PORT = 5987;
    
    public void listenRequest()
    {
        ServerSocket serverSocket = null;
        ExecutorService threadExecutor = Executors.newCachedThreadPool();
        try
        {
            serverSocket = new ServerSocket( LISTEN_PORT );
            System.out.println("Server listening requests...");
            while ( true )
            {
                Socket socket = serverSocket.accept();
                threadExecutor.execute( new RequestThread( socket ) );
            }
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
        finally
        {
            if ( threadExecutor != null )
                threadExecutor.shutdown();
            if ( serverSocket != null )
                try
                {
                    serverSocket.close();
                }
                catch ( IOException e )
                {
                    e.printStackTrace();
                }
        }
    }
    
    /**
     * @param args
     */
    public static void main( String[] args )
    {
        Server server = new Server();
        server.listenRequest();
    }
    
    /**
     * 處理Client端的Request執行續。
     *
     * @version
     */
    class RequestThread implements Runnable
    {
        private Socket clientSocket;
        
        public RequestThread( Socket clientSocket )
        {
            this.clientSocket = clientSocket;
        }
        
        /* (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        @Override
        public void run()
        {
            System.out.printf("有%s連線進來!\n", clientSocket.getRemoteSocketAddress() );
            DataInputStream input = null;
            DataOutputStream output = null;
            
            try
            {
                input = new DataInputStream( this.clientSocket.getInputStream() );
                output = new DataOutputStream( this.clientSocket.getOutputStream() );
                while ( true )
                {
                    output.writeUTF( String.format("Hi, %s!\n", clientSocket.getRemoteSocketAddress() ) );
                    output.flush();
                    // TODO 處理IO,這邊定義protocol協定!!

                    break;
                }
            }
            catch ( IOException e )
            {
                e.printStackTrace();
            }
            finally 
            {
                try
                {
                    if ( input != null )
                        input.close();
                    if ( output != null )
                        output.close();
                    if ( this.clientSocket != null && !this.clientSocket.isClosed() )
                        this.clientSocket.close();
                }
                catch ( IOException e )
                {
                    e.printStackTrace();
                }
            }
        }
    }
}

Client端

public class Client
{
    public static void main( String[] args ) throws IOException
    {
        String host = "";
        int port = 5987;
        Socket socket = null;
        Scanner consoleInput = new Scanner( System.in );
        System.out.println("請輸入Server端位址");
        host = consoleInput.nextLine();
        try
        {
            socket = new Socket( host, port );
            DataInputStream input = null;
            DataOutputStream output = null;
            
            try
            {
                input = new DataInputStream( socket.getInputStream() );
                output = new DataOutputStream( socket.getOutputStream() );
                while ( true )
                {
                    System.out.println( input.readUTF() );
                    break;
                }
            }
            catch ( IOException e )
            {
            }
            finally 
            {
                if ( input != null )
                    input.close();
                if ( output != null )
                    output.close();
            }
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
        finally
        {
            if ( socket != null )
                socket.close();
            if ( consoleInput != null )
                consoleInput.close();
        }
    }
}

程式解說

  • ServerSocket serverSocket = new ServerSocket( port )當中的port使用上必須是唯一的,因為port是用來辨識電腦上每個獨立的服務,每個不同的服務所使用的port就會不同,可用的port範圍從0~65536,前1024個port是TCP/IP欲留著給一些特定協定使用(例如:HTTP=80, FTP=21),所以程式的port只能使用大於1024之後的整數。
  • Server端採用允許多個Client端連接的簡單多執行緒連線架構,其思路為每一個Client連線就用一個執行緒來處理,在ServerSocket.accept()呼叫後會回傳一個和目前Client連線的Socket,我們將此Socket傳遞給執行緒做後續的處理,而ServerSocket可以繼續listen()來達到多個Client連接的架構。
  • 程式當中是使用DataInput/OutputStream來處理IO資料傳遞,當然你可以照你的需求來使用不同的IO Stream。
  • 取得IO Stream後就可以依照你所定義的protocol來做資料的傳遞,程式當中是Server端回傳一個訊息給Client端,然後Client端取得後印出。