In a exercise, I have to create an iterator for an InputStream.
The goal is that the user can do :
for(byte b : new InputStreamToIterable(myInputStream)){
//do stuff with byte
}
I finished to create it and it works well, but the Iterator method is not very elegant (lot of try/catch).
#Override
public Iterator<Byte> iterator() {
// TODO Auto-generated method stub
try {
return new Iterator<Byte>() {
int data = is.read();
#Override
public boolean hasNext() {
// TODO Auto-generated method stub
return data != -1;
}
#Override
public Byte next() {
// TODO Auto-generated method stub
if(!hasNext()){
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int a = data;
try {
data = is.read();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return (byte)a;
}
#Override
public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
};
} catch (IOException e) {
// TODO Auto-generated catch block
throw new UnsupportedOperationException();
}
}
Is there a way to make it nicer ?
You could ...
in method next(): unify the two try-catch blocks into a single one
do the assignment int data = is.read(); in a constructor, using a try-catch-block, and so get rid of the outermost try-catch-block.
When catching the IOExceptions, instead of simply calling e.printStackTrace(); and continuing program execution, a better practice would be to enable users of this class to programmatically treat the error by re-throwing some RuntimeException (which needn't be declared and so doesn't violate the Iterable interface):
catch(IOException e) {
throw new RuntimeException(e);
}
You could clean it up somewhat by combining the two try-catch blocks in next():
boolean isClosed = false;
#Override
public Byte next() {
if(isClosed) throw new NoSuchElementException();
int a = data;
try {
if(!hasNext()) {
is.close();
isClosed = true;
} else
data = is.read();
} catch(IOException e) { throw new RuntimeException(e); }
return (byte)a;
}
EDIT
Changed the code according to discussion below
Related
I am writing a program for keeping track of library books. There is an object book that includes a title, sku number, price and quantity. All the books are stored in an Array List. I'm trying to serialize the books and add new books but every time a book is added the last is overwritten.
here is the code below to load objects from save
public static void readSave() {
File stockFile = new File("inventory.txt");
try {
if(!stockFile.createNewFile() && stockFile.length() != 0) {
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(stockFile));
int size = objIn.readInt();
for(int i = 0; i < size; i++) {
Book t = (Book) objIn.readObject();
bookList.add(t);
}
objIn.close();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
here is my save method and it is set to save every time the program executes.
public static void save() {
File inventoryFile = new File("inventory.txt");
ObjectOutputStream objOut;
try {
objOut = new ObjectOutputStream(new FileOutputStream(inventoryFile));
objOut.writeInt(bookList.size());
Iterator<Book> i = bookList.iterator();
while(i.hasNext()){
objOut.writeObject(i.next());
}
objOut.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
below is my main method which calls these functions
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
readSave();
CampusBookWindow window = new CampusBookWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
save();
}
});
}
My problem was when I hit the add book button I would not create a new book object for that item, but instead I was reassigning that last book object so the object last book object was erased from the bookList array list
I wrote a SocketClient for connect to the socket, and add some callback in it.
public class SocketClientV2 {
public static void main(String[] args) {
SocketClientV2.Listener listener = new SocketClientV2.Listener() {
#Override
public void recv(byte[] result) {
// TODO Auto-generated method stub
System.out.println("====recv something");
}
#Override
public void connected() {
// TODO Auto-generated method stub
System.out.println("=====connected!");
}
#Override
public void disconnect() {
// TODO Auto-generated method stub
System.out.println("=====disconnect!");
}
};
SocketClientV2 client = new SocketClientV2("172.16.16.102", 4444,
10000, listener);
byte[] test = new byte[10];
test[0] = (byte) 0x1c;
test[1] = (byte) 0xff;
test[2] = (byte) 0x08;
client.send(test);
}
public interface Listener {
public void recv(byte[] result);
public void connected();
public void disconnect();
}
Socket client = null;
boolean isConnect = false;
OutputStream outputStream = null;
InputStream inputStream = null;
public SocketClientV2() {
}
Listener cb = null;
public SocketClientV2(String site, int port, int timeout, Listener cb) {
this.cb = cb;
try {
client = new Socket(site, port);
client.setSoTimeout(timeout);
System.out.println("Client is created! site:" + site + " port:"
+ port);
if (isConnected()) {
isConnect = true;
if (cb != null) {
cb.connected();
}
checkConnect();
listenRecv();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public Socket getClient() {
return this.client;
}
public void closeSocket() {
try {
isConnect = false;
inputStream.close();
outputStream.close();
client.close();
client = null;
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean isConnected() {
try {
client.sendUrgentData(0xff);
isConnect = true;
} catch (Exception e) {
System.out.println("return false....2");
isConnect = false;
e.printStackTrace();
return false;
}
return true;
}
private void checkConnect() {
new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("check connect....1");
try {
while (isConnected()) {
Thread.sleep(500);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("finally....3");
if (cb != null) {
cb.disconnect();
}
closeSocket();
}
}
}.start();
}
private void listenRecv() {
new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("listening Recv....");
try {
inputStream = client.getInputStream();
while (isConnect) {
byte[] result = readStream(inputStream);
if (cb != null) {
cb.recv(result);
}
Thread.sleep(500);
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
public void send(final byte[] byteSend) {
new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
// System.out.println("sendMsg coming....");
if (isConnect) {
try {
outputStream = client.getOutputStream();
outputStream.write(byteSend);
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
public byte[] readStream(InputStream inStream) throws Exception {
int count = 0;
while (count == 0) {
// System.out.println(0);
count = inStream.available();
// if(count!=0)
// System.out.println(count);
}
byte[] b = new byte[count];
inStream.read(b);
return b;
}
}
there is one thread checkConnect to check the connect status for the socket..
but it will disconnect after running few mins,
Client is created! site:172.16.16.102 port:4444
=====connected!
check connect....1
listening Recv....
====recv something
====recv something
====recv something
====recv something
====recv something
====recv something
====recv something
return false....2
java.io.IOException: Broken pipe
at java.net.PlainSocketImpl.socketSendUrgentData(Native Method)
at java.net.PlainSocketImpl.sendUrgentData(PlainSocketImpl.java:622)
at java.net.Socket.sendUrgentData(Socket.java:954)
at com.udpdemo.multicast.SocketClientV2.isConnected(SocketClientV2.java:100)
at com.udpdemo.multicast.SocketClientV2.access$0(SocketClientV2.java:98)
finally....3
=====disconnect!
at com.udpdemo.multicast.SocketClientV2$2.run(SocketClientV2.java:121)
java.io.IOException: Stream closed.
at java.net.PlainSocketImpl.available(PlainSocketImpl.java:483)
at java.net.SocketInputStream.available(SocketInputStream.java:217)
at com.udpdemo.multicast.SocketClientV2.readStream(SocketClientV2.java:205)
at com.udpdemo.multicast.SocketClientV2$3.run(SocketClientV2.java:154)
so what's problem with my sendUrgentData???
'Broken pipe' always means that you wrote to a connection which had already been closed by the peer. It's an application protocol error.
But unless the peer of this client isn't written in Java there is no point in using urgent data in the first place. Java can only receive urgent data 'in-line', i.e. after all the other pending data that had already been sent. And that only happens if the peer calls setOOBLine(true), otherwise
by default, this option is disabled and TCP urgent data received on a socket is silently discarded.
It's possible you're doing this to detect a broken connection. In this case, your dream came true, it worked, and all you have to do is adjust your catch and your code accordingly. But this is not in general a reliable technique.
Other notes:
isConnected() can never be false at the point you test it after creating the Socket, and it never magically becomes false afterwards. You need to revisit all the code that calls this method. Most of it doesn't make sense, or relies on false assumptions.
Your readStream() method spin-loops while available() returns zero. There is absolutely no point in this. You're just smoking the CPU. It's also completely at odds with your attempted use of a read timeout, which simply cannot possibly work while this loop is there. The following read() call will block until at least one byte of data arrives, or end of stream or an exception occurs. Your present code will never detect end of stream. You need to completely redesign this part of the code as well. It's poor practice to return a byte array for example.
That same piece of code completely ignores the count returned by read(). Never do that.
could you please have a look at my code :
private void initSocket() {
try {
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.bind(null);
socketChannel.connect(new InetSocketAddress(host,port));
while(! socketChannel.finishConnect() ){
Thread.sleep(5);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void initOutput() {
outBuffer = ByteBuffer.allocateDirect(512); //Allocate direct for better performance (no java-heap alloc)
outBuffer.clear();
}
private void initInput() {
inBuffer = ByteBuffer.allocateDirect(1024); //Allocate direct for better performance (no java-heap alloc)
inBuffer.clear();
}
public String in () {
try {
while (socketChannel.re)
socketChannel.read(inBuffer);
inBuffer.mark();
final String ret = Charset.forName("UTF-8").newDecoder().decode(inBuffer).toString();
bulletin.PIPE_IN.Info.push(" <<< ", new String[]{"TsPipe2","in"}, new Object[]{ret, inBuffer});
return ret;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void out (String out) {
outBuffer.clear();
outBuffer.put(out.getBytes());
//Write all in one go
bulletin.PIPE_OUT.Info.push(" >>> ", new String[]{"TsPipe2","out"}, new Object[]{outBuffer, out});
int toWrite = outBuffer.remaining();
for (int i = 0; i < toWrite; ++i) {
try {
i += socketChannel.write(outBuffer);
Thread.sleep(Period.NIO_CHANNEL_WRITE_SLEEP.getValue());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
And tell me what am I doing wrong ?
As the topic states I am always getting the same data from the in-method and am not sure wether my out-method works or not
I travelled throught several tutorials now and it might be I mixed something up.
I also found promising stuff on stackoverflow - but nothing ever worked.
As a little background info - I am writing a Teamspeak bot communicatin via Sockets with a TS-Server and have gone pretty far. From the moment I first heard about nio I wanted to migrate to it.
Are their other frameworks to consider ? heard Google Grizzly is pretty neat, but not sure if it's useful for my case ?
I believe you're missing some braces at this while (socketChannel.re) loop.
I'm trying to make a new thread for parsing xml from an rss feed. When I click run it says there are errors please correct them etc. I have 2 classes in my project. The other class has no errors and this class below has only warnings that a lot of the things in the try/catch statements may be uninitialized. I understand that and figured I should still be able to run the program anyways, I expect them to be initialized and if they're not that's fine I want to know about it. Is this really what's going on or am I missing something? I thought it would compile if something may be uninitialized but its not certainly uninitialized.
public class RssParse extends Thread {
Thread th=new Thread() {
public void run(){
System.out.println("1");
URL iotd;
try {
iotd = new URL("http://www.nasa.gov/rss/image_of_the_day.rss");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("2");
BufferedReader in;
try {
in = new BufferedReader(new InputStreamReader(iotd.openStream()));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("3");
XmlPullParserFactory factory;
try {
factory = XmlPullParserFactory.newInstance();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
factory.setNamespaceAware(true);
System.out.println("4");
XmlPullParser xpp;
try {
xpp = factory.newPullParser();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("5");
try {
xpp.setInput(in);
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("6");
int eventType;
try {
eventType = xpp.getEventType();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(eventType+"!!!!!!!!!!!!!!!!");
while(eventType!=XmlPullParser.END_DOCUMENT){
if(eventType==XmlPullParser.START_DOCUMENT){
System.out.println("start");
}
}
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//method
};//thread
}//class
Look at this try/catch block for example :
URL iotd;
try {
iotd = new URL("http://www.nasa.gov/rss/image_of_the_day.rss");
} catch (MalformedURLException e) {
e.printStackTrace();
}
If iotd = new URL("...") fails, iotd will remain uninitialized.
There are two ways to deal with this :
Assign a default value to iotd, like : URL iotd = null; However, it's bad here because if you use iotd later its value may be null and can throw a NullPointerException.
Stop the execution of your function if something failed instead of just printing the stack trace. For example you can add a return statement in the catch block :
URL iotd;
try {
iotd = new URL("http://www.nasa.gov/rss/image_of_the_day.rss");
} catch (MalformedURLException e) {
e.printStackTrace();
return;
}
All the warnings you are getting are because all your catch blocks are not dealing with the exception at all (just printing the stacktrace to standard out).
Let's see it through an example:
URL iotd;
try {
iotd = new URL("http://www.nasa.gov/rss/image_of_the_day.rss");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
at that snipped you are declaring a iotd variable as a URL but without initializing it (not assigning any value), you do it inside the try block - which isn't wrong by the way. However if for any reason the statement inside the try block throws an exception program flow will go to the catch block leaving the iotd variable with its initial value (unassigned).
So, in that case, execution of the program will continue and when reaching this statement:
in = new BufferedReader(new InputStreamReader(iotd.openStream()));
it will find no value assigned to the iotd variable.
To remove the warning regarding the uninitialized value you can either assign a null value to the variable when declaring it or rethrow another exception inside the catch block, stopping the program flow.
In the other hand, the snippet you posted here is not just one class, it's actually two as you are extending the Thread class and then creating an anonymous one inside its body. Using threads is easier than that in Java, just implement the Runnable interface and then instantiate a new thread from that interface:
public class MyRunnable implements Runnable {
public void run() {
// do stuff
}
}
and then:
new Thread(new MyRunnable()).start();
cheers
you need to initialize the variables above the try catch block, or give them a value in catch or finally block
find updated code here
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
public class RssParse extends Thread {
Thread th=new Thread() {
public void run(){
System.out.println("1");
URL iotd=null;
try {
iotd = new URL("http://www.nasa.gov/rss/image_of_the_day.rss");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("2");
BufferedReader in=null;
try {
in = new BufferedReader(new InputStreamReader(iotd.openStream()));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("3");
XmlPullParserFactory factory=null;
try {
factory = XmlPullParserFactory.newInstance();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
factory.setNamespaceAware(true);
System.out.println("4");
XmlPullParser xpp=null;
try {
xpp = factory.newPullParser();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("5");
try {
xpp.setInput(in);
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("6");
int eventType=-1; // set to a default value of your choice
try {
eventType = xpp.getEventType();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(eventType+"!!!!!!!!!!!!!!!!");
while(eventType!=XmlPullParser.END_DOCUMENT){
if(eventType==XmlPullParser.START_DOCUMENT){
System.out.println("start");
}
}
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//method
};//thread
}//class
I've been trying to call the following:
public static void startfile() {
Log.i("File Works", "working2 ");
try {
FileOutputStream fos = openFileOutput("sdcard/sdtext.txt", MODE_WORLD_WRITEABLE);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I get an error that tells me that "Cannot make a static reference to the non-static method openFileOutput(String, int) from the type ContextWrapper"
So I searched for that error and found this site.
I implemented this:
public static void startfile(Trackfile O) {
Log.i("File Works", "working2 ");
O.nonstatstartfile();
}
public void nonstatstartfile(){
Log.i("File Works", "nonStat");
try {
FileOutputStream fos = openFileOutput("sdcard/sdtext.txt", MODE_WORLD_WRITEABLE);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
When I call startfile from another class getting a Null pointer error. What argument do I need to send to avoid the null pointer error?
You can pass context from activity like below
public static void startfile(Context c) {
Log.i("File Works", "working2 ");
try {
FileOutputStream fos = c.openFileOutput("sdcard/sdtext.txt", MODE_WORLD_WRITEABLE);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
public void startfile() {
Log.i("File Works", "working2 ");
try {
FileOutputStream fos = openFileOutput("sdcard/sdtext.txt", MODE_WORLD_WRITEABLE);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Add this method to your class, and use it without problems.
If you need it in main class, use it over object.