[英]Issue sending byte array over objectoutputstream in java
我正在嘗試為相當復雜的Java服務器編寫上傳系統。 我在下面列出的兩個小程序中重現了這個錯誤。 基本上,我使用ObjectOutputStream / ObjectInputStream通過客戶端/服務器進行通信。 這是一項要求; 我有數千行代碼在這個ObjectOutputStream / ObjectInputStream設置下運行得非常好,所以我必須能夠在上傳完成后仍然使用這些流。
要訪問文件(在客戶端上讀取的文件和正在服務器上寫入的文件),使用FileInputStream和FileOutputStream。 我的客戶似乎運作正常; 它讀入文件並在每次迭代時發送一個不同的字節數組(它一次讀取1MB,因此可以處理大型文件而不會溢出堆)。 但是,在服務器上,似乎字節數組總是只發送第一個數組(文件的前1MB)。 這不符合我對ObjectInputStream / ObjectOutputStream的理解。 我正在尋求解決這個問題的工作方法,或者就此問題進行足夠的教育,以形成我自己的解決方案。
以下是客戶端代碼:
import java.net.*;
import java.io.*;
public class stupidClient
{
public static void main(String[] args)
{
new stupidClient();
}
public stupidClient()
{
try
{
Socket s = new Socket("127.0.0.1",2013);//connect
ObjectOutputStream output = new ObjectOutputStream(s.getOutputStream());//init stream
//file to be uploaded
File file = new File("C:\\Work\\radio\\upload\\(Op. 9) Nocturne No. 1 in Bb Minor.mp3");
long fileSize = file.length();
output.writeObject(file.getName() + "|" + fileSize);//send name and size to server
FileInputStream fis = new FileInputStream(file);//open file
byte[] buffer = new byte[1024*1024];//prepare 1MB buffer
int retVal = fis.read(buffer);//grab first MB of file
int counter = 0;//used to track progress through upload
while (retVal!=-1)//until EOF is reached
{
System.out.println(Math.round(100*counter/fileSize)+"%");//show current progress to system.out
counter += retVal;//track progress
output.writeObject("UPACK "+retVal);//alert server upload packet is incoming, with size of packet read
System.out.println(""+buffer[0]+" "+buffer[1]+" "+buffer[2]);//preview first 3 bytes being sent
output.writeObject(buffer);//send bytes
output.flush();//make sure all bytes read are gone
retVal = fis.read(buffer);//get next MB of file
}
System.out.println(Math.round(100*counter/fileSize)+"%");//show progress at end of file
output.writeObject("UPLOAD_COMPLETE");//let server know protocol is finished
output.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
以下是我的服務器代碼:
import java.net.*;
import java.io.*;
public class stupidServer
{
Socket s;
ServerSocket server;
public static void main(String[] args)
{
new stupidServer();
}
public stupidServer()
{
try
{
//establish connection and stream
server = new ServerSocket(2013);
s = server.accept();
ObjectInputStream input = new ObjectInputStream(s.getInputStream());
String[] args = ((String)input.readObject()).split("\\|");//args[0] will be file name, args[1] will be file size
String fileName = args[0];
long filesize = Long.parseLong(args[1]);
String upack = (String)input.readObject();//get upload packet(string reading UPACK [bytes read])
FileOutputStream outStream = new FileOutputStream("C:\\"+fileName.trim());
while (!upack.equalsIgnoreCase("UPLOAD_COMPLETE"))//until protocol is complete
{
int bytes = Integer.parseInt(upack.split(" ")[1]);//get number of bytes being written
byte[] buffer = new byte[bytes];
buffer = (byte[])input.readObject();//get bytes sent from client
outStream.write(buffer,0,bytes);//go ahead and write them bad boys to file
System.out.println(buffer[0]+" "+buffer[1]+" "+buffer[2]);//peek at first 3 bytes received
upack = (String)input.readObject();//get next 'packet' - either another UPACK or a UPLOAD_COMPLETE
}
outStream.flush();
outStream.close();//make sure all bytes are in file
input.close();//sign off
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
一如既往,非常感謝您的時間!
您當前的問題是ObjectOutputStream
使用ID機制來避免多次在流上發送相同的對象。 客戶端將為buffer
的第二次和后續寫入發送此ID,服務器將使用其緩存值。
這個直接問題的解決方案是添加對reset()的調用:
output.writeObject(buffer);//send bytes
output.reset(); // force buffer to be fully written on next pass through loop
除此之外,您通過在它們之上分層您自己的協議來濫用對象流。 例如,將文件名和文件大小寫為由“|”分隔的單個字符串; 只需將它們寫為兩個獨立的值。 同上每個寫入的字節數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.