主頁 > 後端開發 > Shell 標準輸入和輸出

Shell 標準輸入和輸出

2022-12-16 06:38:58 後端開發

無論是要交給程式處理的資料,還是控制腳本的簡單命令,都少不了輸入和輸出,程式要做的第一件事就是處理如同一陰一陽的“輸入與輸出”,

1 、從檔案獲取輸入

當我們希望向檔案輸出內容時,我們可以通過符號 > 或 >> 實作,而用代表輸入重定向的符號 < 可以從檔案中讀取資料,如下:

$ wc < my.file

之所以選擇這種形狀的運算子號,原因在于它們可以從視覺上提示重定向的方向,

很多 shell 命令可以接受一個或多個檔案名作為引數,但如果沒有給出檔案名,命令就會從標準輸入讀取,使用這種命令時,可以采用command filename 或者 command < filename,這兩種形式的結果沒什么區別,在這個例子中,wc 是這樣,換作 cat 或其他命令,也是如此,

2、將資料與腳本存放在一起

< 可以從檔案讀取資料,當你需要獲得腳本輸入,但又不想用單獨的檔案時,使用 <<(here-document)從命令列而非檔案重定向輸入文本,如果放在 shell 腳本中,則腳本檔案可以同時包含資料與代碼,

以下是名為 ext.sh 的 shell 腳本示例:

# 下面是here-document
grep $1 <<EOF

mike x.123

joe x.234

sue x.555

pete x.818

sara x.822

bill x.919

EOF

當我們運行此腳本,可以傳入一個引數,如下呼叫:

$ ./ext.sh bill
# 輸出以下內容
bill x.919

grep 命令查找第一個引數是否在指定檔案中出現,如果沒有指定檔案,那么它會在標準輸入中查找,通過設定 here document,告訴 shell 將標準輸入重定向(臨時)到此處,<< 語法表示我們想創建一個臨時輸入源,EOF 是一個任意的字串(你想用什么都行),用作臨時輸入的終止符,它并不屬于輸入的一部分,只是作為標記告訴輸入在哪里結束,

3、避免here-document中的怪異行為

here-document 在使用時可能會出現一些怪異的行為,你想用上一節介紹的方法來保存一份簡單的捐贈人串列,因此創建了一個名為donors.sh 的檔案,如下所示:

# 簡單地查找慷慨的捐贈人

grep $1 <<EOF

pete $100

joe $200

sam $ 25

bill $ 9

EOF

但是運行時出現了奇怪的輸出:

$ ./donors.sh bill

pete bill00

bill $ 9

$ ./donors.sh pete

pete pete00

正常情況下(除非使用了轉義語法),bash 手冊頁中是這樣說的:“……here-document 的每一行都要執行引數擴展、命令替換以及算術擴展”,因此,最初的 donors 腳本中所發生的事情是捐贈額被當作 shell 變數了,例如,$100 被視為 shell 變數 $1,隨后跟著兩個 0,這就是為什么我們在搜索“pete”時,得到的是 pete00;搜索“bill”時,得到的是 bill00,

解決辦法:

通過轉義結尾標記中的任意或所有字符,修改腳本內容,關閉 here-document 內部的 shell 特性(注意觀察EOF位置的變化):

# 簡單地查找慷慨的捐贈人
grep $1 <<'EOF'

pete $100

joe $200

sam $ 25

bill $ 9

EOF

盡管其中存在非常微妙的區別,但也可以將 <<EOF 替換成 <<\EOF或 <<'EOF',甚至是 <<E\OF,都沒問題,盡管這并不是最優雅的語法,但足以告訴 bash 你希望區別處理 here-document 中的內容,如果我們轉義了 EOF 的部分或全部字符,那么 bash 就知道不用執行擴展,這樣就符合我們的預期行為了,

$ ./donors.sh pete

pete $100

4、獲取用戶輸入

輸入不止從檔案中獲取,有時我們還需要獲取用戶輸入的內容,此時,我們需要用到read命令,如下:

$ read

或者

$ read -p "answer me this " ANSWER

不帶引數的 read 陳述句會讀取用戶輸入并將其保存在 shell 變數REPLY 中,這是 read 的最簡形式,如果希望 bash 在讀取用戶輸入前先輸出提示資訊,可以使用 -p 選項,-p 之后的單詞就是提示資訊,如果想提供多個單詞,可以將其參考起來,記住,要在提示資訊結尾處加上標點符號或空格,因為游標會停在那里等待輸入,-t 選項可以設定超時值,指定秒數達到后,不管用戶是否輸入,read 陳述句都會回傳,我們的示例同時用到了 -t 和 -p 選項,但你也可以單獨使用 -t 選項,

上面的方式獲取用戶輸入時會以明文回顯,那適用密碼輸入么?

當我們需要用戶輸入敏感資訊時,需要禁止用戶輸入內容的回顯,此時用 read 命令讀取用戶輸入,需要加上一個特殊選項來關倍訓顯:

read -s -p "password: " PASSWD

printf "%b" "\n"

-s 選項告訴 read 命令不要回顯輸入的字符(s 代表 silent),-p 選項指明下一個引數是提示資訊,會在讀取用戶輸入之前顯示,從用戶那里讀取到的輸入行保存在變數 $PASSWD 中,在 read 之后,我們用 printf 輸出了一個換行符,這里的printf 不能少,因為 read -s 會關閉字符回顯,如果禁止了回顯功能,當用戶按下回車鍵時,就不會回顯換行符,后續輸出就會和提示資訊出現在同一行,輸出換行符會將游標帶到下一行,

當然,我們也可以選擇一行,如下:

read -s -p "password: " PASSWD ; printf "%b" "\n"

Shell標準輸出

如果無法產生輸出,那么軟體也就沒什么價值了,但長久以來,I/O一直是難纏的計算領域之一,問題是有太多型別的輸出,向螢屏寫入不同于向檔案寫入,向檔案寫入也不同于向磁帶或閃存寫入,所以,對于輸出會產生一些問題,如下:

  • 軟體開發人員是否要針對各種輸出設備撰寫代碼,甚至包括尚未發明的設備?
  • 寫到哪個檔案?程式怎么知道是該寫入代表終端視窗的檔案、磁盤檔案還是其他種類的檔案?

顯然,如果把這些事情都交給每個程式員是不合理的,所以這種事情留給shell 就行了,

1、輸出到終端/終端視窗

想要用 shell 命令產生一些簡單的輸出,使用內建命令 echo,命令列中的所有引數都會列印到螢屏上,

echo Please wait.

輸出:

Please wait.

結果和在 bash 提示符(字符 $)后輸入該命令相同:

file

echo 是最簡單的 bash 命令之一,該命令可以將引數輸出到螢屏上,但是有幾點需要記住:

  • 首先,shell 負責決議 echo 的命令列引數,將引數交給 echo前,shell 會完成所有的替換、通配符匹配等操作,
  • 其次,在決議引數時,引數之間的空白字符會被忽略,如下圖:

file

shell 對引數間的空白字符沒有太多限制,這通常是一種不錯的特性,但對于 echo 來說,就有點煩人了,

  • 保留輸出中的空白字符,將字符放入引號中就可以保留空白字符,如下圖:

file

引號中的單詞組成了 echo 命令的單個引數,該引數是一個字串,shell 不會干涉字串的內容,實際上可以用單引號('')明確告訴shell 不要干涉字串,

2、在輸出中加入更多格式控制

使用內建命令 printf,例如:

printf '%s = %d\n' Lines $LINES
Lines = 24

或者:

$ printf '%-10.10s = %4.2f\n' 'Gigahertz' 1.92735

Gigahertz = 1.93

內建命令 printf 的行為和 C 語言中的同名庫函式相似,其中第一個引數是格式控制字串,之后的引數都根據格式規范(%)進行格式化,

% 和格式型別(本例為 s 或 f)之間的數字提供了額外的格式化細節,

對于浮點型別(f),第一個數字(指示符 4.2 中的 4)是整個欄位的寬度,第二個數字(2)是應該在小數點右側列印出的數位量,注意,結果會按照四舍五入處理,

對于字串,第一個數字是欄位的最大寬度,第二個數字是要輸出的字符數量,根據需要,字串會被截斷(長于 max)或用空白填充(不足 min),如果指示符 maxmin 相同,那么就可以確保字串按照該長度輸出,指示符左側的負號表示字串向左對齊(在字段寬度內),如果不使用負號,則字串向右對齊

3、消除輸出中的換行符

希望輸出中不包含 echo 默認生成的換行符,使用 printf,做法很簡單,去掉格式化字串末尾的 \n 即可,如下圖:

printf "%s %s" next prompt

file

如果是 echo,則使用 -n 選項:

$ echo -n prompt

file

因為 printf 的格式字串(第一個引數)末尾并沒有換行符,所以命令列提示符($)出現在了 printf 的輸出之后,該特性在shell 腳本中用處更大,你可能希望在形成一整行前由多條陳述句逐部分輸出,或者在讀取輸入前顯示用戶提示,

換作 echo 命令(參見 15.6 節),消除換行符的方法有兩種,

首先,-n 選項能夠抑制輸出行尾的換行符,

另外,echo 命令還可以處理多種具有特殊含義的轉義序列(如表示換行符的 \n),這些轉移序列與 C 語言字串中的類似,呼叫 echo 命令時加上 -e 選項,其中一種轉義序列是 \C,它并不會輸出什么字符,而是禁止在行尾輸出換行符,如下圖:

$ echo -e 'hi\c'

file

4、保存命令輸出

如過想把命令輸出保存在檔案中,用 > 符號告訴 shell 將輸出重定向至檔案,例如:

$ echo fill it up

fill it up

$ echo fill it up > file.txt

我們來查看一下檔案 file.txt 的內容,看看其中是否包含了命令的輸出:

$ cat file.txt

fill it up

示例第一部分的第一行中出現的 echo 命令包含了 3 個要輸出的引數,第二行用 > 將這些輸出保存到檔案 file.txt 中,這就是看不

到 echo 輸出的原因,

示例第二部分用 cat 命令顯示檔案內容,我們可以看出,檔案中包含的正是 echo 本該輸出的內容,

cat 命令得名自一個較長的單詞 concatenation(拼接),該命令會將出現在命令列上的檔案的輸出拼接在一起,如果你輸入 cat

file1 file2 file3,那么這些檔案的內容會逐個發送到終端視窗,如果一個大檔案被分成了兩半,你也可以用 cat 將其恢復原樣(也就是將兩部分拼接起來),這只需將輸出保存到另一個檔案中:

cat first.half second.half > mergeFile.txt

5、將輸出保存到其他檔案

如想要用重定向將輸出保存到當前目錄之外的其他位置,重定向輸出時加上路徑,如下:

echo some more data > /tmp/echo.out

或者:

echo some more data > ../../over.here

出現在重定向符號(>)后的檔案名其實就是路徑名,如果沒有任何限定部分,那么檔案就會放置在當前目錄中,

如果檔案名以斜線(/)起始是絕對路徑名,此時檔案會被放置在檔案系統層次結構(目錄樹)中以根目錄起始的指定位置,

第二個例子中,我們使用了相對路徑名 ../../over.here,其中的.. 是一個指向父目錄的特殊目錄,存在于每個目錄中,

6、將輸出和錯誤訊息發送到不同檔案

希望獲得程式的輸出,但不想輸出被出現的錯誤訊息弄亂,要保存的錯誤訊息混雜在程式輸出中不容易找出,可將輸出和錯誤訊息重定向到不同檔案,如下:

$ myprogram 1> messages.out 2> message.err

或者采用更常見的方法:

$ myprogram > messages.out 2> message.err

shell 會創建兩個輸出檔案,

第一個是messages.out,程式 myprogram 的所有輸出都會重定向到該檔案,

第二個是message.err,程式myprogram 的所有錯誤訊息都會重定向到 message.err,

在 1> 和 2> 中,數字表示檔案 描述符,

  • 1 代表標準輸出(STDOUT),
  • 2 代表標準錯誤(STDERR),
  • 0 代表標準輸入(STDIN),

如果不指定數字,則假定為 STDOUT,

7、將輸出和錯誤訊息發送到同一檔案

利用重定向,我們可以將輸出或錯誤訊息保存到單獨的檔案中,但如何將兩者送往同一檔案呢?用 shell 語法將標準錯誤訊息重定向到和標準輸出相同的地方,

首選:

$ myprogram >& outfile

或者:

$ myprogram &> outfile

又或者老式且略煩瑣的寫法:

$ myprogram > outfile 2>&1

其中,myprogram是準備向 STDERR 和 STDOUT 生成輸出的程式,

&> 和 >& 只是將 STDOUT 和 STDERR 發送到相同地方的便捷寫法,

8、追加輸出

每次重定向輸出,都會產生一個全新的輸出檔案,如果想要兩次(或三次、四次……)重定向輸出,同時又不想破壞之前的輸出,該怎么辦呢?

在 bash 的重定向符號中,雙大于號(>>)表示追加輸出:

$ ls > /tmp/ls.out
$ cd ../elsewhere
$ ls >> /tmp/ls.out
$ cd ../anotherdir
$ ls >> /tmp/ls.out

如果存在同名檔案,第一行中的重定向會將其截斷,并將 ls 命令的輸出保存在這個已被清空的檔案中,

后兩次呼叫 ls 時使用了雙大于號(>>),表示向輸出檔案中追加內容,而不是覆寫其原有內容,

如果想要同時重定向錯誤訊息(STDERR),可以將 STDERR 的重定向放在后面,如下所示:

ls >> /tmp/ls.out 2>&1

在 bash 4 中,你可以將這兩個重定向合二為一:

$ ls &>> /tmp/ls.out

該命令會重定向 STDERR 和 STDOUT,并將兩者追加到指定檔案中,& 符號必須先出現,且這 3 個字符之間不能有空格

9、丟棄輸出

你有時不想將輸出保存到檔案中或者有時甚至不想看到輸出,如我們在查找某個檔案時,忽略那些沒有權限的提示,如下圖:

file
此時,我們可以將輸出重定向到 /dev/null,如下所示:

$ find / -name myfile 2> /dev/null

其實,你可以將不想要的輸出重定向到檔案,然后再將其洗掉,但還有一個更簡單的方法,Unix 和 Linux 系統都存在一個特殊設備,該設備并非真實的硬體,而僅僅是一個位桶(bit bucket),我們可以將不需要的資料都扔進去,它就是 /dev/null,非常適用于此類場景,寫入其中的資料會被直接丟棄并不會占用磁盤空間,重定向很容易做到這一點,示例中,只有發往標準錯誤的輸出被丟棄了

本文由傳智教育博學谷教研團隊發布,

如果本文對您有幫助,歡迎關注點贊;如果您有任何建議也可留言評論私信,您的支持是我堅持創作的動力,

轉載請注明出處!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/539980.html

標籤:Java

上一篇:Centos安裝Nginx

下一篇:公司新來一個同事,把網關系統設計的爐火純青!(萬能通用,穩的一批。。)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more