2014-01-06 22 views
0

我從一個pdf文件從android平板電腦客戶端發送到Java應用程序運行在Windows 7上。該文件總是以零字節的大小到達。這裏有什麼問題?套接字,發送的pdf文件總是到達零字節大小

在pdf文件從客戶端發送到服務器之前,文件的大小作爲長整型值從客戶端發送到服務器,這個大小是正確的並且總是到達服務器。對於pdf文件,我使用這個測試的大小是566718字節。

我怎樣才能得到PDF文件作爲正確的大小?

Server代碼

public class Server { 
ServerSocket serverSocket; 
Socket socket; 
boolean runner = true; 

Server() throws IOException{ 

    serverRunner(); 
    System.out.println("server constructor started"); 

} // Server() constructor 

public void serverRunner() throws IOException { 

    System.out.println("serverrunner started"); 

    try { 

     serverSocket = new ServerSocket(6789, 100); 

     runner = true; 

     while (runner) { 

      socket = serverSocket.accept(); 

      MultiThreader multi = new MultiThreader(socket); 
      Thread t = new Thread(multi); 
      t.start(); 

     } // while runner 
     } catch (IOException ex) { 

    } 

} // serverRunner() 

} // class Server 


public class MultiThreader implements Runnable { 
Socket socket; 
public int fileSizeFromClient; 
FileOutputStream fos = null; 
BufferedInputStream bis = null; 
BufferedOutputStream bos = null; 
DataInputStream dis = null; 
DataOutputStream dos = null; 

public MultiThreader(Socket socket){ 
    System.out.println("print out from multithreader class"); 
    this.socket = socket; 

} // multiThreader 

@Override 
public void run() { 

    System.out.println("multi threader started"); 

    // action #1 read file from client ===================================== 
    // transfer.pdf read this file sent from android device to this computer 

    int bufferSize = 0; 

    try { 

    bis = new BufferedInputStream(socket.getInputStream()); 
    dis = new DataInputStream(bis); 

    fileSizeFromClient = dis.readInt(); 
    System.out.println("file size from client is " + fileSizeFromClient); 

     File fileDirectory = new File("C:/DOWNLOAD/"); 
     if (!fileDirectory.exists()) { 
      fileDirectory.mkdir(); 
     } 
     File file = new File("C:/DOWNLOAD/transfer.pdf"); 
     file.createNewFile(); 

     fos = new FileOutputStream(file); 
     bos = new BufferedOutputStream(fos); 
     dos = new DataOutputStream(bos); 

     byte[] buffer = new byte[fileSizeFromClient]; 

     int totalBytesRead = 0; 

     while(totalBytesRead < fileSizeFromClient){ 
      int bytesRemaining = fileSizeFromClient = totalBytesRead; 
      int bytesRead = dis.read(buffer, 0, (int) Math.min(buffer.length, bytesRemaining)); 
      if(bytesRead == -1) { 
       break; 
      } else { 
       dos.write(buffer, 0, bytesRead); 
        totalBytesRead += bytesRead; 
      } 
     } // while 

     } catch (IOException ex) { 
     Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex); 
     } finally { 
     try { 
      // socket.close(); 
     } catch (IOException ex) { 
      Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

} // run 

} // MultiThreader 

客戶端代碼

public class MainActivity extends Activity implements Runnable { 

TextView textViewOne; 
Button buttonOne; 
Socket socket; 
private String serverIP = "192.XXX.X.X"; 
FileInputStream fis; 
FileOutputStream fos; 
private File file; 
DataInputStream dis; 
DataOutputStream dos; 
BufferedInputStream bis; 
BufferedOutputStream bos; 
long length; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    textViewOne = (TextView) findViewById(R.id.textView1); 
    buttonOne = (Button) findViewById(R.id.button1); 

    buttonOne.setOnClickListener(new OnClickListener() { 

    @Override 
    public void onClick(View v) { 
     Thread myThread = new Thread(MainActivity.this); 
     myThread.start(); 

    } 

    }); 

} // oncreate 

@Override 
public void run() { 

    MainActivity.this.runOnUiThread(new Runnable(){ 
     @Override 
     public void run() { 
      textViewOne.setText("run method started"); 
     } 
     }); 

    try { 
     socket = new Socket(InetAddress.getByName(serverIP), 6789); 

     if (socket == null) { 
      return; 
     } else { 
      MainActivity.this.runOnUiThread(new Runnable(){ 
       @Override 
       public void run() { 
        textViewOne.setText("connected"); 
       } 
       }); 

     } 

     file = new File(Environment.getExternalStorageDirectory().getPath() + File.separator + "transfer.pdf"); 

     length = file.length(); 

     fis = new FileInputStream(file); 
     bis = new BufferedInputStream(fis); 
     dis = new DataInputStream(bis); 

     bos = new BufferedOutputStream(socket.getOutputStream()); 
     dos = new DataOutputStream(bos); 

     dos.writeInt((int) length); // sends the length as number bytes is file size 

     int count = 0; 
     byte[] buffer = new byte[(int) length]; 

     while ((count = bis.read(buffer)) > 0) 
     { 
      bos.write(buffer, 0, count); 
     } 

     bos.flush(); 
     bis.close(); 
     socket.close(); 

    } catch (UnknownHostException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 

} // mainactivity 
+1

是否有任何異常記錄?你爲什麼不關閉服務器上的輸出流?你有沒有嘗試在複製循環中添加診斷? –

+0

您不需要調用createNewFile(),但您確實需要關閉輸出流。 – EJP

回答

2

這是我相信的問題。

int bytesRemaining = fileSizeFromClient = totalBytesRead; 

這是做兩項工作,所以你指派0至fileSizeFromClient立即和退出循環。

您的意思是:

int bytesRemaining = fileSizeFromClient - totalBytesRead; 

這是一個相當微妙的錯字,你是不幸,它是仍然導致有效的代碼:(

一個錯字既然你關閉套接字立即反正但是,目前還不清楚爲什麼你要先發送文件大小,如果你在客戶端和服務器端都有相同的「從輸入流到輸出流的複製,直到輸入用完數據」爲止,那麼代碼可能會更簡單。服務器,從FileInputStreamSocketOutputStream在客戶端,SocketInputStreamFileOutputStream(可能帶有緩衝包裝)在服務器上。

我還建議關閉全部流 - 如果您使用的是Java 7,那麼您可以簡單地使用try-with-resources語句來完成此操作;在早期版本中,您應該關閉finally塊中的流。

+0

這是正確的,那是問題,現在它工作 – Kevik

0

-拇指的規則,總是寫入/讀取並從中後關閉該流。

-關閉流在服務器端。與InputStream使用SocketScanner的插座之間無憂無慮的數據傳輸 -

。 (多數民衆贊成我的感受,試驗插座。)

+1

我絕對會*避免*在這裏使用'掃描儀'。這裏絕對沒有必要。 –

+0

Mr.Skeet,我已經嘗試過Scanner,InputStream和InputStreamReader的組合......我沒有覺得它爲我工作幾次...當我嘗試使用Socket,InputStream和Scanner的組合時,它已經在目標上轟炸了......我是你的忠實粉絲...我很想糾正我使用Scanner的錯誤,如果你可以讓我知道它的病態效果。我將被迫 –

+1

當你*不使用'Scanner'時,你不能真正地告訴你做錯了什麼,儘管如果你在非文本數據上使用了'InputStreamReader',那將是一個問題。但是我發現'Scanner' API的許多問題不像預期的那樣運作,而僅僅傳輸數據,'InputStream'和'OutputStream' API確實非常簡單。 –