I have a client server program where I need to serialize the file object and send it to the client.
At server side:
FileInputStream input_file = new FileInputStream(file);
object_output_stream.writeObject(input_file);
At client side:
FileOutputStream ouput_file = new FileOutputStream(new File(filename));
output_file = object_input_stream.readObject();
I need to serialize the input_file object and send it to the client. The ObjectOutputStream and ObjectInputStream are Non-Serializable. What would be the best way for this?
You cannot serialize files - that would imply that the client could read from a file at the server, which would require a complicated protocol that is simply not present in the Java serialization mechanism.
Your best best is to read the data from the file into a byte array, and to then either send the byte array plainly to the client, or to serialize the byte array in the ObjectOutputStream (you would do that if you want to send other objects as well)
You can use apache-commons IOUtils.toByteArray(InputStream input) to read a file into a byte[] easily.
On the server side:
FileInputStream input_file = new FileInputStream(file);
byte[] input_data = IOUtils.toByteArray(input_file);
object_output_stream.writeObject(input_data);
On the client side:
FileOutputStream output_file = new FileOutputStream(new File(filename));
byte[] input_data = (byte[]) object_input_stream.readObject();
output_file.write(input_data);
Related
By using instance of PrintStream and println function, I can send raw string to the client(s). But, I want to send whole .html file to the client in order to see the web page. For this reason, What should be my approach ? I have tried to read a file and give the whatever is read on the println function. But, attempts is failed.
Maby something like this will help:
// sendfile
File myFile = new File ("source.html");
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = sock.getOutputStream();
System.out.println("Sending...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
sock.close();
I need help on my homework, any help will be much appreciated. I can send small files without a problem. But when i try to send let’s say a 1GB file byte array sends OutOfMemoryError so i need a better solution to send file from server to client. How can i improve this code and send big files, please help me.
Server Code:
FileInputStream fis = new FileInputStream(file);
byte[] fileByte = new byte[fis.available()]; //This causes the problem.
bytesRead = fis.read(fileByte);
oos = new ObjectOutputStream(sock.getOutputStream());
oos.writeObject(fileByte);
Client Code:
ois = new ObjectInputStream(sock.getInputStream());
byte[] file = (byte[]) ois.readObject();
fos = new FileOutputStream(file);
fos.write(file);
Don't read the whole file into memory, use a small buffer and write while you are reading the file:
BufferedOutputStream bos = new BufferedOutputStream(sock.getOutputStream())
File file = new File("asd");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] buffer = new byte[1024*1024*10];
int n = -1;
while((n = bis.read(buffer))!=-1) {
bos.write(buffer,0,n):
}
Use Buffered* to optimize the writing and reading from Streams
Just split the array to smaller chunks so that you don't need to allocate any big array.
For example you could split the array into 16Kb chunks, eg new byte[16384] and send them one by one. On the receiving side you would have to wait until a chunk can be fully read and then store them somewhere and start with next chunk.
But if you are not able to allocate a whole array of the size you need on server side you won't be able to store all the data that you are going to receive anyway.
You could also compress the data before sending it to save bandwidth (and time), take a look at ZipOutputStream and ZipInputStream.
Here's how I solved it:
Client Code:
bis=new BufferedInputStream(sock.getInputStream());
fos = new FileOutputStream(file);
int n;
byte[] buffer = new byte[8192];
while ((n = bis.read(buffer)) > 0){
fos.write(buffer, 0, n);}
Server Code:
bos= new BufferedOutputStream(sock.getOutputStream());
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
int n=-1;
byte[] buffer = new byte[8192];
while((n = bis.read(buffer))>-1)
bos.write(buffer,0,n);
Depending on whether or not you have to write the code yourself, there are existing libraries which solve this problem, e.g. rmiio. If you are not using RMI, just plain java serialization, you can use the DirectRemoteInputStream, which is kind of like a Serializable InputStream. (this library also has support for things like auto-magically compressing the data).
Actually, if you are only sending file data, you would be better off ditching the Object streams and use DataInput/DataOutput streams. first write an integer indicating the file length, then copy the bytes directly to the stream. on the receiving side, read the integer file length, then read exactly that many bytes.
when you copy the data between streams, use a small, fixed size byte[] to move chunks of data between the input and output streams in a loop. there are numerous examples of how to do this correctly available online (e.g. #ErikFWinter's answer).
Im working on a Client/server chat application which allows user to send files (images / videos...) through a socket connection.
In order to manage all kind of communication, I use an Object "Packet" which stores all information that I want to send. (Sender, receivers, file ...).
Here is a code sample where I write in the stream :
private void write(Packet packet) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(packet);
this.outStream.write(bos.toByteArray());
}
And outStream is an OutputStream.
Here is my Connection run :
public void run() {
while (isRunning()) {
try {
byte[] buffer = new byte[65536];
// Read from the InputStream
inStream.read(buffer);
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer));
Packet p = (Packet) in.readObject();
} catch (IOException e) {
e.printStackTrace();
this.disconnect();
}
}
}
It works very well for all purpose except files transfer !
I put the file in a byte[] (with filestream) and store the array in my Packet Object.
When the server receive the communication it breaks on the "in.readObject()" and give me a pretty "java io streamcorruptedexception wrong format : 0" exception.
I tried the transfer with a custom byte[] (filled by a string.getBytes()) and it worked very well.
So, what am I doing wrong ?
You're reading from the InputStream to a byte array (with an arbitrary size which could be too small). Then you construct an ObjectInputStream to read from this byte array. Why don't you read your object directly from the InputStream?
ObjectInputStream in = new ObjectInputStream(inStream);
Packet p = (Packet) in.readObject();
No need for a buffer.
Moreover, InputStream.read() doesn't read everything from the InputStream. It reads what is available, and returns the number of bytes read. If you don't loop until it returns -1, you only read a part of what has been sent on the other side.
BTW, you're doing the same mistake on the sending side. Instead of writing your object directly to the output stream, you write it to a byte array, adn then send this byte array. Write your object directly to the stream:
ObjectOutputStream os = new ObjectOutputStream(this.outputStream);
os.writeObject(packet);
No need for a buffer.
In my java application I want to transfer some Images from client to server.
I am using Socket to connect client with server.
It is working when I transfer string from client to server but I am not able to transfer Image file.
I am using
BufferedInputStream
BufferedOutputStream
for transferring string.
I know for transferring file I need to use FileInputStream as:
BufferedInputStream bis bis = new BufferedInputStream(new FileInputStream("111.JPG"));
But I don't know, what exactly I need to write.
so please give your answer by some sample of code.
You should convert image to byte.
You can use this function.
static byte[] ImageToByte(System.Drawing.Image iImage)
{
MemoryStream mMemoryStream = new MemoryStream();
iImage.Save(mMemoryStream,
System.Drawing.Imaging.ImageFormat.Gif);
return mMemoryStream.ToArray();
}
And you can call this function in your server program.
Bitmap tImage = new Bitmap(Image URL goes here);
byte[] bStream = ImageToByte(tImage);
while (true)
{
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected");
while (client.Connected)
{
NetworkStream nStream = client.GetStream();
nStream.Write(bStream, 0,
bStream.Length);
}
}
There are many examples on the internet already:
here
here
etc.
Please consider using google next time.
I'm creating a TFTP server. I've got it tranfering files fine but most of the files wont open when they arrive at the other end. This is because the output of the ArrayList im using to store file bytes from every packet received adds a load of bytes to the start of the file. eg. "¬í sr java.util.ArrayListxÒ™Ça I sizexp w ur [B¬óøTà xp ü!". The reason for using the List in the first place is that the server im creating has no way to tell the file size of the file which is being received. Therefore as far as I can tell I cant use a byte[] as this needs to be initialised with a set length. Is there any way round this?
WRQ WRQ = new WRQ();
ACK ACK = new ACK();
DatagramPacket outPacket;
byte[] bytes;
byte[] fileOut;
List fileBytes = new ArrayList();
outPacket = WRQ.firstPacket(packet);
socket.send(outPacket);
socket.receive(packet);
while (packet.getLength() == 516){
bytes = WRQ.doWRQ(packet);
fileBytes.add(bytes);
outPacket = ACK.doACK(packet);
socket.send(outPacket);
socket.receive(packet);
}
bytes = WRQ.doWRQ(packet);
fileBytes.add(bytes);
outPacket = ACK.doACK(packet);
socket.send(outPacket);
ObjectOutputStream os;
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(5000);
os = new ObjectOutputStream(new BufferedOutputStream(byteStream));
os.flush();
os.writeObject(fileBytes);
os.flush();
byte[] outFile = byteStream.toByteArray();
os.close();
FileOutputStream foStream = new FileOutputStream(filename);
foStream.write(outFile);
foStream.close();
You store byte arrays in an ArrayList, and then you write the whole ArrayList to a ByteArrayOutputStream wrapped in an ObjectOutputStream, using the writeObject() method.
This uses the native Object serialization mechanism to save the ArrayList object. It doesn't write every byte array in the list one after the other. To make it clear: it writes the class name, and the internal structure of the ArrayList, using the object serialization protocol.
You don't need an ArrayList. Write directly to a ByteArrayOutputStream, or even directly to a FileOutputStream. As is, you're trying to
write bytes to a list
write the bytes in the list to a byte array
write the byte array to a file.
It would be much more straightforward (and efficient) to write directly to the output file (wrapped in a BufferedOutputStream for buffering)