在java中通过objectoutputstream发送字节数组的问题
我正试图为一个相当复杂的java服务器编写一个上传系统。我在下面列出的两个小程序中重现了这个错误。基本上,我使用ObjectOutputStream/ObjectInputStream通过客户机/服务器进行通信。这是一项要求;在ObjectOutputStream/ObjectInputStream设置周围,我有数千行代码可以很好地工作,因此在上传完成后,我必须能够仍然使用这些流 要访问文件(在客户端读取的文件和在服务器上写入的文件),请使用FileInputStream和FileOutputStream。我的客户似乎运作良好;它读取文件并在每次迭代中发送不同的字节数组(每次读取1MB,因此可以在不溢出堆的情况下处理大型文件)。但是,在服务器上,字节数组似乎总是第一个发送的数组(文件的前1MB)。这不符合我对ObjectInputStream/ObjectOutputStream的理解。我正在寻求这个问题的有效解决方案,或者就这个问题进行足够的教育,以形成我自己的解决方案 以下是客户端代码:在java中通过objectoutputstream发送字节数组的问题,java,sockets,bytearray,objectoutputstream,Java,Sockets,Bytearray,Objectoutputstream,我正试图为一个相当复杂的java服务器编写一个上传系统。我在下面列出的两个小程序中重现了这个错误。基本上,我使用ObjectOutputStream/ObjectInputStream通过客户机/服务器进行通信。这是一项要求;在ObjectOutputStream/ObjectInputStream设置周围,我有数千行代码可以很好地工作,因此在上传完成后,我必须能够仍然使用这些流 要访问文件(在客户端读取的文件和在服务器上写入的文件),请使用FileInputStream和FileOutputS
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机制来避免在流上多次发送同一对象。客户端将在第二次和后续写入缓冲区时发送此ID,服务器将使用其缓存值
解决这个紧迫问题的方法是添加一个调用:
除此之外,通过在对象流之上分层您自己的协议,您正在滥用对象流。例如,将文件名和文件大小写入以“|”分隔的单个字符串;只需将它们写成两个独立的值。每次写入的字节数也是如此。您当前的问题是ObjectOutputStream
使用ID机制来避免在流上多次发送相同的对象。客户端将在第二次和后续写入缓冲区时发送此ID,服务器将使用其缓存值
解决这个紧迫问题的方法是添加一个调用:
除此之外,通过在对象流之上分层您自己的协议,您正在滥用对象流。例如,将文件名和文件大小写入以“|”分隔的单个字符串;只需将它们写成两个独立的值。每次写入的字节数也是如此。正好解决了这个问题。我不知道发送的对象是缓存的,我还有一些阅读要做。。。。非常感谢你的帮助!这正好解决了问题。我不知道发送的对象是缓存的,我还有一些阅读要做。。。。非常感谢你的帮助!
output.writeObject(buffer);//send bytes
output.reset(); // force buffer to be fully written on next pass through loop