簡體   English   中英

Java TCP-使用DataOutputStream發送文件

[英]Java TCP - Sending a file using DataOutputStream

嗨,謝謝你。

因此,當前,我正在嘗試讓我的TCP程序從目錄(這是服務器端)讀取文件,然后將該文件發送到請求該文件的套接字(客戶端)。

這是我的代碼:

服務器端:

File FileList = new File(".....filepath....");
Scanner scan = new Scanner(FileList);

//idToFile just searching for the name of the file the client asked for
String TheName = idToFile(Integer.toString(result));

//Opens the chosen file such as an image to be used     
File myImageFile = new File("....filepath...." + TheName);

//sendResponse is a function with a writeUTF (but only works for strings)
sendResponse("#OK");
sendResponse(TheName);
sendResponse(Long.toString(myImageFile.length()));

//This line causes the error and says that it expected a string and not a file          
output.writeUTF(myImageFile);


private void sendResponse(String response)
    {
        try 
        {
            output.writeUTF(response);
        } 
        catch (IOException ex) 
        {
            ex.printStackTrace();
        }
    }

客戶端:

ClientHandler client = new ClientHandler();


//getResponse just catches the written strings, but it can't work with a file either
String TheMessage = client.getResponse();
String Name = client.getResponse();
long FileSize = Long.parseLong(client.getResponse());

這是ClientHandler的代碼:

public class ClientHandler 
{
    private static int port = 2016;

    private DataInputStream input;
    private DataOutputStream output;

    private Socket cSocket; 


    public ClientHandler()
    {
        cSocket = null;

        try
        {
            cSocket = new Socket("localhost", port); //connecting to the server 
            System.out.println("Client is connected on port " + port);

            output = new DataOutputStream(cSocket.getOutputStream());
            input = new DataInputStream(cSocket.getInputStream());
        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
    }

    public void sendMessage(String message) //checking if the message is sent
    {
        try
        {
            output.writeUTF(message);
            output.flush();
            System.out.println("Message sent to the server");
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
        }
    }

    public String getResponse()
    {
        String msg = "";
        try
        {
              msg = input.readUTF();
        }
        catch(IOException ex)
        {
            ex.printStackTrace(); 
        }
        return msg;
    }

}

那么,如何使用DataOutputStream將任何類型的文件從服務器發送到客戶端,以及我的客戶端如何使用DataInputStream捕獲該文件並將其保存到磁盤?

謝謝。

如下所示創建DataOutputStreamDataInputStream的新實例。

DataOutputStream socketOut = new DataOutputStream(socketObject.getOutputStream());
DataInputStream  socketIn  = new DataInputStream(socketObject.getInputStream());

有關示例代碼,請簽出本講義中顯示的示例類

為了快速參考,以下是示例類的摘錄

DataInputStream streamIn = new 
              DataInputStream(new 
              BufferedInputStream(client.getInputStream()));
String incomingDataLine = streamIn.readLine();
...
...
DataOutputStream socketOut = new DataOutputStream(client.getOutputStream());
socketOut.writeBytes(line + '\n');

=========編輯1:閱讀評論后

網絡上的任何內容都是1和0,即字節。 假設您要將映像從一台服務器傳輸到另一台服務器,那么推薦的方法是讓服務器讀取文件內容(以字節java.nio.Files.readAllBytes()並將其寫入套接字)。

在客戶端,從套接字讀取所有字節(在實際項目中使用BufferedReader)並將其寫入磁盤。 您必須確保服務器和客戶端都使用相同的編碼。

使用BufferedInputStream和BufferedOutputStream代替DataXXXStream。

這將適用於任何文件類型-mp3,mp4,jpeg,png,acc,txt,java。 要使其在客戶端系統中可用,請確保創建具有正確擴展名的文件。

這里以一個簡單的服務器為例,該服務器將二進制文件發送到每個客戶端,而無需進一步的交互。

套接字提供輸出流以將字節寫入客戶端。 我們有一個要發送的文件“ picin.jpg”,因此我們需要將此文件的每個字節寫入套接字的輸出流。 為了做到這一點,我們使用包裹在BufferedInputStreamFileInputStream

package networking;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

  public static void main(String[] args) {
    try {
      ServerSocket ss = new ServerSocket();
      ss.bind(new InetSocketAddress("localhost", 4711));
      for(;;) {
        Socket sock = ss.accept();
        System.out.println("Connected to " + sock.getInetAddress());
        try (
          InputStream in = new BufferedInputStream(new FileInputStream("picin.jpg"));
          OutputStream out = sock.getOutputStream();
        ) 
        {
          int bytesSent = Util.copy(in, out);
          System.out.println(String.format("%d bytes sent.", bytesSent));
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}

我將copy方法提取到util類中,因為我們需要客戶端中完全相同的方法。 我們使用一個小字節數組作為緩沖區,然后將一個塊又一個塊從一個流復制到另一個流。

package networking;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Util {
  public static int copy(InputStream in, OutputStream out) throws IOException {
    byte[] buf = new byte[2048];
    int bytesRead = 0;
    int totalBytes = 0;
    while((bytesRead = in.read(buf)) != -1) {
      totalBytes += bytesRead;
      out.write(buf, 0, bytesRead);
    }
    return totalBytes;
  }

}

客戶端打開與服務器的連接,並將接收到的字節寫入文件。 套接字為輸入流提供來自服務器的字節。 我們使用包裹在BufferedOutputStreamFileOutputStream寫入文件。 我們使用相同的Util.copy()方法將字節實際上從一個流復制到另一個流。

package networking;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class Client {

  public static void main(String[] args) {
    try {
      Socket sock = new Socket(InetAddress.getByName("localhost"), 4711);
      try(
        InputStream in = sock.getInputStream();
        OutputStream out = new BufferedOutputStream(new FileOutputStream("picout.jpg"))
      )
      {
        System.out.println("Connected to " + sock.getRemoteSocketAddress());
        int bytesCopied = Util.copy(in, out);
        System.out.println(String.format("%d bytes received", bytesCopied));
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}

注意:流通過try-with-ressources語句自動關閉。 關閉套接字,同時關閉相應的流。

Java 8包含一些方便的方法,可將字節從文件復制到輸出流或從輸入流復制到文件。 參見java.nio.file.Files

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM