windows輸入重定向中#句柄備份#原理

重定向是指使用重定向符號對輸入或輸出位置進行重新指定。

以下是理論說明,懂的可以跳過,也可以先看例子,遇到不明白的再倒回來看。

重定向符號有< 、> 、>> 、<& 、>& 和| 共六個。

 

重定向符號的作用如下表所示:

 

符號      作用

——————————————————————————————

<      從文件或設備(如默認的con 鍵盤)中讀取命令輸入。

>      將命令輸出寫入到文件或設備(如prn 打印機)中。 

>>     將命令輸出添加到文件末尾而不刪除文件中的信息。

<&    從後一個句柄讀取輸入並寫入到前一個句柄輸出中。

>&    將前一個句柄的輸出寫成後一個句柄的輸入。

|      讀取前一個命令中的輸出作爲後一個命令的輸入。也稱作管道符。

——————————————————————————————

注意:句柄的輸入輸出只是其指向,真正的輸入輸出是靠設備。

重定向符號的默認句柄,< 的默認句柄是0,> 的默認句柄是1。

 

可用句柄(0 - 9)如下表:

 

句柄        句柄號      說明

——————————————————————————————

STDIN        0        標準輸入,默認從鍵盤輸入

STDOUT      1       標準輸出,默認輸出到命令提示符窗口

STDERR      2          標準錯誤輸出,默認輸出到命令提示符窗口

UNDEFINED  3-9       這些句柄由應用程序和各個具體工具單獨定義。

——————————————————————————————

STD 即Standard —— 標準的縮寫。

 

設備

標準輸入設備爲鍵盤,用con 表示。

標準輸出設備爲控制檯(即命令提示符),默認也用con 表示。

常用的還有:

空設備,用nul 表示。

存儲設備,文件就歸到這類。

不常用的如:打印機prn。

 

指向

句柄實際上也是一組0 1 數據,是存儲了一個指向。

句柄0 默認指向con,這裏con 爲標準輸入設備,即鍵盤。

句柄1 默認指向con,這裏con 爲標準輸出設備,即控制檯。

句柄2 默認也指向con,同1。

此外,我們對句柄的指向重新設定(即所謂的重定向)時,可以改變句柄的指向。

如1>nul 是讓“標準輸出”數據輸出到空設備,效果就是屏蔽輸出。

特別之處: 3 - 9 默認是沒有指向的,我們可以用(空)來表示,注意是不同於空設備nul 的哦!

 

 

下面拿個簡單的例子來說明

pause>nul

後面的>nul 的作用就是屏蔽了pause 命令的默認輸出“請按任意鍵繼續. . .”。

以上是簡單的描述,而實際的過程可沒那麼簡單:

首先確定重定向符號爲>;

接着檢查句柄號,發現沒有,控制檯爲其加上默認句柄1,此時變成pause 1>nul;

由於句柄1的默認指向con,此時要被臨時設定爲指向nul,爲了之後取回原來的指向,所以要先對1 的指向進行備份,備份到句柄3,備份過後臨時設定1 指向nul;

(爲什麼要備份,爲什麼要備份到3 而不是4?見下文)

到這時這條語句才被執行,效果就是批處理暫停,沒有輸出只有一個光標閃阿閃。

執行完後1要取回原來的指向,1 的指向在上面被備份到3,不管3 的指向有沒有改變1 要取回它的指向來,取回後1 指向con;3 的指向被取走,由於3 沒有備份,所以恢復到原來的(空),即無指向。

至此整個過程描述完畢。

可以發現這時的情況與最初是相同的,所有句柄的指向都是其默認值。

 

    接着引出 句柄(指向)備份理論。

 

1.  當指向爲非空的句柄被重新設置時要進行備份,而且是備份到第一個沒有指向的句柄。

2.  語句運行完後要取回其備份,而不管備份中的句柄指向有沒有改變。

3.  如果當前狀態下3 - 9 這七個句柄都有了指向,這時新設置的句柄其原指向將不再備份。

複製代碼

1.  另一種表述:也就是說當指向爲(空)的句柄被設定時是不需要備份的。如:複製句柄時源句柄不備份,因爲沒有被再次設置。

2.  補充說明:一個句柄只能存儲一個指向。

  

還有一個特別的例子:

echo 你好!>nul >hello.txt >prn >con

它使用的是相同的句柄1,這時要以最後一個爲準,其他的忽略。把它存爲批處理運行,能夠清楚的看到前面的三種指向直接被剪掉了。

同理:

echo 你好!1<&3 >nul

也以後面的”>nul“ 爲準,即不顯示”你好!“。

 

具體例子講解

1.  @echo off

2.  echo 哇,這就是傳說中的樹葉嗎?>con 3>nul

3.  echo 我有一片神奇的樹葉(吹口哨),

4.  echo 你看不見我,

5.  echo 我現身,>con

6.  echo 我又隱身啦。

7.  echo 誰偷了我的葉子,快還我。>con 4>con

8.  echo 沒穿褲褲被你們看到了!

9.  pause>nul

複製代碼

哇,這就是傳說中的樹葉嗎?

這句用了“>con >nul” 同示例三,首先 句柄1 指向要被設爲con,先備份到3 再設定;第二步 這時3 指向爲con,現在又要設爲nul,先備份con 到4;最後1 指向con,3 指向nul,4 指向con;所以這句執行時是要顯示的。

執行完後返回,1 取回3的指向nul,3 取回4 的指向con,4 恢復(空),所以返回結束時1 指向nul,3 指向con。假設這時狀態爲A。

因此接下來兩句“我有一片神奇的樹葉(吹口哨),”,“你看不見我,” 是不顯示的。

“我現身,” 這句設定爲“>con”。執行時1 爲con,原來的nul 備份到4(因爲前面3 已經爲con 不是沒有指向了);執行完後1 取回備份nul,4 恢復(空)。這時的狀態還是A。

所以下一句“我又隱身啦。” 還是不顯示。

倒數第二句“誰偷了我的葉子,快還我。”

設定爲“>con 4>con”,首先 句柄1 指向要被設爲con,3 已經不爲(空)了,所以備份nul 到4;第二步 這時4 指向爲nul,現在又要設爲con,先備份nul 到5;最後1 指向con(3 指向nul)4 指向con,5 指向nul;所以這句顯示。

返回時1取回4 的指向con,4 取回5 的指向nul,5 恢復(空)。而這時狀態已經不同於A 了,設爲狀態B。最後一句“沒穿褲褲被你們看到了!” 使用的是狀態B 的句柄指向,所以也顯示。

  

補充

我們可以比較一下下面兩句的差別

echo 你好!>con 2>con

echo 你好!

(有人會問了“你不是說句柄1 和2 默認指向爲con 嗎?”)

沒錯,我來解釋一下。

第一句對句柄1和2 進行了重新設定(雖然是和默認一樣的),因此要有備份和取回的過程;

而第二句沒有設定,直接取默認值作爲當前設定(不需要備份什麼的哦);

這樣第二句就比第一句快一點,如果在一個循環多次的程序中使用,速度差別就很明顯了。

 

應用

一次性屏蔽錯誤輸出(加在開始屏蔽的語句後面)

2>nul 3>nul

 

一次性將輸出寫入文件a.txt(不包括錯誤反饋,用法同上)

>&3 3>a.txt

 

問題:經過重定向後句柄的指向已經不同於默認指向了,還能恢復成原來的默認指向嗎?

回答:因爲指向不能設定或複製成空,所以語句運行完後的指向如果改變了是不能回到默認指向的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章