2014-01-06 24 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确实非常简单。 –