2017-10-02 17 views
0

こんにちは、ありがとうございます。Java TCP - 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; 
    } 

} 

だから、どのようにすることができます私はDataOutpを使うutStreamを使用して、サーバーからクライアントにファイルを送信し、クライアントがDataInputStreamを使用してファイルをキャッチしてディスクに保存する方法を教えてください。

ありがとうございます。

+0

「出力」とは何ですか? 'sendResponse'のスニペットを共有できますか? – Archit

+0

これは何ですか?あなたは何を使っていますか? 'sendResponse''出力 ''クライアント '??? – Oleg

+0

私は今それらをすべて追加します – Duckman

答えて

1

新しいインスタンスをDataOutputStreamDataInputStreamのように作成します。サンプルコードについて

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

、ここで、クイックリファレンスについてin this lecture notes.

を示すサンプルクラスをチェックアウトサンプルクラスからスニペット

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を使用してソケットからすべてのバイトを読み取り、ディスクに書き込みます。サーバーとクライアントの両方が同じエンコーディングを使用していることを確認する必要があります。

DataXXXStreamの代わりにBufferedInputStreamとBufferedOutputStreamを使用します。

これはmp3、mp4、jpeg、png、acc、txt、javaのいずれのファイルタイプでも機能します。クライアントシステムで使用できるようにするには、正しい拡張子を持つファイルを作成してください。

+0

その文字列を送信したいです。私は、テキストファイル、画像ファイル、またはビデオファイルなどのファイルを送信できるようにしたい。基本的に私はストリームの上にそれらの種類のファイル(または技術的に他のもの)を送ることができる必要があります。 – Duckman

+1

@Duckmanネットワーク上のものはすべて1と0、つまりバイトです。ファイルの内容を送信する場合は、java.nio.Fileオブジェクトをシリアル化するか(推奨しません)、java.nio.Files.readAllBytes()を使用してコンテンツをバイトとして取得します。 – rohitmohta

0

ここでは例として、バイナリファイルをそれ以上の相互作用なしに各クライアントに送信する単純なサーバーを示します。

ソケットは、バイトをクライアントに書き込むための出力ストリームを提供します。送信したいファイル "picin.jpg"があるので、このファイルのすべてのバイトをソケットの出力ストリームに書き込む必要があります。これを行うには、BufferedInputStreamにラップされたFileInputStreamを使用します。

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(); 
    } 
    } 

} 

コピーメソッドをutilクラスに抽出しました。これは、クライアントで完全に同じものが必要なためです。小さなバイト配列をバッファとして使用し、あるストリームから別のストリームへと1つのチャンクをコピーします。

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; 
    } 

} 

クライアントは、サーバーへの接続を開き、受信したバイトをファイルに書き込みます。ソケットは、入力ストリームにサーバーからのバイトを提供します。ファイルに書き込むためににラップされたFileOutputStreamを使用します。同じUtil.copy()メソッドを使用して、1つのストリームから別のストリームに実際にバイトをコピーします。

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

+0

ありがとうございました。それは私がする必要がある大きなチャンクを解決しました。これで、イメージファイルをクライアント側に正常に保存できるようになりました(ただし、イメージの最後の数バイトを切り捨てるように見えます)が、まだ例外が表示されます。ここにあります:java.lang.ArrayIndexOutOfBoundsException:len == -1 off == 0バッファ長== 4096.何が問題なのでしょうか? – Duckman

+0

また、ストリームは自動的に閉じられると言いますが、もう1つのアクション(クライアントはログアウトボタンを使用しています)を開いておく必要があります。どのようにストリームを開いたままにすることができますか? – Duckman

+0

これを出発点にしてください。あなた自身でもっとやりなさい。例外がある場合は、例外クラス 'docs。実行をスローする特定の関数のドキュメントを読んでください。そのような例外がスローされたときにヒントがあることがあります。デバッガの使い方を学んでください。あなたのコードを試してみてください。コードの各行が何をするのかを理解してください。ストリームを開いたままにしたい場合は、作業が完了する前にストリームを閉じないでください。 – vanje

関連する問題