2023年10月20日 星期五

windows 標準輸出

 # 標準輸出

> 正確的命令 > 檔案,也可用 1>

> 正確的命令表示打完後「不會」出錯

1. echo xxx > d:\abc.txt

2. echo xxx 1> d:\abc.txt

每次都會清空之前的內容

---


 # 標準附加輸出

> 正確的命令 >> 檔案,也可用 1>>

1. echo xxx >> d:\abc.txt

2. echo xxx 1>> d:\abc.txt

每次都「不會」清空之前的內容,會在檔案最後附加上去

---


 # 標準錯誤輸出、標準錯誤附加輸出

> 不正確的命令 2> 檔案

> 不正確的命令表示打完後會出錯

xxx > d:\abc.txt

每次都會清空之前的內容

如果要附加,只要將 2> 改成 2>> 即可

---


 # 標準輸出、標準錯誤輸出導出不同檔案

1. echo xxx >> d:\abc.txt 2>> aaa.txt

2. echo xxx > d:\abc.txt 2> aaa.txt

不可以導到相同的檔案,>,2>>都和上面說的一樣,可以自己決定要不要附加

---


# 標準輸出、標準錯誤輸出導出相同檔案

1. echo xxx >> d:\abc.txt 2>&1

2. xxx >> d:\abc.txt 2>&1

只要在最後加上 2>&1 即可,附加看的是前面的標準輸出或標準附加輸出


2023年1月26日 星期四

java Native 調用 C

public class TestNative {
    public native void helloNative1();
    public static native void helloNative2();

    static {
        System.load(System.getProperty("user.dir") + "/xxx.dll");
    }

    public static void main(String[] args) {
        new TestNative().helloNative1();
        TestNative.helloNative2();
    }
}

※System.getProperty("user.dir") 為專案路徑
※xxx.dll 為 c 的程式碼變成的


產生 dll 的方法:
1.到 TestNative.java 打上 javac TestNative.java -h .
會產生副檔名為 h 和 class 的檔案

2.將副檔名為 h 的檔案複製一份出來改檔名為 cpp,完成後為如下的圖:


3.修改 cpp 檔案的內容,這個就是要實作 native 的內容

#include <jni.h>
#include <stdio.h>
#include "TestNative.h"

JNIEXPORT void JNICALL Java_TestNative_helloNative1
  (JNIEnv *, jobject) {
  printf("%s", "helloNative1\n");
  }

JNIEXPORT void JNICALL Java_TestNative_helloNative2
  (JNIEnv *, jclass) {
  printf("%s", "helloNative2\n");
  }

※要 include TestNative.h

4.到 sourceforge.net 下載 c 的編譯器 MinGW-w64,然後如下下載,並解壓



5.進入解壓後的資料夾的 bin
打上 gcc --version,出現版本號表示可以用 gcc 這個指令了
再打上 gcc -I "C:\Program Files\Java\jdk1.8.0_202\include" -I "C:\Program Files\Java\jdk1.8.0_202\include\win32" --shared -o xxx.dll D:\JavaProject\src\TestNative.cpp
會產生 xxx.dll 的檔案

※-I 表示 include,要包含兩個檔案,因為 3 的檔案要用到 jni.h,這個檔案在 include 裡;然後 jni.h 這個檔案還要 include jni_md.h,這個檔案在 include\win32

※-o 為 output,後面接想輸出的檔案名稱

※最後是 cpp 所在路徑

6.將得到的 xxx.dll 放在專案路徑下即可,其他 cpp、h 都可以不需要,結果畫面如下:










2023年1月9日 星期一

C語言指針

 線上測試

※基本型態指針

// 包括 short int long float double chat

#include <stdio.h>

void test(int *d)  {

    *d = 100; // 將 d 這個位址對應的值,改成 100; 寫 d 或 &d 都會報錯

}


int main() {

    int digit = 2;

    test(&digit);

    printf("digit=%d", digit);

    return 0;

}


在變數前加上 &,表示傳的是記憶體位址;

    在變數前加上 *,表示接收記憶體位址

    所以可以這樣宣告變數 int *x = &digit;   test(x);

※這樣的好處是方法裡改變的值,會影響調用方的值

※只有傳的時候給 &,接收時給 * 才不會報錯,其他都會報錯



※陣列指針

#include <stdio.h>


int main() {

    int arr[] = {1, 2, 3};


    // 注意是用 int *p 來接,不是 int[]*p,會報錯

    int *p = arr; // 指向的是 arr[0]的記憶體位址,陣列不可打 &arr,因為它有多個值,要傳其中一個值可用 &arr[0],但代表整體就不能有 &,會報錯

    

    // 以下三個結果一樣

    printf("%p\n", &arr[0]);

    printf("%p\n", arr);

    printf("%p\n", p);

    

    // 以下三個結果一樣,和上面差 4,也就是 4 Bytes

    printf("%p\n", &arr[1]);

    printf("%p\n", arr + 1);

    printf("%p\n", p + 1);

    

    // 以下三個結果都是 2,也就是取值

    printf("%d\n", *(&arr[1]));

    printf("%d\n", *(arr + 1));

    printf("%d\n", *(p + 1));

    

    printf("%p\n", &arr + 1); // &arr 是整個 arr 的記憶體位址,如果佔用 4Bytes,結果將是 4Bytes 結束再 + 1,可用 sizeof() 查看佔多少 Byte

    return 0;

}



※字串指針

int main() {

    char *p = "a";

    printf("string=%s", p);

    

    // int *i = 9;

    // printf("digit=%d", i);

    return 0;

}

※字串指針可以直接賦值,其他不行


※陣列裡放指針

int main() {

    char *s1 = "ab";

    char *s2 = "cd";

    char *s3 = "ef";

    

    char *s[3] = {s1, s2, s3}; // 和陣列就差一個 *,只有字串可以這樣寫

    printf("string=%p\n", s);

    printf("%s", s[1]);


    return 0;

}





2022年8月11日 星期四

lambda 的 this (java8 八)

/**
 * 印 this 的時候,會調用 Object.toString()
 * 匿名類別的 this:會先調用自己匿名類別的 toString,沒有才去 Object.toString
 * Lambda 的 this:會先調用「當下」類別的 toString,沒有才去 Object.toString
 */
public class ThisTest {
    Animal a1 = new Animal() {
        @Override
        public void m(String str) {
            System.out.println(this);
        }

//        @Override
//        public String toString() {
//            return "anonymous toString";
//        }
    };

    Animal a2 = s -> System.out.println(this);

//    @Override
//    public String toString() {
//        return "this toString";
//    }

    public static void main(String[] args) {
        ThisTest thisTest = new ThisTest();
        thisTest.a1.m("xxx");
        thisTest.a1.m("aaa");
        thisTest.a2.m("ooo");
        thisTest.a2.m("bbb");
    }

    @FunctionalInterface
    public interface Animal {
        void m(String str);
    }
}


2022年7月14日 星期四

Java 的 floorMod 和 %

// System.out.println(Math.floorMod(113, 30)); // 23
System.out.println(Math.floorMod(113, -30)); // -7
System.out.println(Math.floorMod(-113, 30)); // 7
System.out.println(Math.floorMod(-113, -30)); // -23
System.out.println("-----------------------");
// System.out.println(113 % 30); // 23
System.out.println(113 % -30); // 23
System.out.println(-113 % 30); // -23
System.out.println(-113 % -30); // -23
System.out.println("=======================");
// System.out.println(Math.floorDiv(113, 30)); // 3
System.out.println(Math.floorDiv(113, -30)); // -4
System.out.println(Math.floorDiv(-113, 30)); // -4
System.out.println(Math.floorDiv(-113, -30)); // 3
System.out.println("-----------------------");
// System.out.println(113 / 30); // 3
System.out.println(113 / -30); // -3
System.out.println(-113 / 30); // -3
System.out.println(-113 / -30); // 3

除數和被除數全正數和全負數時,% 和 mod 一模一樣

※全負數時,除法是負負得正;

※有負數時, % 的正負號看左邊,mod 的正負號看右邊,如 -113 % -30,-113 是左邊;-30 是右邊,一正一負時也是一樣

※113 / 30 是 3...23

floorDiv 時,一正一負為負,(3 + 1) * -1 = -4,固定加1乘-1

floorMod 時,30 - 23 = 7,然後看 30 是正或負,7 的正負號就和它一樣

目前不知道 mod 這樣有什麼用




 

2022年2月17日 星期四

檢查服務是否啟動、grep、sed、awk

檢查服務是否啟動

lsof -i:8080

netstat -lntup |grep 8080

ss -lntup |grep 8080

ps -ef |grep 8080



grep 

過濾文字

-A 之前x行(不包括搜尋的行)

-B 之後x行(不包括搜尋的行)

-C 前後x行(不包括搜尋的行)

-c 有幾行,類似 wc -l 的功能

-i 忽略大小寫

-w word,單字匹配

-v 回傳相反的匹配


grep -A3 5 fileName:找到 5 後,將前3行顯示出來,所以總共會顯示 4 行

seq 10 |grep -A3 5   ==> 5~8

seq 10 |grep -B3 5   ==> 2~5

seq 10 |grep -C3 5   ==> 2~8


seq 20 |grep 5 |wc -l

seq 20 |grep -c 5


grep -i a test.txt


seq 50 |grep 5

seq 50 |grep -w 5


seq 20 |grep -v 5




sed

針對行的增刪改查,stream edit 的縮寫


-n:sed 會一行一行執行,預設每行都會輸出,所以匹配到的會出現兩次,而加這個只會將匹配成功的輸出

-i:顯示的結果,預設不會覆蓋原檔案,如果要覆蓋要加這個參數

-r -E:加上正則表達式支援


增刪改查

c a i:replace想成 ce的c/append/insert

d:delete

s:substitute

p:print


p:

'3p' 印出第3行

'1,5p' 印出1~5行

'/xxx/p' 找 xxx

'/10:00/,/11:00/p' 找 10:00~11:00 之間的資料


增刪改查範例:

sed -n '/7/,/10/p' test.txt

sed '/7/,/10/d' test.txt // 加 -n 會看不到結果,每次的7~10都會刪除

sed 's/a/aaa/' test.txt // s寫在前面,s/a/aaa/、s#a#aaa#,分隔符不要太奇怪都可以

sed 's#[0-9]##g' test.txt // 將數字取代成空,但仍然有換行,最後不加 g,只會取代每行的第一個數字

sed '6a xxxxxx' test.txt // 在第6行之後加一行 xxxxxx 

sed '6i xxxxxx' test.txt // 在第6行之前加一行 xxxxxx 

sed '6c xxxxxx' test.txt // 取代第6行,變成 xxxxxx 


awk

發明人的名字第一個字母組成的


record:行(左右),預設 \n,-v RS 可改

field:列(上下),預設空隔,-F 或 -v FS 可改


$數字:第x列,$0是整行

NF:最後一列的數字,可以加減,但要用圓括號包起來

NR:行號

-F分隔符

FS:-v FS=分隔符,給 awk 的分隔符,相當於 -F,預設是空格

OFS:-v OFS=分隔符,awk 返回結果的分隔符,預設是空格

RS:-v RS=換行符,預設 \n

ORS:-v ORS=換行符,預設 \n

print 會換行

printf 不會換行


NR

Number of Record

NR==1 取出第一行

NR >=1 && NR <= 5 取出 1~5 行,還有 == != 可用

awk 'NR >= 12 && NR <= 15' test.txt


假設有一行 1,2,3,4,5,6,7,8,9,10

awk -F, 'NR==1{print $NF}' test.txt // 取第一行,然後以,分隔,再取最後一列,所以是10

awk -F, 'NR==1{print $(NF-1)}' test.txt // 取到數第二列

ls -l |awk '{print $5, $NF}' |column -t // 取第五列和最後一列,並排版

ls -l |awk '{for(i=5;i<=NF;i++){printf $i" "};printf "\n"}' |column -t // 取第五列到最後一列


正則

awk '$10~/^1/{print $10}' fileName    // 第 10 個欄位是 1 開頭就印出來

~ 包含

!~ 不包含

^$ 空

//,//

//,//{print $2}


BEGIN、END

BEGIN{} 內容在 awk 讀檔案之前執行

END{} 內容在 awk 讀檔案之後執行


seq 100 |awk 'BEGIN {pring 0} {sum=sum+$1; print sum} END{print "finish"}'

印出 0~100 相加的過程,BEGIN 和 END 可以只用一個



陣列

非數字要用字串包起來

awk 'BEGIN{x[0]=123; x[1]="xxx"; print x[0], x[1]}'

awk 'BEGIN{x[0]=123; x[1]="xxx"; for(i in x) print x[i]}'