顯示具有 Java 標籤的文章。 顯示所有文章
顯示具有 Java 標籤的文章。 顯示所有文章

2018年2月3日 星期六

「HTML5][Java] Server-Sent Events

Server-Sent Events

W3Schools上的說明:

server-sent event is when a web page automatically gets updates from a server.
This was also possible before, but the web page would have to ask if any updates were available. With server-sent events, the updates come automatically.
Examples: Facebook/Twitter updates, stock price updates, news feeds, sport results, etc.


簡單來說SSE的特點為"One Way Messaging" ,也就是Client端被動接收Server端訊息。

過去HTTP 都是一個單一回合結束,如果要取得新的資料,必須重新發送一次

HTTP Request,而SSE則是可以持續接收Server資訊,無須主動發送Request ,

但Client端無法透過SSE與Server端進行溝通,這是與webSocket不同的地方。

以下有一個範例,利用Java Servlet 透過SSE的方式與Client端JavaScript溝通.

當下按Start Button後,JavaScript會開始接收由Server端傳送過來的SSE資料,並更新

在網頁上。

Client端程式碼
<!DOCTYPE HTML>
<html>
    <head>
        <title>Server-Sent Events Servlet example</title>
        <script>
            function start() {
                var eventSource = new EventSource("Server");
                eventSource.onmessage = function (event) {
                    document.getElementById('myDiv').innerHTML = event.data;
                }
            }
            ;

        </script>
        <style>
            body {
                font-family: sans-serif;
            }
        </style>
    </head>
    <body>

        Time: <span id="myDiv"></span>

        <br><br>
        <button onclick="start()">Start</button>


    </body>
</html>


Server端Servlet程式碼
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author boywhychen
 */
public class Server extends HttpServlet {

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("UTF-8");

        PrintWriter writer = response.getWriter();

        for (int i = 0; i < 20; i++) {

            writer.write("data: " + getTime() + "\n\n");
            writer.flush();

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        writer.close();
    }

    private String getTime() {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        return sdf.format(cal.getTime());
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}


參考資料來源:

https://gist.github.com/viralpatel/7007662

2017年3月16日 星期四

[Java] Transpose Array

Transpose Array :

將Array的 由橫向變成縱向(相反亦同)。

Ex:

1 2 3 4
5 6 7 8 
9 10 11 12

 
變成
1 5 9 
2 6 10
3 7 11 
4 8 12

範例程式碼如下:


public class Testtranspose
{  
  public static void main(String[] args)
  {
    
    final int[][] original = new int[][] { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
        for (int i = 0; i < original.length; i++) {
            for (int j = 0; j < original[i].length; j++) {
                System.out.print(original[i][j] + " ");
            }
            System.out.print("\n");
        }
        int[][] tranposeArray=transpose(original) ;
     for (int i = 0; i < original[0].length; i++) {
                for (int j = 0; j < original.length; j++) {
                    System.out.print(original[j][i] + " ");                   
                }
                System.out.print("\n");
            }
   }
  
  public static int[][] transpose(int[][] original) {

        int[][] transposeArray=new int[original[0].length][original.length];
        System.out.print("\n\n matrix transpose:\n");
        // transpose
        if (original.length > 0) {
            for (int i = 0; i < original[0].length; i++) {
                for (int j = 0; j < original.length; j++) {                  
                   transposeArray[i][j]=original[j][i];
                }
            }
        }
     return transposeArray;
    }
}


參考資料來源:
http://stackoverflow.com/questions/8422374/java-multi-dimensional-array-transposing

2016年12月20日 星期二

[Java] For的陷井

今天在用迴圈時,發現一個現像,紀錄下來

以下這段程式碼A


public static void main(String[] args) {
        
        String[] date=new String[]{"a'","'b"};
     
        for( String str : date)
        {
            str=str.replace("'", "");
        }
        
        for( String str : date)
        {
            System.out.println(str);
        }
               
    }

輸出結果為

a'
'b


而以下這段程式碼B


 public static void main(String[] args) {
        
        String[] date=new String[]{"a'","'b"};
     
        for( int i=0;i<date.length;i++)
        {
            date[i]=date[i].replace("'", "");
        }
        
        for( String str : date)
        {
            System.out.println(str);
        }
               
    }

輸出結果為

a
b


我們發現A程式並沒有實際去改變date陣列中的值,而B程式碼會。

我們再看一下以下這段程式碼C ,比較物件的記憶體位址 ,在未進行replace前,

str與date[index]記憶體位址是相同的,但進行replace後,重新設定了str的值,對

foreach來說,改變它的值,相當於重新new一塊記憶體位址,而不是去改變原本記憶體位

所以原本位置的值是不會改變的。


    public static void main(String[] args) {
        
        String[] date=new String[]{"a'","'b"};
     
        int index=0;
        for( String str:date)
        {   
           System.out.println("index="+ index+  " address equals: "+ (str == date[index]));
        
           str=str.replace("'", "");
           
           System.out.println("index="+ index+  " address equals: "+ (str == date[index]));
           index++;
        }
        
        for( String str : date)
        {
            System.out.println(str);
        }
               
    }

輸出結果如下:

index=0 address equals: true
index=0 address equals: false
index=1 address equals: true
index=1 address equals: false
a'
'b


如果我們把String 改成int呢


public static void main(String[] args) {
        
        int[] date=new int[]{1,2};
     
        int index=0;
        for( int str:date)
        {   
           System.out.println("index="+ index+  " address equals: "+ (str == date[index]));
        
           str=str+10;
           
           System.out.println("index="+ index+  " address equals: "+ (str == date[index]));
           index++;
        }
        
        for( int str : date)
        {
            System.out.println(str);
        }
               
    }

輸出結果如下

index=0 address equals: true
index=0 address equals: false
index=1 address equals: true
index=1 address equals: false
1
2


即使是int,依然是無法修改,原因在於JAVA For Each做法


是將陣列中的值,依序COPY到 str中,但你改變str時 ,則會另外配置一塊記憶體。


使用Foreach處理陣列時,需注意這一個限制。


參考下列連結:

http://chris800731.blogspot.tw/2013/08/javaforeach-foreach-in-java.html


2016年2月7日 星期日

[java] 繞著圓心走的同心圓座標

之前有寫一篇,怎樣算出一個繞著一點走的圓,

接下來我用程式來實現,程式在座標的計算上與數學常用的座標不太一樣。



//半徑
int r = 150;
//座標的矩陣
slidepoint = new int[360][2];
//圓心位址
int x0 = 225;
int y0 = 225;
//計算
for (int i = 1; i < 361; i++) {
    int x1 = (int) (x0 + r * Math.cos(Math.toRadians(i)));
    int y1 = (int) (y0 + r * Math.sin(Math.toRadians(i)));

   slidepoint[360 - i][0] = x1;
   slidepoint[360 - i][1] = y1;
  //draw angle string
   if (i % 10 ==0)
 g.drawString(String.valueOf(i), x1, y1);
}


我先用swing做個示範,每隔10度畫出角度在座標上









































你會發現跟我們習慣的角度好像方向不同,我們做個轉換



class DrawPane extends JPanel {
  public void paintComponent(Graphics g) {
                      //畫大圓
   g.drawOval(0, 0, 450, 450);
                       //大圓
   int r = 150;
                        //座標的矩陣
   slidepoint = new int[360][2];
                        //圓心位址
   int x0 = 225;
   int y0 = 225;
                       //計算
   for (int i = 1; i < 361; i++) {
             int x1 = (int) (x0 + r * Math.cos(Math.toRadians(i)));
      int y1 = (int) (y0 + r * Math.sin(Math.toRadians(i)));

    slidepoint[360 - i][0] = x1;
    slidepoint[360 - i][1] = y1;
    
   }
                        //轉換
   for (int i = 0; i < 360; i++) {
    int x1 = slidepoint[i][0];
    int y1 = slidepoint[i][1];
                                //繪圓
    if (i%10==0)
     g.drawString(String.valueOf(i), x1, y1);
   
   }

  }
 }






2015年12月14日 星期一

[Java] Java Read EXIF

Java 讀取數位相片EXIF檔的程式碼
package exif;


import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.imaging.jpeg.JpegProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author flowercatswets
 */
public class Exif {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        File jpegFile = new File("/Users/flowercatswets/Desktop/test/P1080033.JPG");  
    
    Metadata metadata = null;  
        try {
            metadata = JpegMetadataReader.readMetadata(jpegFile);
            print(metadata);
        } catch (JpegProcessingException ex) {
            Logger.getLogger(Exif.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Exif.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
    
     private static void print(Metadata metadata)
    {
        System.out.println("-------------------------------------");

      
        for (Directory directory : metadata.getDirectories()) {

          
            for (Tag tag : directory.getTags()) {
                System.out.println(tag);
                
               // String tagName= tag.getTagName();
                //String tagDes=tag.getDescription();
                
            }

            //
            // Each Directory may also contain error messages
            //
            if (directory.hasErrors()) {
                for (String error : directory.getErrors()) {
                    System.err.println("ERROR: " + error);
                }
            }
        }
    }
    
}


但是要先去拉一個專案的code下來

https://github.com/drewnoakes/metadata-extractor

Netbean滙不進這一個專案,所以我把裡面的Source資料夾下的程式碼COPY到

專案中,讓import可以正常,接下來找一張相片。

執行一下輸出結果

-------------------------------------
[JPEG] Compression Type - Baseline
[JPEG] Data Precision - 8 bits
[JPEG] Image Height - 3000 pixels
[JPEG] Image Width - 4000 pixels
[JPEG] Number of Components - 3
[JPEG] Component 1 - Y component: Quantization table 0, Sampling factors 1 horiz/1 vert
[JPEG] Component 2 - Cb component: Quantization table 1, Sampling factors 1 horiz/1 vert
[JPEG] Component 3 - Cr component: Quantization table 1, Sampling factors 1 horiz/1 vert
[JFIF] Version - 1.1
[JFIF] Resolution Units - none
[JFIF] X Resolution - 1 dot
[JFIF] Y Resolution - 1 dot
[JFIF] Thumbnail Width Pixels - 0
[JFIF] Thumbnail Height Pixels - 0
[Exif IFD0] Make - Panasonic
[Exif IFD0] Model - DMC-GF2
[Exif IFD0] Orientation - Top, left side (Horizontal / normal)
[Exif IFD0] Software - iPhoto 9.5.1
[Exif IFD0] Date/Time - 2014:07:13 16:31:27
[Exif SubIFD] Exposure Time - 1/400 sec
[Exif SubIFD] F-Number - f/10.0
[Exif SubIFD] Exposure Program - Program normal
[Exif SubIFD] ISO Speed Ratings - 100
[Exif SubIFD] Exif Version - 2.30
[Exif SubIFD] Date/Time Original - 2014:07:13 16:31:27
[Exif SubIFD] Date/Time Digitized - 2014:07:13 16:31:27
[Exif SubIFD] Components Configuration - YCbCr
[Exif SubIFD] Compressed Bits Per Pixel - 2 bits/pixel
[Exif SubIFD] Exposure Bias Value - 0 EV
[Exif SubIFD] Max Aperture Value - f/5.6
[Exif SubIFD] Metering Mode - Multi-segment
[Exif SubIFD] White Balance - Unknown
[Exif SubIFD] Flash - Flash did not fire, auto
[Exif SubIFD] Focal Length - 42 mm
[Exif SubIFD] FlashPix Version - 1.00
[Exif SubIFD] Color Space - sRGB
[Exif SubIFD] Exif Image Width - 4000 pixels
[Exif SubIFD] Exif Image Height - 3000 pixels
[Exif SubIFD] Sensing Method - One-chip color area sensor
[Exif SubIFD] File Source - Digital Still Camera (DSC)
[Exif SubIFD] Scene Type - Directly photographed image
[Exif SubIFD] Custom Rendered - Normal process
[Exif SubIFD] Exposure Mode - Auto exposure
[Exif SubIFD] White Balance Mode - Auto white balance
[Exif SubIFD] Digital Zoom Ratio - Digital zoom not used
[Exif SubIFD] Focal Length 35 - 84 mm
[Exif SubIFD] Scene Capture Type - Standard
[Exif SubIFD] Gain Control - None
[Exif SubIFD] Contrast - None
[Exif SubIFD] Saturation - None
[Exif SubIFD] Sharpness - None
[Xmp] XMP Value Count - 8
[Xmp] Lens - LUMIX G VARIO 14-42/F3.5-5.6  
[Xmp] Serial Number - F931109140259
[ICC Profile] Profile Size - 560
[ICC Profile] CMM Type - ADBE
[ICC Profile] Version - 2.1.0
[ICC Profile] Class - Display Device
[ICC Profile] Color space - RGB
[ICC Profile] Profile Connection Space - XYZ
[ICC Profile] Profile Date/Time - 星期六 八月 12 03:51:59 +08:00 2000
[ICC Profile] Signature - acsp
[ICC Profile] Primary Platform - Apple Computer, Inc.
[ICC Profile] Device manufacturer - none
[ICC Profile] XYZ values - 0.964 1 0.825
[ICC Profile] Tag Count - 10
[ICC Profile] Copyright - Copyright 2000 Adobe Systems Incorporated
[ICC Profile] Profile Description - Adobe RGB (1998)
[ICC Profile] Media White Point - (0.9505, 1, 1.0891)
[ICC Profile] Media Black Point - (0, 0, 0)
[ICC Profile] Red TRC - 0.0085908
[ICC Profile] Green TRC - 0.0085908
[ICC Profile] Blue TRC - 0.0085908
[ICC Profile] Red Colorant - (0.6097, 0.3111, 0.0195)
[ICC Profile] Green Colorant - (0.2053, 0.6257, 0.0609)
[ICC Profile] Blue Colorant - (0.1492, 0.0632, 0.7446)
[Photoshop] Caption Digest - 30 46 141 110 6 218 48 251 230 96 58 140 160 40 46 157
[IPTC] Coded Character Set - UTF-8
[IPTC] Application Record Version - 2
[IPTC] Digital Time Created - 16:31:27
[IPTC] Digital Date Created - 星期日 七月 13 00:00:00 +08:00 2014
[IPTC] Special Instructions - jyVgAHzDQNCOpuAZrUdFnQ
[IPTC] Date Created - 星期日 七月 13 00:00:00 +08:00 2014
[IPTC] Time Created - 16:31:27
[File] File Name - P1060712.JPG
[File] File Size - 9306586 bytes
[File] File Modified Date - 星期二 七月 15 23:28:01 +08:00 2014

參考資料來源:

https://github.com/drewnoakes/metadata-extractor

2015年11月18日 星期三

[Java]透過Java hidAPI來取得usb裝置資訊

his is JNI wrapper around C/C++ HIDAPI library providing simple java API to work with devices such as USB gamepads, joysticks, keyboards, mice on Mac, Linux and Windows.

它是一個將C/C++ HID API library 透過JNI包裝成JAVA可以使用的API,

並且可以在Mac , Linux以及Windows上運作,可以偵測的裝置例如

遊戲搖桿,鍵盤, 滑鼠等等。


首先下載Java HidAPI

https://code.google.com/p/javahidapi/downloads/list

將jar檔加入專案,撰寫以下程式碼


import com.codeminders.hidapi.HIDDeviceInfo;
import com.codeminders.hidapi.HIDManager;
public class JavaApplication37 {

 
    
    public JavaApplication37()
    {
     
    }
    public static void main(String[] args) {

      try {
            com.codeminders.hidapi.ClassPathLibraryLoader.loadNativeHIDLibrary();
            HIDManager hidManager = HIDManager.getInstance();
            HIDDeviceInfo[] infos = hidManager.listDevices();
            for (HIDDeviceInfo info : infos) {
                System.out.println("info: " + info.toString());
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

輸出結果如下

info: HIDDeviceInfo [path=USB_05ac_8242_0x7fab6b40fc50, vendor_id=1452, product_id=33346, serial_number=, release_number=256, manufacturer_string=Apple, Inc., product_string=Apple IR, usage_page=12, usage=1, interface_number=-1]

info: HIDDeviceInfo [path=USB_046d_c52b_0x7fab6b623d40, vendor_id=1133, product_id=50475, serial_number=, release_number=9216, manufacturer_string=Logitech, product_string=USB Receiver, usage_page=1, usage=6, interface_number=-1]

info: HIDDeviceInfo [path=, vendor_id=0, product_id=0, serial_number=, release_number=0, manufacturer_string=, product_string=Apple Mikey HID Driver, usage_page=12, usage=1, interface_number=-1]

info: HIDDeviceInfo [path=USB_046d_c52b_0x7fab6b622cb0, vendor_id=1133, product_id=50475, serial_number=, release_number=9216, manufacturer_string=Logitech, product_string=USB Receiver, usage_page=65280, usage=1, interface_number=-1]

info: HIDDeviceInfo [path=USB_046d_c52b_0x7fab6b623490, vendor_id=1133, product_id=50475, serial_number=, release_number=9216, manufacturer_string=Logitech, product_string=USB Receiver, usage_page=1, usage=2, interface_number=-1]


環境:

OS X 10.10

java version "1.8.0_40-ea"

Netbeans  IDE 8.0.1

2015年9月10日 星期四

[Java] 好題目3

有1、2、3、4個數字,能組成多少個互不相同且無重複數字的三位元數?

並輸出各種組合?

程式碼如下

int i,j,k;
int count=0;
System.out.print("\n");
for (i=1;i<5;i++)
{
 for(j=1;j<5;j++)
 {
  for (k=1;k<5;k++)
  {
   if (i!=k && i!=j && j!=k)
   {
                           System.out.printf("%d,%d,%d\n",i,j,k);
       count++;
   }
  }
 }
}
System.out.println("total:" + count);

執行結果
2,3,4                                                                                                                                                    
2,4,1                                                                                                                                                    
2,4,3                                                                                                                                                    
3,1,2                                                                                                                                                    
3,1,4                                                                                                                                                    
3,2,1                                                                                                                                                    
3,2,4                                                                                                                                                    
3,4,1                                                                                                                                                    
3,4,2                                                                                                                                                    
4,1,2                                                                                                                                                    
4,1,3                                                                                                                                                    
4,2,1                                                                                                                                                    
4,2,3                                                                                                                                                    
4,3,1                                                                                                                                                    
4,3,2                                                                                                                                                    
total:24   

題目來源:

http://stenlyho.blogspot.tw/2007/04/c100-1-10.html

2015年8月10日 星期一

「Java」將數值IP轉成字串IP

當某些情況,我們取得的IP位置輸出是一個整數值,如下



WifiManager wifi_service = (WifiManager)getSystemService(WIFI_SERVICE);
 //取得wifi資訊
 WifiInfo wifiInfo = wifi_service.getConnectionInfo();
 //取得IP,會是一個數字
int ipAddress = wifiInfo.getIpAddress();

此時我們要將數值轉換成標準的IP格式,可以透過下列程式碼做轉換



 String ip = String.format("%d.%d.%d.%d",(ipAddress & 0xff),(ipAddress >> 8 & 0xff),(ipAddress >> 16 & 0xff),(ipAddress >> 24 & 0xff));

參考來源:

http://blog.johnsonlu.org/android%E5%8F%96%E5%BE%97wifi-ip/

[Java] Regux判定IP


public class JavaApplication37 {

    private Pattern pattern;
    private Matcher matcher;

    private static final String IPADDRESS_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
   + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
   + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
    
    public JavaApplication37()
    {
        pattern = Pattern.compile(IPADDRESS_PATTERN);
    }
    public static void main(String[] args) {

        JavaApplication37 java7=new JavaApplication37();
        
        String testIP1="192.168.2.100";
        String testIP2="256.100.122.199";
        
       System.out.println("IP1 " +java7.validateIP(testIP1));
       System.out.println("IP2 " +java7.validateIP(testIP2));
    }

    public boolean validateIP(final String ip) {
  matcher = pattern.matcher(ip);
  return matcher.matches();
 }
}


輸出結果:

IP1 true
IP2 false

因為testIP2有一個值大於255, 並不合法。