Total Pageviews

2019/12/03

[Java] FTP Client Example

This example will demonstrate how to connect, list files, upload / download / delete file, and disconnect from FTP server.

Add commons-net to your pom.xml
    <dependency>
        <groupId>commons-net</groupId>
        <artifactId>commons-net</artifactId>
        <version>3.6</version>
    </dependency>


FtpService
package test.service;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class FtpService {

    @Value("${ftp.host}")
    private String host;

    @Value("${ftp.port}")
    private Integer port;

    @Value("${ftp.user}")
    private String user;

    @Value("${ftp.password}")
    private String password;

    private FTPClient client;

    /**
     * Obtain a list of file information for specific working directory.
     * 
     * @param directory
     *            specific working directory
     * @return list of file
     * @throws IOException
     */
    public List<String> listFiles(String directory) throws IOException {
        FTPFile[] files = null;
        try {
            connect();

            files = client.listFiles(directory);

            if (files == null || files.length == 0) {
                throw new IllegalArgumentException("cannot find any files in " + directory);
            }
        } catch (IOException e) {
            throw new IOException("fail to list files", e);
        } finally {
            disconnect();
        }
        return Arrays.stream(files).map(FTPFile::getName).collect(Collectors.toList());
    }

    /**
     * Stores a file on the server using the given name.
     * 
     * @param directory
     *            specific working directory
     * @param file
     *            local file
     * @throws IOException
     */
    public void uploadFile(String directory, File file) throws IOException {
        try (InputStream is = new FileInputStream(file);) {
            connect();

            client.changeWorkingDirectory(directory);
            client.storeFile(new String(file.getName().getBytes(), "iso-8859-1"), is);
        } catch (IOException e) {
            throw new IOException("fail to upload file", e);
        } finally {
            disconnect();
        }
    }

    /**
     * Retrieves a named file from the server.
     * 
     * @param directory
     *            specific working directory
     * @param remoteFileName
     *            remote file name
     * @param downloadFile
     *            local file
     * @throws IOException
     */
    public void downloadFile(String directory, String remoteFileName, File downloadFile)
            throws IOException {
        try (OutputStream outputStream1 = new BufferedOutputStream(
                new FileOutputStream(downloadFile));) {
            connect();

            client.retrieveFile(directory + "/" + new String(remoteFileName.getBytes(), "iso-8859-1"),
                    outputStream1);
        } catch (IOException e) {
            throw new IOException("fail to download file", e);
        } finally {
            disconnect();
        }
    }

    /**
     * Delete file from FTP server.
     * 
     * @param directory
     *            specific working directory
     * @param remoteFileName
     *            remote file name
     * @throws IOException
     */
    public void deleteFile(String directory, String remoteFileName) throws IOException {
        try {
            connect();
            client.changeWorkingDirectory(directory);
            client.deleteFile(new String(remoteFileName.getBytes(), "iso-8859-1"));
        } catch (IOException e) {
            throw new IOException("fail to delete file from FTP server", e);
        } finally {
            disconnect();
        }
    }

    /**
     * Connect to FTP server.
     * 
     * @throws IOException
     */
    private void connect() throws IOException {
        try {
            client = new FTPClient();
            client.addProtocolCommandListener(
                    new PrintCommandListener(new PrintWriter(System.out), true));
            
            client.connect(host, port);
            int reply = client.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                client.disconnect();
                throw new IOException("Exception in connecting to FTP Server");
            }

            client.login(user, password);
            client.enterLocalPassiveMode();
            client.setFileType(FTP.BINARY_FILE_TYPE);

            log.debug("connect to FTP server succesfully");
        } catch (IOException e) {
            throw new IOException("fail to connect to FTP server", e);
        }
    }

    /**
     * Disconnect from FTP server.
     * 
     * @throws IOException
     */
    private void disconnect() throws IOException {
        try {
            if (client.isConnected()) {
                client.logout();
                client.disconnect();
            }
            log.debug("disconnect from FTP server succesfully");
        } catch (IOException e) {
            throw new IOException("fail to disconnect from FTP server", e);
        }
    }

}


Client code
package test;

import java.io.File;
import java.util.List;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import lombok.extern.slf4j.Slf4j;
import test.service.FtpService;

@SpringBootApplication
@Slf4j
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    @Bean
    CommandLineRunner run(FtpService svc) {
        return args -> {
            // list files
            List<String> files = svc.listFiles("/tcpb");
            files.forEach(f -> log.debug(f));
            
            // upload file
            svc.uploadFile("/tcpb", new File("C:\\中文測試.zip"));
            
            // download file
            svc.downloadFile("/tcpb", "中文測試.zip", new File("C:\\中文測試1.zip"));
            
            // delete file
            svc.deleteFile("/tcpb", "中文測試.zip");
        };
    }
}






2019/12/02

[閱讀筆記] 情緒勒索:那些在伴侶、親子、職場間,最讓人窒息的相處 (5/5)

  1. 切記,「情緒界線」不是「情緒底線」。界線,是幫助你知道,與人互動時,哪些是你的「範圍領土」。你要找到的,是開始會讓你覺得不舒服的那條線,往內都是「情緒界線」的範圍,而不是拉了一條你的「情緒底線」,彷彿僅設一條盡量忍受的底限,而使得這底線成為讓人一踩到就會爆炸的線。
  2. 你可以隨著你的狀況與需求,彈性調整自己的「界線」,這也可以讓你與人的互動比較有彈性,而非只能仰賴僵化的界線,這就是「情緒界線」與「情緒底線」的差別
  3. 別人否定你的感受,已經是一件很令人難過、受傷的事情,如果連你都懷疑、甚至否定你自己的感受、不能捍衛你自己的感受,這是多麼令人心疼的事情
  4. 擺脫情緒勒索,就是從建立你的「情緒界線」開始,而要建立「情緒界線」,就是從尊重你的自己的感受開始
  5. 好好地去感受你情緒。那些被迫,那些委屈,那些感覺自己沒有價值、不被重視的感受,甚至覺得自己的感受沒有任何在乎的傷痛。請不要忽略它,不要合理化、淡化這些傷口,好好感受這些傷。從感受的過程中,了解這些傷的嚴重性,讓自己有機會深深地理解:「沒有人應該被這樣對待。」
  6. 很多時候,當我們不習慣重視自己的感受,別人也會如此的對待我們
  7. 我們需要為自己的行為,但是,我們不需要為別人的情緒負責
  8. 練習把自己的情緒感受放在第一位,不代表我們不能溝通、不能妥協,而是希望別人用尊重我們的方式,與我們討論事情的進行方法
  9. 我們人生唯一最重要的事情與義務,是在不傷害他人權益的前提下,重視自己的感受,滿足自己的需求,而非僅為了滿足他人期待而活
  10. 練習建立情緒界線的步驟
    1. 停:停止對話、轉移情緒、離開現場
    2. 看:察覺自己的情緒、了解剛剛發生什麼事情
    3. 應:擬訂策略、練習並應用
  11. 情緒勒索者與你的互動循環:
    1. 情緒勒索者給予你壓力
    2. 你因壓力而產生內在焦慮
    3. 你因為內在焦慮而忽略自己的感受
    4. 答應情緒勒索者的要求
  12. 你不必回應情緒勒索者的任何要求,如果你想答應這件事,並非因為你「想要」,而是因為你覺得「害怕、恐懼」。請你先等一下,請給自己一點思考時間。你並不需要非得馬上回應,甚至答應情緒勒索者的任何要求。
  13. 情緒勒索者常會要求你當場決定,要記得,你現在就是沒有辦法馬上做出決定,請堅持你的立場,這是不需要理由的。你不需要去說服對方,不需要說服他「接受」你現在「沒辦法做決定」這件事。你只需要告知,但是你不需要得到任何人的允許
  14. 完成「停」的步驟,進入「看」的步驟,你必須清楚看見,情緒勒索者是如何在我們身上,貼上我們在意的、不喜歡的標籤。當對方貼標籤在我們身上時,只要我們清楚這是他們的手段,我們也清楚,這不是我們的樣子。那麼,我們不需要花時間去辯解、去說服對方,也不需要去做些什麼,以證明我們不是像他們想的那樣。
  15. 真正讓我們痛苦的,是我們不相信這些標籤,卻又不敢擺脫它,反而一直想要與對方辯解,或做出一些行為,讓對方撕下標籤。我們給予別人權力,讓別人有辦法定義、標籤我們,卻忘了:其實,我們自己才有定義自己的權利;當然,我們自己也有撕下標籤的能力
  16. 練習向情緒勒索者表達自己的感受,以促成正向的互動循環。很多時候,情緒勒索者並不是一個純粹的「加害者」。其實,他們只是希望滿足自己的需求,只是過去他們學到滿足需求的方式,是「情緒勒索」。有時候,他們並沒有意識這樣的行為會帶給別人傷害,因為他們也被自己的焦慮綁架了。
  17. 重視自我感受與需求,不代表自私如果你一味地要求別人也要符合你的想法與要求,藉此滿足你的需求,甚至不惜侵犯對方的界線,貶低對方已達到你的目的,這才是自私。
  18. 你要讓你的行為,是出於自發,是自我有意識地選擇,而非出自於害怕與恐懼
  19. 當你安撫自己的罪惡感與焦慮後,「滿足別人的需求」不再是一種飽含罪惡感的習慣,而是一種有意識的選擇。當這選擇權在於我「想不想要」,而非「我害不害怕時」,就會感覺自己對自己是有主導權的。當我想要,我也做得到時,我可以感覺自己很棒,也可以從中感覺到成就感、滿足感與愛。
  20. 在關係中,如果你總是因為對方的情緒勒索,而答應、屈服於對方的要求,慢慢地,你只會感覺這段關係、這個人給你很大的壓力。當你總是處在「害怕」的情緒裡,你很難在這段關係中,真正感受到「在乎與愛」。當你為對方做些什麼,其實都不是因為你「愛」對發而自願去做,而是因為「害怕」時,你會與對方漸行漸遠,最後,這段關係就會變成「沒有愛的壓迫關係」
  21. 擺脫情緒勒索,絕對不是自私,而是為了讓我們能夠更純粹的感受到關係中的「愛」,這才是關係中最重要的元素。我們想要好好的「愛」對方,想要好好經營這段關係,而非只是因為害怕、恐懼,所以屈服

2019/12/01

[閱讀筆記] 情緒勒索:那些在伴侶、親子、職場間,最讓人窒息的相處 (4/5)

  1. 「討好、逃避、說服、憤怒」,這些情緒逃避策略,其實都與我們習慣承擔他人情緒責任,而沒有意識到「他人的情緒是他的責任」的思考有關。一旦開始能夠把情緒責任還給對方,我們也就越來越能尊重對方的感受。尤其是,當對方情緒不好時,就算與你有關,也不是你的責任。他需要自己練習與妳溝通,說出他的感受,讓你們有機會討論,調整彼此間的互動關係
  2. 面對他人負面情緒時,停在當下,告訴自己:「那是他的情緒,是他的責任,不是我的,與我無關。」讓自己練習忍受心裡覺得「一定要做些什麼」的焦慮感。如果很困難,你可以暫時離開現場,或是找一間你有興趣的事情,讓你的注意力,可以從對方的情緒轉移到你自己專注做的事情上。
  3. 你一定要好好的尊重自己。尊重自己從了解、尊重並接納自己的感受開始。學著不否定自己的感受,練習負起自己的情緒責任;同樣地,你也要尊重他人的感受,並且讓他人負起自己的情緒責任
  4. 你有選擇,可以決定你要怎麼做,而不是「非要」滿足他人需求不可。你可以為你自己做主,為你的人生做主
  5. 為什麼我們會無法擺脫情緒勒索,其原因有二
    1. 可能是你根深蒂固的恐懼、焦慮與害怕的情緒太強
    2. 你太過在乎別人的感受,被這些焦慮與害怕,引發你「習慣性的罪惡感」
  6. 一般的罪惡感 vs. 習慣性的罪惡感
    1. 一般的罪惡感
      1. 是在我們做錯事時出現,它的出現是提醒我們可以彌補,可以讓我們與其他人的關係變得更好,是維持這個社會秩序的一個重要情緒
      2. 是一種「利他」的情緒,因為有這個「罪惡感」,使得社會的道德秩序能夠有相當的維持,是一種「被教導」而形成的感受
    2. 習慣性的罪惡感
      1. 讓我們以為做錯事,但實際上沒有。這種罪惡感,只是我們從小到大養成的一種習慣。一旦我們沒有符合別人期待,達成別人要求的時候,就會跑出來
      2. 是一種被教導、訓練而成的,是一種「過度利他」的情緒
      3. 如同孫悟空的緊箍咒,當想要重視自己的需求,甚至覺得自己是對的時候,習慣性的罪惡感就會被立即召喚出來。一旦違抗這種教條與情緒,就會感到極大的焦慮,使得最後你仍屈服於別人的期待與需求中
  7. 情緒勒索的三元素:貶低你的能力、引發你的罪惡感、威脅你的安全感
  8. 擺脫情緒勒索的第一步,就是從自我察覺開始,問問自己
    1. 是誰決定這個教條與信念?
    2. 我非得按照這些教條與信念過活嗎?
    3. 如果不遵守這些教條與信念,最糟會發生什麼事情?我能否處理與面對?
    4. 當我「違反」這些教條與信念時,我內心的感受如何?
    5. 客觀而言,如果違反這些教條,後果真的有我想像的那麼嚴重嗎?
    6. 如果不確定後果,嘗試問問自己身邊可以信任的他人,問問他們的看法與意見
  9. 許多深陷情緒勒索關係的被勒索者,常具有「在意別人評價」的特質,有著「自省」的能力與習慣。適當的自省,對我們的人生其實是有幫助的,讓我們有機會對自己的行為做適當地修正,但「過度的自省與自責無異」。
  10. 被勒索者總是擔心自己對不起別人,但是,你對得起自己嗎?你應該看一下,深埋在你內心深處的委屈與傷痛。
  11. 情緒勒索對我們的影響
    1. 失去自尊
    2. 自我懷疑
    3. 對自己失望
    4. 忽略自我
    5. 合理化對方無理的要求
    6. 習慣取悅對方,讓對方開心,減少衝突
  12.  合理化的行為,其實與社會上期待的「抗壓性很高」的行為,有些不謀而合。你越能合理化這些不合理的事物,你就越能忽略自己的感受,你當然就越能忍耐對方不合理的態度與要求。從外在表現來看,抗壓性很高或許讓你看起來越來越厲害,但你在過程中,可能反而越來越容易自我懷疑,沒自信。或許會越來越不喜歡你自己。然後,你就越來越空虛,越來越「沒有快樂」、「沒有感覺」
  13. 若你是那種「習慣性取悅對方,想讓對方情緒變好以減少衝突」的互動方式,當對方發現他的情緒是可以「勒索你」、「討好他」時,他的情續強度會越來越高,甚至可能越來越不合理,而你可能會更加卑微地要求自己去取悅對方、割地賠款,以求獲得暫時、表面的和平關係
  14. 「習慣性的罪惡感」,是過去你鍛鍊出來,用來應付生活,回應他人需要以利於生存的一種「生存策略」,是你思考的「慣性模式」。
  15. 你的「過度配合」,可能會使得對方完全「沒有界線」,不曉得自己的行為已經太過份、太超限,甚至當有時候已經太過份,因此你沒有滿足他的需求時,你還會覺得「都是你的錯」
  16. 建立情緒界線,指的是:我們為我們自己的行為負責,但是不為他的情緒負責。如此才能保護我們,讓我們在情緒上可以與他人保有一定的距離,不至於因為他人「過多」或「過當」的情緒與要求,使得讓我們的情緒界線被侵犯,就能使我們不至於時常因他人過多的情緒干涉、影響我們,或是迫使我們忽略自己的感受與需求
  17. 「情緒界線」是有彈性的,有時候我們可以讓界線靠近我們一點,多替對方想;有時,當我們比較沒能量的時候,我們選擇多照顧自己一些,此時情緒界線或許就會往外一些。重點是:情緒界線的建立,沒有「應該或不應該」,而是「選擇」
  18. 你無法控制別人怎麼想,你也不需要去爭取對方的認同或好的評價,你可以自己評價你自己.只要你相信:你不是他所說的那種人
  19. 當你發現,其實你想像的恐懼,遠大於實際上會發生的後果,而你其實是有能力去面對、承擔,甚至解決這個後果時,你會發現,這個想法會帶給你勇氣,幫助你減少「過度放大」情緒勒索者可能帶給你的威脅
  20. 所謂的「情緒界線」,指的就是我們自己的忍受範圍。這個範圍,因人而異,你並不需求跟任何人解釋,或是尋求任何人的認同。即使他們不認同,他們如果要與你相處,就必須使用你能夠接受,尊重你感受的互動模式,與你相處

2019/11/15

[Java 8] How to delete files in specific directory?

Requirement
How to delete files in specific directory?

How-To
Here has sample code:
package com.xxx.tool.filegenerator.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

@Slf4j
@Component
public class FileWriter {

    @Value("${file.property}")
    private String propertyFilePath;

    private void deleteFiles() throws IOException {
        Path path = Paths.get(propertyFilePath);

        try (Stream<Path> walk =  Files.walk(path)){
            walk.map(Path::toFile).forEach(File::delete);
            log.debug("delete existing files from {}", path.toAbsolutePath());
        } catch (IOException e) {
            throw new IOException("Fail to delete existing files : " + e.getMessage(), e);
        }
    }

}


2019/11/14

[Oracle] 安裝 Oracel 11g 過程中,發生找不到 wfmlrsvcapp.ear 錯誤

Problem
安裝 Oracel 11g 過程中,發生找不到 wfmlrsvcapp.ear 錯誤

How-To
由於安裝檔被分成 win64_11gR2_database_1of2.zip 與 win64_11gR2_database_2of2.zip,在執行安裝時,會發生此錯誤。

應將 win64_11gR2_database_2of2 目錄下所有檔案,複製到  win64_11gR2_database_1of2 目錄下,再開始安裝,即可避免此錯誤。


2019/11/13

[Microsoft Office] [Word] 如何調整微軟正黑體行距

Problem
因為每個字體有不同的行距,微軟正黑體閱讀起來比較舒服,但預設的行距過大,導致空間的浪費


How-To


2019/11/12

[Apache POI] How to read large excel file

Problem
I am trying to read a large excel file , around 700000 records, via Apache POI.
It takes  lots of time and resources to read this kind of large excel file.
Is it any effective approach to handle this kind of situation?

The original code will take around 60 seconds to read:
package tw.com.abc.dcb.service;

import com.monitorjbl.xlsx.StreamingReader;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.stereotype.Component;
import tw.com.abc.dcb.vo.DcbRecord;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Component
@Slf4j
public class ExcelReaderService {

    /**
     * Read Excel file
     *
     * @param xlsFile excel file path
     * @return excel data
     * @throws IOException fail to read excel file
     */
    public List<DcbRecord> readExcel(String xlsFile) throws IOException {
        List<DcbRecord> result = new ArrayList<>();
        int rowCount = 1;

        try (Workbook workbook = WorkbookFactory.create(new File(xlsFile))) {
            Sheet sheet = workbook.getSheetAt(0);

            Iterator<Row> rowIterator = sheet.iterator();
            while (rowIterator.hasNext()) {
                if (rowCount == 1) {
                    // skip header
                    rowIterator.next();
                    rowCount++;
                } else {
                    Row row = rowIterator.next();

                    DcbRecord record = DcbRecord.builder()
                            .company(row.getCell(0).getStringCellValue().trim())
                            .paymentDescription(row.getCell(1).getStringCellValue().trim())
                            .amount((int) row.getCell(2).getNumericCellValue())
                            .build();

                    result.add(record);
                    rowCount++;
                }
            }
        } catch (IOException e) {
            throw new IOException("fail to read excel file : " + e.getMessage(), e);
        }
        return result;
    }

}



How-To
The original approach to read excel file is not very memory efficient.
We can make good use of Excel Streaming Reader to import this disadvantage.
The new approach's read time will improve to 20 seconds.

Sample code:
package tw.com.abc.dcb.service;

import com.monitorjbl.xlsx.StreamingReader;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.stereotype.Component;
import tw.com.abc.dcb.vo.DcbRecord;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Component
@Slf4j
public class ExcelReaderService {

    /**
     * Read large excel file
     *
     * @param xlsxFile large excel file path
     * @return excel data
     * @throws IOException fail to read excel file
     */
    public List<DcbRecord> readLargeExcel(String xlsxFile) throws IOException {
        List<DcbRecord> result = new ArrayList<>();
        int rowCount = 1;
        try (InputStream is = new FileInputStream(new File(xlsxFile));
             Workbook workbook = StreamingReader.builder().rowCacheSize(100).bufferSize(4096).open(is)) {
            for (Sheet sheet : workbook) {
                for (Row row : sheet) {
                    if (rowCount == 1) {
                        // skip header
                        rowCount++;
                    } else {
                        DcbRecord record = DcbRecord.builder()
                                .company(row.getCell(0).getStringCellValue().trim())
                                .paymentDescription(row.getCell(1).getStringCellValue().trim())
                                .amount((int) row.getCell(2).getNumericCellValue())
                                .build();

                        result.add(record);
                    }
                }
            }
        } catch (IOException e) {
            throw new IOException("fail to read excel file : " + e.getMessage(), e);
        }
        return result;
    }

}




Reference

[1] https://github.com/monitorjbl/excel-streaming-reader