歡迎您光臨本站 註冊首頁

Java實現Socket發送和接收文件的代碼

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0

  這是一個簡單的包含發送端和接收端的例子.發送端向接收端發送文件名和文件內容,接收端將收到的文件保存在磁碟上.接收端可以同時接收多個發送端傳來的文件,但沒有處理文件同名的情況.

  這個例子中設計了一個簡單的協議.發送的內容是這樣的:

  文件名長度(4位元組)—文件名—文件內容長度(4位元組)—文件內容.

  接收端也按照這個結構進行解析.建議先看 Client 類,再看 Server 類.

  import java.io.*;

  import java.net.ServerSocket;

  import java.net.Socket;

  /**

  * 簡單的文件發送與接收示例

  */

  public class FileTrasmission {

  //程序入口

  public static void main(String[] args) throws Exception {

  int port = 7788;

  new Server(port, "c:\save\").start();

  new Client().sendFile("127.0.0.1", port, "c:\迷失在康熙末年.txt");

  }

  }

  /**

  * 接收端.可同時接收多個發送端發來的文件.但如果發來的文件是同名的話那就亂了.

  */

  class Server {

  private int listenPort;

  private String savePath;

  /**

  * 構造方法

  *

  * @param listenPort 偵聽埠

  * @param savePath 接收的文件要保存的路徑

  *

  * @throws IOException 如果創建保存路徑失敗

  */

  Server(int listenPort, String savePath) throws IOException {

  this.listenPort = listenPort;

  this.savePath = savePath;

  File file = new File(savePath);

  if (!file.exists() && !file.mkdirs()) {

  throw new IOException("無法創建文件夾 " savePath);

  }

  }

  // 開始偵聽

  public void start() {

  new ListenThread().start();

  }

  // 網上抄來的,將位元組轉成 int.b 長度不得小於 4,且只會取前 4 位.

  public static int b2i(byte[] b) {

  int value = 0;

  for (int i = 0; i < 4; i ) {

  int shift = (4 - 1 - i) * 8;

  value = (b[i] & 0x000000FF) << shift;

  }

  return value;

  }

  /**

  * 偵聽線程

  */

  private class ListenThread extends Thread {

  @Override

  public void run() {

  try {

  ServerSocket server = new ServerSocket(listenPort);

  // 開始循環

  while (true) {

  Socket socket = server.accept();

  new HandleThread(socket).start();

  }

  } catch (IOException e) {

  e.printStackTrace();

  }

  }

  }

  /**

  * 讀取流並保存文件的線程

  */

  private class HandleThread extends Thread {

  private Socket socket;

  private HandleThread(Socket socket) {

  this.socket = socket;

  }

  @Override

  public void run() {

  try {

  InputStream is = socket.getInputStream();

  readAndSave(is);

  } catch (IOException e) {

  e.printStackTrace();

  } finally {

  try {

  socket.close();

  } catch (IOException e) {

  // nothing to do

  }

  }

  }

  // 從流中讀取內容並保存

  private void readAndSave(InputStream is) throws IOException {

  String filename = getFileName(is);

  int file_len = readInteger(is);

  System.out.println("接收文件:" filename ",長度:" file_len);

  readAndSave0(is, savePath filename, file_len);

  System.out.println("文件保存成功(" file_len "位元組).");

  }

  private void readAndSave0(InputStream is, String path, int file_len) throws IOException {

  FileOutputStream os = getFileOS(path);

  readAndWrite(is, os, file_len);

  os.close();

  }

  // 邊讀邊寫,直到讀取 size 個位元組

  private void readAndWrite(InputStream is, FileOutputStream os, int size) throws IOException {

  byte[] buffer = new byte[4096];

  int count = 0;

  while (count < size) {

  int n = is.read(buffer);

  // 這裡沒有考慮 n = -1 的情況

  os.write(buffer, 0, n);

  count = n;

  }

  }

  // 讀取文件名

  private String getFileName(InputStream is) throws IOException {

  int name_len = readInteger(is);

  byte[] result = new byte[name_len];

  is.read(result);

  return new String(result);

  }

  // 讀取一個數字

  private int readInteger(InputStream is) throws IOException {

  byte[] bytes = new byte[4];

  is.read(bytes);

  return b2i(bytes);

  }

  // 創建文件並返回輸出流

  private FileOutputStream getFileOS(String path) throws IOException {

  File file = new File(path);

  if (!file.exists()) {

  file.createNewFile();

  }

  return new FileOutputStream(file);

  }

  }

  }

  ======================================

  /**

  * 發送端

  */

  class Client {

  // 網上抄來的,將 int 轉成位元組

  public static byte[] i2b(int i) {

  return new byte[]{

  (byte) ((i >> 24) & 0xFF),

  (byte) ((i >> 16) & 0xFF),

  (byte) ((i >> 8) & 0xFF),

  (byte) (i & 0xFF)

  };

  }

  /**

  * 發送文件.文件大小不能大於 {@link Integer#MAX_VALUE}

  *

  * @param hostname 接收端主機名或 IP 地址

  * @param port 接收端埠號

  * @param filepath 文件路徑

  *

  * @throws IOException 如果讀取文件或發送失敗

  */

  public void sendFile(String hostname, int port, String filepath) throws IOException {

  File file = new File(filepath);

  FileInputStream is = new FileInputStream(filepath);

  Socket socket = new Socket(hostname, port);

  OutputStream os = socket.getOutputStream();

  try {

  int length = (int) file.length();

  System.out.println("發送文件:" file.getName() ",長度:" length);

  // 發送文件名和文件內容

  writeFileName(file, os);

  writeFileContent(is, os, length);

  } finally {

  os.close();

  is.close();

  }

  }

  // 輸出文件內容

  private void writeFileContent(InputStream is, OutputStream os, int length) throws IOException {

  // 輸出文件長度

  os.write(i2b(length));

  // 輸出文件內容

  byte[] buffer = new byte[4096];

  int size;

  while ((size = is.read(buffer)) != -1) {

  os.write(buffer, 0, size);

  }

  }

  // 輸出文件名

  private void writeFileName(File file, OutputStream os) throws IOException {

  byte[] fn_bytes = file.getName().getBytes();

  os.write(i2b(fn_bytes.length)); // 輸出文件名長度

  os.write(fn_bytes); // 輸出文件名

  }

  }


[火星人 ] Java實現Socket發送和接收文件的代碼已經有709次圍觀

http://coctec.com/docs/java/show-post-60752.html