I'm a bit confused. I got this block of code :
public void serializeStock(){
FTPClient client = new FTPClient();
try{
client.connect("ftp.**.***");
client.login("***", "*****");
FileInputStream fin = new FileInputStream(someVariableContainingObject); // <-- The object ( StockVault stocks = new StockVault();
ObjectInputStream oos = new ObjectInputStream(fin);
client.storeFile("theObject", oos);
System.out.println("Wrote Stocks data to file");
client.logout();
client.disconnect();
}catch(Exception ex){
ex.printStackTrace();
}
}
I open a connection to my remote FTP server, I now want to write a object named "stocks" to the server. I know I can save the object file first, and then upload it. But is it possible to store the object in a "file" variable or something, and feed it directly to the FileInputStream? This way I wont have to save the object to an actual system file, and then upload it. But make some kind of variable to hold the file, and then upload the "file-variable" to the ftp-server.
It is possible to stream directly to the FTP server, but FileInputStream is not the right class to do so -- it always reads from a local file.
The simplest way to do this in your case may be to use
client.storeFileStream(remoteName)
This method returns an output stream you can write to (instead of sucking up all the data from a given input stream), which seems to be a more natural fit for your case.
Example:
OutputStream os = client.storeFileStream("theObject");
ObjectOutputStream oos = new ObjectOutputStream(os);
// write your object to oos here,
// then close everything.
An alternative that uses the same client method as in your example but no file would be to first write the object to a ByteArrayOutputStream, then create a ByteArrayInputStream from getBytes(), and hand that over to the ftp client.
BTW: The Object stream in your code can be omitted -- you can use the file stream directly:
FileInputStream fin = new FileInputStream(someVariableContainingObject);
client.storeFile("theObject", fin);
// ...
Related
ObjectOutputStream oos = new ObjectOutputStream(c.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(c.getInputStream());
File file = new File("lol.txt");
if(!file.exists()){
file.createNewFile();
}
byte[] textBytes;
while((textBytes = (byte[])ois.readObject()) != null){
Files.write(file.toPath(), textBytes);
}
//do stuff...
byte[] textBytes;
while((textBytes = (byte[])ois.readObject()) != null){
Files.write(file.toPath(), textBytes);
}
How can I read a file on a server multiple times? Should this code work? Will it not get stuck in the first loop check?
The server is writing it to the client like this.
byte[] fileBytes = Files.readAllBytes(fp.toPath());
oos.writeObject(fileBytes);
oos.flush();
A repeatable read on a Socket's InputStream is not possible, because it is a buffer based, blocking implementation, using a descriptor to indicate where the current position in the buffer is.
When you read from the InputStream the descriptor moves the amount of bytes you have read. It's not possible to rewind the descriptor to the previous position, because the read bytes maybe already overwritten by new received bytes.
You server client communication must be in this way
(I use the following abbreviations: S -> a Server, C -> a Client):
C: Request file from S
S: Send file to C
C: Request file from S
S: Send file to C
(and so on)
I am making a Smart ATM project in which a user can create a account as well and thus I will need to store the data to file. I have tried using the Serialization method and writing the objects of User class to the serialized file. But the problem is that whenever I restart the program the database gets re written (Over Written).
I there a way out if this without using any other methods like SQL. I mean I would like to stick with Serialization for now because I am not yet familiar to other methods.
public void addUserToDatabase() {
String fileName = System.getProperty("user.home")+"/accounts.txt";
try {
FileOutputStream fos = new FileOutputStream(fileName);
ObjectOutputStream oos = new ObjectOutputStream(fos);
for(int i =0; i<numberOfUser; i++) {
oos.writeObject(u[i]);
}
fos.close();
oos.close();
}
catch(Exception e) {
System.out.println("UNABLE TO ADD USER TO DATABASE!");
}
}
public void fileInputStreamMethod() throws Exception
{
String fileName = System.getProperty("user.home")+"/aas.txt";
FileOutputStream fos = new FileOutputStream(fileName);
DataOutputStream dos = new DataOutputStream(fos);
int i=12;
dos.writeInt(i);
dos.close();
FileInputStream fis = new FileInputStream(fileName);
DataInputStream dis = new DataInputStream(fis);
int factorial=dis.readInt();
System.out.println("The No. YOu entered is "+factorial);
dis.close();
}
Your reading to database and writing to database needs to be symmetric -- if you write objects out using an ObjectOutputStream, then to read back, you must read objects back in using an ObjectInputStream. You don't do that as you're writing out with the ObjectOutputStream but appear to be reading back in using a DataInputStream. This won't throw an error since everything, even serialized objects, are "data", but your code won't be able to retrieve usable information. If you make your input and outputs symmetric your problem (at least the short term problem) should be solved.
I want to use a single ObjectInputStream to read from a byte array, but I keep getting a StreamCorruptedException every time I start the program.
public void run(){
byte[] receiveBuffer = new byte[65535];
bIn = new ByteArrayInputStream(receiveBuffer);
try {
in = new ObjectInputStream(bIn);
} catch (IOException e1) {
e1.printStackTrace();
}
while(true){
try {
packetIn = new DatagramPacket(receiveBuffer, receiveBuffer.length);
sock.receive(packetIn);
Object o = in.readObject();
//do things with o
}
}
}
I'm just trying to initialize the ObjectInputStream to read from the byte array eventually, but it's throwing that exception even if I remove the while loop.
What am I doing wrong here?
If you take a look at the javadocs for the ObjectInputStream(InputStream) constructor, you'll see:
Creates an ObjectInputStream that reads from the specified InputStream. A serialization stream header is read from the stream and verified. This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.
...
throws
StreamCorruptedException - if the stream header is incorrect
(emphasis added)
In other words, the constructor doesn't just record the InputStream reference you give it, it also reads from that object. In this case, that's a stream of all 0s.
You should defer creating the ObjectInputStream until you have the serialized data (or at least enough of it to read the header).
(In the interest of "teach a person to fish," I'll also note that any time a method/constructor throws an exception you don't expect, that method's javadocs are a good place to start for understanding its behavior. The javadocs for the JDK classes are usually pretty good.)
Ok, this is how object streams work and the solution that works everywhere.
Object stream data is preceded by a 4 byte 'magical' sequence AC ED 00 05. An ObjectInputStream will peek for this data at construction time rather than before the first read. And that's logical: one wants to be sure it is a proper stream before being too far in an application. The sequence is buffered by the ObjectOutputStream at construction time so that it is pushed on the stream at the first write. This method often leads to complexities in buffered situations or transferring via pipes or sockets. Fortunately, there is a just as simple as an effective solution to all these problems:
Flush the ObjectOutputStream immediately after construction!
ObjectOutputStream myStream = new ObjectOutputStream ( anotherStream );
myStream.flush();
In your case, you will have to use a ObjectOutputStream if you want to read from an ObjectInputStream
The stream protocol includes a stream header, which ObjectInputStream reads in the constructor. You have to defer creating the stream until you have received something:
sock.receive(packetIn);
try {
in = new ObjectInputStream(bIn);
Object o = in.readObject();
} catch (IOException e1) {
e1.printStackTrace();
}
Hello Stack Overflow community,
I am doing multistep processing on some data I am receiving with a java Servlet. The current process I have is that I input the files to a server using Apache File Upload and convert them to a File. Then once input1 is populated with data, I run through a flow similar to this (where the process functions are xsl transforms):
File input1 = new File(FILE_NAME); // <---this is populated with data
File output1 = new File(TEMP_FILE); // <---this is the temporary file
InputStream read = new FileInputStream(input1);
OuputStream out = new FileOutputStream(output1);
process1ThatReadsProcessesOutputs( read, out);
out.close();
read.close();
//this is basically a repeat of the above process!
File output2 = new File(RESULT_FILE); // <--- This is the result file
InputStream read1 = new FileInputStream(output1);
OutputStream out1 = new FileOutputStream(output2);
Process2ThatReadsProcessesOutputs( read1, out1);
read1.close();
out1.close();
…
So my question is if there is a better way to do this so I do not have to create those temporary Files and recreate streams to those Files? (I am assuming I am incurring a decent performace penatly)
I saw this Most Efficient Way to create InputStream from OutputStream but I am not sure if this is the best route to go...
Just replace FileOutputStream to ByteArrayInputStream vice/versa.
Example:
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
I don't know why are you converting the FileItem retrieved with Apache Commons if you don't really needed. You can use the same InputStream that each FileItem has to using and read the content of the uploaded file:
// create/retrieve a new file upload handler
ServletFileUpload upload = ...;
// parse the request
List<FileItem> items = (List<FileItem>) upload.parseRequest(request);
/* get the FileItem from the List. Yes, it's not a best practice because you must verify
how many you receive, and check everything is ok, etc.
Let's suppose you've done it */
//...
FileItem item = items.get(0);
// get the InputStrem to read the contents of the file
InputStream is = item.getInputStream();
So finally, you can use the InputStream object to read the uploaded stream sent by the client avoiding unnecessary instantiations.
And yes, it's really recommended to use Buffered clases like BufferedInputStream and BufferedOutputStream.
The other idea could be to avoid FileOutputStream (the middle one) and replace it with ByteArrayOutputStream if you don't need to be written in disk (always is slower than working in memory).
Java 9 brings a new answer to the question:
// All bytes from an InputStream at once
byte[] result = new ByteArrayInputStream(buf)
.readAllBytes();
// Directly redirect an InputStream to an OutputStream
new ByteArrayInputStream(buf)
.transferTo(System.out);
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.