本文提供基於 Java Socket 的文件傳輸完整代碼,實現客戶端讀取本地文件透過 TCP 發送至伺服器,伺服器接收寫入磁碟並回傳確認訊息。
shutdownOutput()) 標記傳輸結束import java.io.*;
import java.net.*;
class send2 {
public static void main(String[] args) throws Exception {
// 1. 建立連接
Socket socket = new Socket("192.168.33.1", 10005);
// 2. 讀取本地文件
BufferedReader fileReader = new BufferedReader(new FileReader("io.java"));
// 3. 獲取網路輸出流,自動 flush
PrintWriter netOut = new PrintWriter(socket.getOutputStream(), true);
// 4. 逐行讀取並發送
String line;
while ((line = fileReader.readLine()) != null) {
netOut.println(line);
}
// 5. 關鍵:關閉輸出流,發送 EOF 信號
socket.shutdownOutput();
// 6. 接收伺服器回應
BufferedReader netIn = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String response = netIn.readLine();
System.out.println("伺服器回應: " + response);
// 7. 關閉資源
fileReader.close();
socket.close();
}
}
import java.io.*;
import java.net.*;
class rece2 {
public static void main(String[] args) throws Exception {
// 1. 建立伺服器 Socket
ServerSocket serverSocket = new ServerSocket(10005);
// 2. 接受客戶端連接 (阻塞)
Socket socket = serverSocket.accept();
// 3. 讀取網路輸入流
BufferedReader netIn = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
// 4. 寫入本地文件
PrintWriter fileOut = new PrintWriter(new FileWriter("io2.txt"), true);
String line;
while ((line = netIn.readLine()) != null) {
// 可選:特殊標記結束
// if ("over".equals(line)) break;
fileOut.println(line);
}
// 5. 發送成功確認
PrintWriter netOut = new PrintWriter(socket.getOutputStream(), true);
netOut.println("上傳成功!");
// 6. 關閉資源 (順序很重要)
fileOut.close();
serverSocket.close();
socket.close();
}
}
readLine() 返回 null,read() 返回 -1readLine() 等待更多資料PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
// 第二參數 true = autoFlush,每次 println/printf/format 後自動 flush
確保資料即時發送,不滯留在緩衝區。
| 模式 | 適用場景 | 類別 | 注意事項 |
|---|---|---|---|
| 文字模式 | 原始碼、配置、日誌、CSV 等文本文件 | Reader/Writer, PrintWriter, BufferedReader | 自動處理換行符,編碼需一致 (UTF-8) |
| 二進位模式 | 圖片、視頻、壓縮包、執行檔等二進位文件 | InputStream/OutputStream, FileInputStream, FileOutputStream | 使用 byte[] 緩衝區,無編碼轉換,保真度高 |
// 發送端
try (FileInputStream fis = new FileInputStream("image.jpg");
OutputStream out = socket.getOutputStream()) {
byte[] buffer = new byte[8192];
int len;
while ((len = fis.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
socket.shutdownOutput();
}
// 接收端
try (InputStream in = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("received.jpg")) {
byte[] buffer = new byte[8192];
int len;
while ((len = in.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
}
原因:網路不穩、緩衝區溢出、無超時設定
方案:
socket.setSoTimeout(30000) 讀取超時原因:編碼不一致 (客戶端 UTF-8,伺服器 GBK)
方案:
new InputStreamReader(in, "UTF-8")原因:單執行緒 accept() 循環
方案:
accept() 後啟動新 Thread 處理Java Socket 文件傳輸核心在於:shutdownOutput() 正確標記結束、二進位模式保真傳輸、資源正確關閉順序。文字模式適合文本文件,二進位模式通用性更強。生產環境需增加協議層、錯誤處理、安全機制與監控能力。