This question already has an answer here:
Why is ObjectInputStream readObject() throwing EOF exception
(1 answer)
Closed 7 years ago.
So, I write an object to a client like so:
ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
out.writeObject(args);
out.close();
And receive the object on the client side like so:
ObjectInputStream in = new ObjectInputStream(connection.getInputStream());
Object objIn;
while(true) {
if((objIn = in.readObject()) != null) {
//work with obj
}
}
I never create an output stream on the client side or an input stream on the server side.
Also, the object I send is serializable.
Thanks for you help!
EDIT: The "duplicate" of this question doesn't help me answer my problem, so this one is not a duplicate.
while(true) {
if((objIn = in.readObject()) != null) {
//work with obj
}
}
Q. Why are you testing for null? Are you planning on sending a null? Because that's the only time you'll ever get one.
A. Because you think readObject() returns null at end of stream. Although you've left out the break that would escape the infinite loop.
It doesn't. It throws EOFException. So your loop should look like this:
try
{
while(true) {
objIn = in.readObject();
//work with obj
}
}
catch (EOFException exc)
{
// end of stream
}
finally
{
in.close();
}
Assuming you received the exception while reading the input stream from connection Object .
If you already invoked the connection.getInputStream() prior to the above cited code for input stream you will receive a EOF exception . Because the input Stream in the connection object is already consumed .
related topic
One solution to such problem is to write the content of the input stream in a Random access file as they enables you to traverse through the file .
public static RandomAccessFile toRandomAccessFile(InputStream is, File tempFile) throws IOException
{
RandomAccessFile raf = new RandomAccessFile(tempFile, "rwd");
byte[] buffer = new byte[2048];
int tmp = 0;
while ((tmp = is.read(buffer)) != -1)
{
raf.write(buffer, 0, tmp);
}
raf.seek(0);
return raf;
}
Later you can always read from the file as follows .
public static InputStream toInputStream(RandomAccessFile file) throws IOException
{
file.seek(0); /// read from the start of the file
InputStream inputStream = Channels.newInputStream(file.getChannel());
return inputStream;
}
Related
I'am trying to write the inputstream image to OutputStream to display the image in the browser this is the code:
try
{
InputStream input = Filer.readImage("images/test.jpg");
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1)
{
responseBody.write(buffer, 0, bytesRead);
}
}
catch(IOException e)
{
System.out.println(e);
}
the readImage:
public static InputStream readImage(String file) throws IOException {
try (InputStream input = new FileInputStream(file)) {
return input;
}
}
but I get an error while writing:
java.io.IOException: Stream Closed
any ideas?
The try-with-resources closes the stream when you exit the block
try (InputStream input = new FileInputStream(file)) {
ie. when your method returns.
Just remove it and take care of closing the stream at the end of your other method body.
As stated in the comments, here's a link to the official tutorial on try-with-resources.
Taken from oracle tutorial the resource is closed when the statement completes:
The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
Prior to Java SE 7, you can use a finally block to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. The following example uses a finally block instead of a try-with-resources statement:
I am developing a tool to get client information, send to a server, and receive the information again (a proxy). I'm also trying to dump the data being received from the server. I can read the Integer representation of the inputStream, but I am not able to read the String format. I've tried the below example, but it hangs and never connects to the server. Also, System.out.println(inputStream.nextLine()) displays only one line and hangs.
public void run() {
try {
int i;
while ((i = inputStream.read()) != -1){
System.out.println(IOUtils.toString(inputStream));
outputStream.write(i);
}
} catch (IOException e) {
System.out.println("Lost connection to the client.");
}
}
My guess at this is that you're reading from the input stream, and then using the IOUtils library to read from the stream too. My suspicion is that your application is reading the first byte from the input stream, then reading the remainder of the inputstream with the IOUtils library, and then printing out the initial byte that was read.
It doesn't make any sense to call IOUtils.toString(inputstream) from within a loop. That method call will put all the data from the inputstream into a string. Why have the loop at all in this case?
You might want to try not using the IOUtils library for this. Just read a byte of data, push it into a StringBuilder, and then print that byte. In this approach, the loop would be necessary, and you'll probably get what you're looking for.
Try something like this, but modify it as necessary to print the data at the same time to your output stream:
public static String inputStreamToString(final InputStream is, final int bufferSize)
{
final char[] buffer = new char[bufferSize];
final StringBuilder out = new StringBuilder();
try {
final Reader in = new InputStreamReader(is, "UTF-8");
try {
for (;;) {
int rsz = in.read(buffer, 0, buffer.length);
if (rsz < 0)
break;
out.append(buffer, 0, rsz);
}
}
finally {
in.close();
}
}
catch (UnsupportedEncodingException ex) {
/* ... */
}
catch (IOException ex) {
/* ... */
}
return out.toString();
}
The code you posted doesn't attempt to connect to the server, but if any of it executes you must already have connected.
If your program is hanging in this code, either the server hasn't sent any data yet, or the IOUtils.toString() method probably tries to read to EOS, so if the peer doesn't close the connection you will block here forever.
If your program hangs at a readLine() call it means the peer hasn't sent a line to read.
I currently have a working parser. It parses a file once(not what I want it to do) and then outputs parsed data into a file. I need it to keep parsing and appending to the same output file until the end of the input file. Looks something like this.
try {
// my code parsing the data and appending to eof of output. (works)
}
catch (EOFException eof){
}
Everything is done except the while loop. It only parses once when I need it to keep parsing. I'm looking for a while loop function to reach eof.
I'm also using a DataInputStream. Is there some sort of DataInputStream.hasNext function?
DataInputStream dis = new DataInputStream(new FileInputStream(inFile));
i.e. dis.read();
.
//Need a while !eof while loop
try {
// my code parsing the data and appending to eof of output. (works)
}
catch (EOFException eof){
}
Warning: This answer is incorrect. See the comments for explanation.
Instead of looping until an EOFException is thrown, you could take a much cleaner approach, and use available().
DataInputStream dis = new DataInputStream(new FileInputStream(inFile));
while (dis.available() > 0) {
// read and use data
}
Alternatively, if you choose to take the EOF approach, you would want to set a boolean upon the exception being caught, and use that boolean in your loop, but I do not recommend it:
DataInputStream dis = new DataInputStream(new FileInputStream(inFile));
boolean eof = false;
while (!eof) {
try {
// read and use data
} catch (EOFException e) {
eof = true;
}
}
DataInputStream has a lot of readXXX() methods that do throw EOFException but the method that you're using DataInputStream.read() does not throw EOFException.
To correctly identify the EOF while using read() implement your while loop as follows
int read = 0;
byte[] b = new byte[1024];
while ((read = dis.read(b)) != -1) { // returns numOfBytesRead or -1 at EOF
// parse, or write to output stream as
dos.write(b, 0, read); // (byte[], offset, numOfBytesToWrite)
}
If you are using FileInputStream, here's an EOF method for a class that has a FileInputStream member called fis.
public boolean isEOF()
{
try { return fis.getChannel().position() >= fis.getChannel().size()-1; }
catch (IOException e) { return true; }
}
I'm trying to read a webpage using following code :
URL url = new URL("somewebsitecomeshere");
URLConnection c = url.openConnection();
if(getHttpResponseCode(c) == 200)
{
if (isContentValid(c))//accept html/xml only!
{
InputStream is = c.getInputStream();
Reader r = new InputStreamReader(is);
System.out.println(r.toString());
//after commenting this everything works great!
setHTMLString(getStringFromReader(r));
System.out.println(getHTMLString());
ParserDelegator parser = new ParserDelegator();
parser.parse(r, new Parser(url), true);
r.close();
is.close();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
log("content is not valid!");
}
else
{
System.out.println("ERROR" + c.getContentType() + c.getURL());
}
//---------------------------------------------------
private String getStringFromReader(Reader reader) throws IOException {
char[] arr = new char[8*1024]; // 8K at a time
StringBuffer buf = new StringBuffer();
int numChars;
while ((numChars = reader.read(arr, 0, arr.length)) > 0) {
buf.append(arr, 0, numChars);
}
//Reset position to 0
reader.reset();
return buf.toString();
}
if try to read string using getStringFromReader() the rest of the code will be ignored due to changing position of Reader to EOF so I tried to reset the position to 0 but I got the following error :
java.io.IOException: reset() not supported
at java.io.Reader.reset(Unknown Source)
at sample.getStringFromReader(Spider.java:248)
at default(sample.java:286)
at default.main(sample.java:130)
How can I reset the Reader position to 0?
Short answer, your stream doesn't support reset or mark methods. Check the result of:
is.markSupported()
Long answer, an InputStream is a flow of bytes. Bytes can come from a file, a network resource, a string, etc. So basically, there are streams that don't support resetting the reader position to the start of the stream, while others do (random access file).
A stream from a web site will normally use underlying network connection to provide the data. It means that it's up to the underlying network protocol (TCP/IP for example) to support or not resetting the stream, and normally they don't.
In order to reset any stream you would have to know the entire flow, from start to end. Network communications send a bunch of packages (which may be in order or not) to transfer data. Packages may get lost or even be duplicated, so normally information is buffered and interpreted as it is received. It would be very expensive to reconstruct all messages at network level. So that is normally up to the receiver, if it wants to do that.
In your case If what you want is print the input stream I would recommend creating a custom InputStream, which receives the original InputStream and whenever it is read it prints the read value and returns it at the same time. For example:
class MyInputStream extends InputStream {
InputStream original = null;
public MyInputStream(InputStream original) {
this.original = original;
}
#Override
public int read() throws IOException {
int c = original.read();
System.out.printf("%c", c);
return c;
}
}
Then wrap your original InputStream with that:
.
.
.
InputStream myIs = new MyInputStream(is);
Reader r = new InputStreamReader(myIs);
.
.
.
Hope it helps.
InputStreamReader does not support reset(). Also, you did not call mark(0) before.
What you could do is wrap your reader in a BufferedReader of a sufficient size so that reset is supported. If you cannot do that, then you should try to open a new connection to your URL.
I have to read a series of object from a binary file.
I use:
ObjectOutputStream obj = new ObjectOutputStream(new FileInputStream(fame));
obj.readObject(p);
where p is a reference to an object I had created. How can I read the entire file until the end?
I can use:
while(p!=null){}
?
readObject() returns null if and only if you wrote a null. The correct technique is to catch EOFException and when you get it close the stream and exit the reading loop.
Let's assume you meant ObjectInputStream and p = obj.readObject().
I would do something like this: (this is wrong, see EDIT below)
FileInputStream fstream = new FileInputStream(fileName);
try {
ObjectInputStream ostream = new ObjectInputStream(fstream);
while (ostream.available() > 0) {
Object obj = ostream.readObject();
// do something with obj
}
} finally {
fstream.close();
}
EDIT
I take it back! EJP rightly points out that the use of available() is incorrect here. I think the fixed code might be:
FileInputStream fstream = new FileInputStream(fileName);
try {
ObjectInputStream ostream = new ObjectInputStream(fstream);
while (true) {
Object obj;
try {
obj = ostream.readObject();
} catch (EOFException e) {
break;
}
// do something with obj
}
} finally {
fstream.close();
}
Although the documentation for readObject() doesn't explicitly say that EOFException is thrown at the end of the stream, it seems to be implied and may be the only way to detect the end of the stream.
Another option if you control the code that wrote the stream would be to write an object count at the beginning, or a flag after each object indicating whether the previous object was the final one.
If you want to read object into your program, then you have to use ObjectInputStream, not ObjectOutputStream.
And if you will store a bunch of objects, then use an appropriate Collection for writing to file and reading from it. The API documentation for readObject does not state that it will return null or throw an exception if EOF is reached. So to be on the safe side, use Collections.
You may also want to read API docs on ObjectInputStream and ObjectOutputStream.
Boolean i = true;
while(i) {
try {
System.out.println(reader.readObject());
} catch(Exception e) {
i = false;
System.out.println("Dead end");
}
}
Guava's Files.toByteArray does what you want so if fame in your code is a File, then
import com.google.common.io.Files;
...
byte[] fameBytes = Files.toByteArray(fame);