I have this simple Server/Client application. I'm trying to get the Server to send a file through an OutputStream (FileOutputStream, OutputStream, ObjectOutputStream, etc) and receive it at the client side before saving it into an actual file. The problem is, I've tried doing this but it keeps failing. Whenever I create the file and write the object I received from the server into it, I get a broken image (I just save it as a jpg, but that shouldn't matter). Here are the parts of the code which are most likely to be malfunctioning (all the seemingly un-declared objects you see here have already been declared beforehand):
Server:
ObjectOutputStream outToClient = new ObjectOutputStream(
connSocket.getOutputStream());
File imgFile = new File(dir + children[0]);
outToClient.writeObject(imgFile);
outToClient.flush();
Client:
ObjectInputStream inFromServer = new ObjectInputStream(
clientSocket.getInputStream());
ObjectOutputStream saveImage = new ObjectOutputStream(
new FileOutputStream("D:/ServerMapCopy/gday.jpg"));
saveImage.writeObject(inFromServer.readObject());
So, my problem would be that I can't get the object through the stream correctly without getting a broken file.
A File object represents the path to that file, not its actual content. What you should do is read the bytes from that file and send those over your ObjectOutputStream.
File f = ...
ObjectOutputStream oos = ...
byte[] content = Files.readAllBytes(f.toPath);
oos.writeObject(content);
File f=...
ObjectInputStream ois = ...
byte[] content = (byte[]) ois.readObject();
Files.write(f.toPath(), content);
You are not actually transferring the file, but the File instance from Java. Think of your File object as a (server-)local handle to the file, but not its contents. For transferring the image, you'd actually have to read it on the server first.
However, if you're just going to save the bytes on the client anyway, you can forget about the ObjectOutputStream to begin with. You can just transfer the bytes stored in the File. Take a look at the FileChannel class and its transferTo and transferFrom methods as a start.
Related
Currently I want to create a zip file and make it available in the browser via HTTP response. Because I don't want to cache files on the hard disk I have to use streams all the time. The problem is that after creating the zip file I only have one ByteArrayOutputStream, but for sending the response I need an InputStream.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(baos);
// filling zip with multiple ZipEntrys
IOUtils.closeQuietly(zip);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
IOUtils.closeQuietly(baos);
The line
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
gives me a null pointer every time.
What is wrong? Is there a stream not completely written? Additionally I have to do everything with Java 6 and Apache commons.
I need to create a ZIP file which consists of files that are created on-the-fly and have no persistence on the file system.
For example: I want to create an SQLite database in memory and after populating it with data I want to add it to a - not yet existing - ZIP file and than I want to actually write this ZIP file to the file system.
I found several approaches where the files, which are going to be the content of the archive, have to be read from the file system.
Is there actually a way to archive what I want to do? I hoped that compress-commons would help me but apparently they don't.
Do I miss something?
If the in memory object you are trying to zip is serializable, then this is quite easy.
You can take any serializable instance and turn it in to a byte[]. I have a utility method to do this:
public static byte[] convertToBytes(Object object) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos)) {
out.writeObject(object);
out.flush();
return bos.toByteArray();
}
}
Once you have a that object represented in bytes, you can use a ZipOutputStream to zip it up:
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
GZIPOutputStream out = new GZIPOutputStream(bos); ) {
out.write(bytes);
out.finish();
byte[] compressed = bos.toByteArray(); // this is my compressed data
}
(I use Gzip here for simplicity but you can also create a zip with multiple entries, for example).
Is there any way through which we can write the response from GUI(I was updating some data into a text box) into a file(In any format) using java code.
I am updating some values in GUI and in our java code I want to get all that data and store it into a file.
Yes you can write objects into a file.ser (serialized file).
Below is an example of how to write to a file using FOS.
FileOutputStream fout = new FileOutputStream("c:\\object.ser");
ObjectOutputStream oos = new ObjectOutputStream(fout);
Objec Obj ;
oos.writeObject(Obj);
oos.close();
I want to open a specific file and zip it and send the byte array of the zipped result over UDP.
Now I checked the java zip API but it only give me to save the zipped file to the computer and opening it again and send it would be inefficiency.
Is there any way to do what I need without writing an implementation of the compression algorithm of my own ?
You cand wrap your ZipOutputStream around a ByteArrayOutputStream and get the bytes out of the ByteArrayOutputStream.
Something like this:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
//write the entries
zos.close();
byte[] bytes = baos.toByteArray();
I have a database file in res/raw/ folder. I am calling Resources.openRawResource() with the file name as R.raw.FileName and I get an input stream, but I have an another database file in device, so to copy the contents of that db to the device db I use:
BufferedInputStream bi = new BufferedInputStream(is);
and FileOutputStream, but I get an exception that database file is corrupted. How can I proceed?
I try to read the file using File and FileInputStream and the path as /res/raw/fileName, but that also doesn't work.
Yes, you should be able to use openRawResource to copy a binary across from your raw resource folder to the device.
Based on the example code in the API demos (content/ReadAsset), you should be able to use a variation of the following code snippet to read the db file data.
InputStream ins = getResources().openRawResource(R.raw.my_db_file);
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
int size = 0;
// Read the entire resource into a local byte buffer.
byte[] buffer = new byte[1024];
while((size=ins.read(buffer,0,1024))>=0){
outputStream.write(buffer,0,size);
}
ins.close();
buffer=outputStream.toByteArray();
A copy of your file should now exist in buffer, so you can use a FileOutputStream to save the buffer to a new file.
FileOutputStream fos = new FileOutputStream("mycopy.db");
fos.write(buffer);
fos.close();
InputStream.available has severe limitations and should never be used to determine the length of the content available for streaming.
http://developer.android.com/reference/java/io/FileInputStream.html#available():
"[...]Returns an estimated number of bytes that can be read or skipped without blocking for more input. [...]Note that this method provides such a weak guarantee that it is not very useful in practice."
You have 3 solutions:
Go through the content twice, first just to compute content length, second to actually read the data
Since Android resources are prepared by you, the developer, hardcode its expected length
Put the file in the /asset directory and read it through AssetManager which gives you access to AssetFileDescriptor and its content length methods. This may however give you the UNKNOWN value for length, which isn't that useful.