2019/04/16

Java JDOM2 Read / Write

XML如下:
<?xml version="1.0" encoding="UTF-8"?>
<list>
 <Student><name>王小明</name><en>50</en><ch>90</ch><math>80</math></Student>
<Student><name>陳小東</name><en>67</en><ch>70</ch><math>90</math></Student></list>


2019/03/29

Java POI 讀取整個Sheet以及寫入值至cell和取得公式計算後結果


用到的jar有以下幾個
poi-3.17.jar
poi-ooxml-3.17.jar
poi-ooxml-schemas-3.17.jar
commons-collections4-4.1.jar
xmlbeans-2.6.0.jar

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellReference;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;

/**
 * @see <a href="https://poi.apache.org/components/spreadsheet/index.html">POI-HSSF and POI-XSSF/SXSSF - Java API To Access Microsoft Excel Format Files</a>
 */
public class Excel {
    private boolean isExcel2003 = false;
    private Workbook workbook;
    private Sheet sheet;


    public Excel() throws IOException {
        this(Excel.class.getResource("test.xlsx").getPath());
    }

    public Excel(String path) throws IOException {
        this.isExcel2003 = (path.matches("^.+\\.(?i)(xls)$")) ? true : false;

        FileInputStream fileInputStream = new FileInputStream(path);
        if (this.isExcel2003) {
            this.workbook = new HSSFWorkbook(fileInputStream);
        } else {
            //2007
            this.workbook = new XSSFWorkbook(fileInputStream);
        }
        this.selectSheet(0);
    }

    public Sheet selectSheet(int index) {
        if (index < 0 || index > (this.getSheetsCount() - 1)) return null;
        this.sheet = this.workbook.getSheetAt(index);
        return this.sheet;
    }

    public int getSheetsCount() {
        return this.workbook.getNumberOfSheets();
    }

    public void readAllCell(int index) {
        this.selectSheet(index);

        Iterator<Row> rowIterator = this.sheet.rowIterator();
        while (rowIterator.hasNext()) {

            Row row = rowIterator.next();
            Iterator<Cell> cellIterator = row.cellIterator();
            while (cellIterator.hasNext()) {

                Cell cell = cellIterator.next();
                switch (cell.getCellTypeEnum()) {
                    case FORMULA:
                        System.out.println(cell.getCellFormula());
                        break;
                    case STRING:
                        System.out.println(cell.getStringCellValue());
                        break;
                    case NUMERIC:
                        System.out.println(cell.getNumericCellValue());
                        break;
                    case BOOLEAN:
                        System.out.println(cell.getBooleanCellValue());
                        break;
                    default:
                        break;
                }
            }
        }
    }

    public Object getCalculateRule(CellReference reference) {
        FormulaEvaluator evaluator = this.workbook.getCreationHelper().createFormulaEvaluator();
        Row row = this.sheet.getRow(reference.getRow());
        Cell cell = row.getCell(reference.getCol());
        CellValue value = evaluator.evaluate(cell);

        switch (value.getCellTypeEnum()) {
            case STRING:
                return value.getStringValue();
            case NUMERIC:
                return value.getNumberValue();
            case BOOLEAN:
                return value.getBooleanValue();
            default:
                return null;
        }
    }

    public void setValue(CellReference reference, Object v) {
        Row row = this.sheet.getRow(reference.getRow());
        if (row == null)
            row = sheet.createRow(reference.getRow());
        Cell cell = row.getCell(reference.getCol());
        if (v instanceof String)
            cell.setCellValue((String) v);
        else if (v instanceof Double)
            cell.setCellValue((Double) v);
        else if (v instanceof Boolean)
            cell.setCellValue((Boolean) v);
        else if (v instanceof Date)
            cell.setCellValue((Date) v);
        else if (v instanceof Calendar)
            cell.setCellValue((Calendar) v);
        else if (v instanceof RichTextString)
            cell.setCellValue((RichTextString) v);
    }

}

Java 讀寫YAML

要自定義格式要另外新增class而不要將class置於某個class內

SnakeYAML Maven:
<dependency>
 <groupId>org.yaml</groupId>
 <artifactId>snakeyaml</artifactId>
 <version>1.21</version>
</dependency>

User.class:
/**User*/
public class User{

    /**name*/
    private String name;
    /**age*/
    private int age;

    /**
     * @param name Name
     */
    public void setName(String name){this.name=name;}
    /**
     * @return name
     */
    public String getName(){return this.name;}
    /**
     * @param age Age
     */
    public void setAge(int age){this.age=age;}
    /**
     * @return age
     */
    public int getAge(){return this.age;}
    
}

user.yaml:
{age: 20, name: cyfang}


2019/03/28

Redis Cluster 3.0.2 on CentOS 7

這篇其實寫完很久,但一直忘記按發佈XD

Redis Cluster是Redis用於解決分散式的方案,又稱為Redis叢集
是一個讓數據再多個Node之間相互傳輸的服務,Redis Cluster的優勢主要有以下兩個點

  1. 自動分割數據到不同Node
  2. 部分Node當機或不可用情況能夠繼續維持服務


不過Redis Cluster並不支持處理多個keys的命令,在不同Node移動數據並不像Redis那樣高性能,高負載時有可能會遇到不可預期錯誤
Redis Cluster並非採用Consistent Hashing而是用Hash Slots,它其實就是代表一個Keys的集合
Redis Cluster共有16384 Hash Slots,將Key做CRC16校驗接著Mod 16384決定Key會放置於哪個Slot,Redis Cluster每個Node負責一部分的Hash Slots。例如,目前Cluster中有三個Master Node,則:

  • Node A包含0到3000 Hash Slots
  • Node B包含3001到9000 Hash Slots
  • Node C包含9001到16383 Hash Slots

如果新增了Node D,僅需將原本Node上的Hash Slots添加至Node D上;相對的要刪除一個Node A,將Node A上的Hash Slots遷移至Node B / C / D上,再將沒有任何Hash Slots的Node A移除即可;且新增、刪除或搬遷Hash Slots時無須停止任何服務。

Redis Cluster為了使部分Node失敗或大部分的Node無法通訊時仍可以使用,Redis Cluster使用Master-Slave複製模型,則每個Master Node則最少有會1個Slave Node;以上述的例子而言,如果沒有使用該模型的情況下,Node A失效則會導致Cluster因0到3000的Hash Slots不可用而失效。
最後Redis Cluster並不保證數據的一致性,這也意味著Redis Cluster在特定條件下有可能會丟失數據。


讓我們開始來建置Redis Cluster吧

接著我們開始來建立Redis Cluster吧,根據官方文獻建置一個Redis Cluster最少需要三個Master,也意味著還需要三個Slave來確保每個Master失效時才能將角色轉移至Slave上。
所以需先準備6台Host或container,系統為CentOS 7 minimal


Name

IP

Port

Cluster BUS Port

Master 1

192.168.126.135

6379

16379

Master 2

192.168.126.136

6380

16380

Master 3

192.168.126.141

6381

16381

Slave 1

192.168.126.142

6382

6382

Slave 2

192.168.126.143

6383

6383

Slave 3

192.168.126.144

6384

6384

Java 下載檔案並開啟檔案

今天有前輩再問應該如何用steam下載檔案,下載後將其開啟
隨便找篇ppt來當下載的來源
如果你是該作者覺得這樣很不妥歡迎跟我聯繫xd


import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

public class Test {
    public static void main(String []args) throws InterruptedException, NoSuchAlgorithmException, IOException, KeyManagementException {
        downloadFile("https://c.nknu.edu.tw/affair/UploadFile/Files/Files/envedu_1117163234.ppt");
    }

    private final static String CMD = "rundll32 url.dll,FileProtocolHandler %s";

    public static void openFile(String path) throws IOException, InterruptedException {
        if (new File(path).exists() == false) throw new IOException("No File");
        Process process = Runtime.getRuntime().exec(String.format(CMD, path));
        process.waitFor();
    }

    private final static String DOWNLOAD_FOLDER = "C:/Users/C.Y.Fang/Downloads/%s";

    public static void downloadFile(String url) throws IOException, NoSuchAlgorithmException, InterruptedException,  KeyManagementException {
        String[] array = url.split("/");
        String fileName = array[array.length - 1];
        array = null;
        System.out.println(fileName);
        boolean isHttps = url.toUpperCase().contains("HTTPS") ? true : false;


        if (isHttps) {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        }

        URL u = new URL(url);
        ReadableByteChannel readableByteChannel = Channels.newChannel(u.openStream());
        String path = String.format(DOWNLOAD_FOLDER, fileName);
        FileOutputStream fileOutputStream = new FileOutputStream(path);
        fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
        fileOutputStream.flush();
        fileOutputStream.close();
        fileOutputStream = null;
        readableByteChannel.close();
        readableByteChannel = null;
        openFile(path);
    }

    static TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }
    };
}


執行結果:


參考資料:
https://docs.microsoft.com/zh-tw/windows/desktop/api/shellapi/nf-shellapi-shellexecutea
https://confluence.atlassian.com/stashkb/could-not-generate-dh-keypair-on-ssl-715129360.html