Java作為一種編程語言如此普及的原因之一
是它解決了其他語言中常見的I/O
網絡操作中非常困難的問題
C#語言也采用了與Java類似的方法
提供了一些庫來完成對I/O和網絡的操作
並隱藏了其復雜的實現方法
本篇文章將著重討論C#中與I/O
網絡操作有關的名字空間以及這些庫的一些模板的通用用法
為了方便熟悉Java的編程人員更好地掌握C#
使廣大讀者能夠對二種語言進行比較
在本篇文章中我們也都給出了相同功能在Java中的實現方法
理解流操作
Java和C#中的流通常與從控制台
文件系統或網絡讀取數據或向這些設備寫數據有關
在這二種語言間
如果程序需要移動或對許多字節的數據進行操作
都會較多地用到流操作
Java提供了二個抽象類
java
io
InputStream和java
io
OutputStream
其中包括一些允許程序讀或寫流數據的方法
C#則把這二個類合並為一個
System
IO
Stream
與有一個用於讀流數據
一個用於寫流數據的二個對象不同
C#中的Stream對象需要通過測試CanRead
CanWrite屬性對其讀
寫能力進行檢測
同步I/O操作
同步I/O操作在這二種語言中是十分相似的
無論是Java中的java
io
InputStream和 java
io
OutputStream還是C#中的System
IO
Stream都有每次只對一個字節數據進行操作的方法
也有每次對一批數據進行操作的方法
(C#缺乏一次對一個字節數組操作的能力
只能通過偏移量/長度參數對字節數組進行操作
)
表
Java和C#中的同步I/O操作
Java編程人員需要注意的一點是
不要忘記IOException
與Java不同
C#編譯器在編譯時不要求處理異常情況
Java缺乏完成異步I/O操作的正式方法
它沒有
內置
的方法對流進行讀
寫
然後再檢查其結果
其中最
相似
的一種模擬是在同步操作時產生一個java
lang
Thread線程
使得該線程引起側放作用(某些指令取出後
暫時不執行
放在一邊)或完成檢查工作
C#的庫中有內置的異步I/O操作命令
例如
要在Java中執行一個可以對狀態進行檢查的異步read( byte[] b )操作
下面是一種可能的實現方法
file:// 保存讀操作的側放作用的變量
int read; file:// 保存read的結果
IOException exception; // 保存可能發生的異常
Object wait
// 在檢查結束前需要保留的一些值
file://InputStream變量is中有關read的封裝
( new Thread( new Runnable() {
public void run() {
try {
read is
read();
} catch( IOException error ) {
exception error;
} finally {
synchronized( wait ) {
file:// 喚醒等待這一變量的其他進程
// 執行read操作
wait
notifyAll();
}
// 調用檢查方法
callback();
}
}
} ) )
start();
這將使得read的值或執行讀操作的異常情況被分別存儲在read和exception中
另一個依賴於變量wait的進程可能繼續等待或完成檢查的方法
C#提供了封裝了上述全部功能的BeginRead和EndRead這二個方法
BeginRead的作用與Read類似
但它對二個或更多的變量━━一個AsyncCallback變量和一個狀態對象進行操作
返回一個可以稍後用來檢查異步讀進程的IAsyncResult對象
標准的BeginRead的用法與下面的用法相似
IAsyncResult iar sbs
BeginRead( buffer
new AsyncCallback( = callback )
null );
帶callback方法的用法如下
public void callback( IAsyncResult iar )
要檢查實際讀取了多少字節
可以調用帶IAsyncResult對象參數的EndRead方法
需要記住的是
在BeginRead執行完畢之前
EndRead的調用將被阻塞
要在沒有阻塞的情況下檢查read的狀態
可以檢查返回的IAsyncResult變量的IsCompleted屬性
另外需要注意的是
在異步read完成之前
緩沖區中的內容是不可靠的
實現流操作
Java和C#中的流數據非常地相似
如果對Java中的流操作足夠熟悉
在C#中完成流操作就不會是太困難的事兒了
Java和C#中實現流操作的最主要的差別不僅僅是需要實現的適當的讀或寫方法
還有C#中的Stream類還可以作為
讀者
或
作者
和准確反映Stream容量的屬性
表
Java和C#中Stream操作的實現
C#中的Stream類在完成某一種功能時提供了多種選擇
最重要的Read和Write(二者都需要一個字節數組
偏移量
長度三個參數)這二個方法就足夠了
因為所有方法的執行都會用到其他的方法
簡單的read/write方法將能夠給流添加所需要的功能
缺省的ReadByte和WriteByte的執行方式將把long型變量與字節數組之間進行轉換
異步執行的BeginRead和BeginWrite方法將在獨立的線程中執行Read或Write方法
這篇稿子的大部分篇幅談論的都是C#中的System
IO
Stream類有關
在這裡我們還需要討論一下System
IO
TextReader和System
IO
TextWriter這二個類
這二個類與Java處理I/O的方式十分相似
其中的一個類負責處理讀取操作
另一個類則負責處理寫操作
C#中的Stream對象掩蓋了如何讀取
寫的有關細節
TextReader和TextWriter則分別獨立地存儲著讀取或寫入的字節
由上述二種類衍生出的最通用的類是System
IO
StreamReader和System
IO
StreamWrtiter類
這二個類都可以對一個Stream對象進行操作
System
Text
Encoding對象指定一個字節流如何轉換為字符流
(缺省情況下
C#使用UTF
進行編碼/解碼
)
如果需要使用與流類似的功能
而且需要對字符而不是字節進行操作
使用TextReader和TextWriter二個類的子類要比使用Stream類簡單得多
雖然如果Stream動用得當
也可以使用StreamReader和StreamWriter類實現流操作
文件系統I/O
在Java中完成磁盤操作是十分簡單的
通常情況下它就是操作java
io
File對象和使用java
io
FileInputStream或java
io
FileOutputStream
跟我們在上面看到的一樣
C#在許多方面與Java相同
但也有一些不同之處
與Java一樣
C#的文件對象與底層的文件系統之間並沒有特別緊密的聯系
我們可以為一個不存在的文件創建一個File對象
也可以為存在的文件創建一個File對象
並在C#不知道的情況下將它移到別處
由於擁有CreateText或AppendText等向文件系統返回一個流的靜態方法
因此
與Java不同的是
C#中的File對象的作用要重要得多
在Java中要創建一個新文件或向文件寫內容
則必須使用FileInputStream
FileOutputStream fos = new FileOutputStream(
brand
new
file
txt
);
fos
write(
)
但在C#中就可以使用
Stream s = File
Create(
brand
new
file
txt
);
或者使用
StreamWriter sw = File
CreateText(
brand
new
file
txt
);
來得到一個新文件的Stream或StreamWriter
(Java中的添加可以通過設置FileOutputStream的構建者之一的append屬性來完成
)Java允許使用java
io
FileInputStream從文件中讀取內容
而C#則有Open Write和OpenText等靜態的方法
最後
C#在Open方法中提供了更詳細的控制━━這一方法允許設置文件的權限和訪問環境
表
操作文件讀寫的方法
C#中值得一提的改進是File
Copy方法
困擾大多數Java編程人員的一個與文件系統I/O有關的問題是不能正確地移動文件
java
io
File中包含一個可以對文件重新命名的renameTo方法
但它只在文件系統內有效
大多數情況下
編程人員都必須編寫自己的文件移動命令
一般是利用java
io
FileInputStream和java
io
FileOutputStream拷貝文件
然後再刪除原來的文件
C#中的Copy方法可以很方便地移動文件
但File
Move也不能跨卷和文件系統移動文件
C#的文件系統無須處理Java必須處理的跨平台問題
因此也就沒有與java
io
File
pathSeparator或java
io
File
separator功能類似的對象
不幸的是
這也就意味著在C#中不存在受到廣大編程人員喜愛的java
io
File構造器
public File( File parent
String child )
使用C#的編程人員可以使用下面的命令來構造一個新的System
IO
File對象
File parent
File child new File( parent
FullName +
\\
+ childName );
Understanding Networking
二種語言都圍繞著基本協議提供了一些抽象層
Java中的
Socket類的抽象程度要遠高於C#中的System
Net
Sockets
Socket類
Java和C#都提供了對網絡的不同抽象層
編程人員可以使用不同的網絡接口完成對網絡的操作
表
Java和C#中的網絡層次
應答/請求層可以用於HTTP類的請求
其中的一端開始啟動一個連接
發送一些字節的數據
然後停止
等待對方作為應答發回的一些字節
對於象流這樣更靈活的操作
協議層的用處更大
對於大多數的Java編程人員來說
除非需要完成性能非常高的網絡操作
不需要對套接字進行直接控制
如果需要
C#仍然提供了對原始的Berkeley套接字進行控制的能力
應答/請求層
這個層次抽象掉了所有網絡層的細節
提供了一個可以雙向傳輸數據的象流那樣的接口
Java可以接受HTTP URL
並通過下面的命令完成GET命令
URL url= new URL(
);
URLConnection urlConnection url
openConnection();
InputStream input urlConnection
getI
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19431.html