Java InputStream != Readable - java

I am using java.util.Scanner for things such as nextInt(), and all was working fine as long as I was using a java.lang.Readable (one and only constructor argument). However, when I changed to using an InputStream instead, Scanner.nextInt() never returns. Do you know why?
My implementation of the InputStream looks like this:
private static class ConsoleInputStream extends InputStream {
...
private byte[] buffer;
private int bufferIndex;
public int read() throws IOException {
...
while (...) {
if (buffer != null && bufferIndex < buffer.length) {
return buffer[bufferIndex++]; // THE COMMENT!
}
...
}
...
}
}
When I print the data by THE COMMENT I (correctly) get stuff like '1','2','\n' for "12\n", etc. Is there some Scanner hookup, unbeknown to me, that cause this behavior?

From the javadocs for InputStream's read() method:
"Returns: the next byte of data, or -1 if the end of the stream is reached."
I would guess that you're never returning -1?

I think the problem is with your self-built InputStream. Why did you build your own, rather than simply simply using System.in ?
Update:
Wanted input from a JTextField.
OK, got it. It usually doesn't make sense to use I/O handling to read stuff that's already available, in character form, but I can see how that would make your life easier with Scanner.
Still, you could probably have saved yourself some coding and grief by using a "finished" InputStream. What comes to mind is
InputStream is = new ByteArrayInputStream(myTextField.getText().getBytes());
Java I/O is yucky. Be glad the bright people from Sun have encapsulated most of it away for you.

Related

Check if Java InputStream comes from Socket

I have a class that takes an InputStream as an argument to read data.
public Foo {
private DataInput in;
public Foo(InputStream ism) {
in = new DataInputStream(ism);
}
public byte readByte() throws IOException {
return in.readByte();
}
}
Sometimes this InputStream might come from a Socket, e.g.,
ism = new BufferedInputStream(sock.getInputStream());
foo = new Foo(ism);
My question is, is it possible to check from within Foo that the input stream comes from Socket, i.e., it's a network I/O rather than local I/O? Since the
socket.getInputStream
call returns the abstract class. I don't know which concrete input stream implementation to test for.
Edit: the motivation is that there is a piece of big Java software that has this structure. Foo is created in many places. Some place with file input stream while others with socket input stream. The software can perform poorly when the read is across the network. So I want to see if it's possible do tracing to differentiate the two scenarios for this software without changing much of its code. I'm using AspectJ to write the tracing in the hope to not create much mess to this existing software.
The problem is that an InputStream can be a FilterInputStream that is constructed around another InputStream and that socket just returns an InputStream.
One approach, very dirt & buggy: find the root InputStream, that is, recursively/loop if it is an instance of FilterInputStream, check its parent InputStream (protected field in). Then check the class of the root, the name probably contains "Socket" if it comes from a Socket.
AspectJ idea (I do not have that much experience with it): you should be able to add an aspect to the getInputStream method of Socket that stores the returned InputStream in a list (or similar) for later checking, or somehow marks that InputStream (adding a flag/method to it?).
You can create 2 superclasses of input stream before passing it into Foo class.
NetworkInputStream nis = new NetworkInputStream(sock.getInputStream());
Foo networkFoo = new Foo(nis);
FileInputStream fis = new FileInputStream(file.getInputStream());
Foo fileFoo = new Foo(fis);
public class NetworkInputStream extends BufferedInputStream {}
public class FileInputStream extends BufferedInputStream {}
Then, on Foo class:
public Foo(InputStream ism) {
if (ism instanceof NetworkInputStream) {
//Do whatever if it's from network stream
}
if (ism instanceof FileInputStream) {
//Do whateverelse
}
in = new DataInputStream(ism);
}

IllegalStateException - no last call on a mock available

I'm trying to use EasyMock to test that a method runs a specific number of times but I keep getting an IllegalStateException error and I don't understand why. I'm new to EasyMock and JUnit and not very familiar with how to use them so I'm not sure what I'm doing wrong.
My code is:
FileOutputStream mockWriter;
Numbers mockByte;
#Test
public void testNumbers() throws IOException{
mockWriter = createMock(FileOutputStream.class);
mockByte = new Numbers(mockWriter);
mockByte.initByte();
expect(mockByte.generate()).times(10000);
replay(mockWriter);
}
And these are the methods initByte and generate from my Numbers class:
public void initByte() throws IOException{
File outFile = new File("NumbersOutput.txt");
FileOutputStream f = new FileOutputStream(outFile);
for(int i = 0; i < 10000; i++){
int b = generate();
f.write(b);
}
f.flush();
f.close();
}
public int generate(){
return rand.nextInt(100001);
}
The error you're getting is because nothing's calling anything on your mock.
Contrary to your naming, mockByte doesn't refer to a mock at all, so using it in an expect call like this is not going to help you. You should be expecting calls on mockWriter if anything.
However, it's not clear why you're using a mock for a stream at all, nor what the OutputStream in the Numbers constructor is used for. Your initByte() method doesn't use any state within the object other than rand. Even when that's fixed, it would probably be simplest just to use a ByteArrayOutputStream... make your API talk in terms of OutputStream instead of FileOutputStream, and it'll be much easier to test.
I suspect you should:
Remove the construction of a new FileOutputStream from the initByte method, instead writing to the stream you accept in the Numbers constructor
If your constructor parameter type is FileOutputStream, change it to OutputStream to make it cleaner and easier to test
Create a ByteArrayOutputStream in your test - you don't need mocking at all. You can then get all the bytes that have been written, and check them for whatever you want.
Think carefully about what you expect f.write(b) to do. It's only going to write a single byte, so the top 24 bits of your random number are going to be ignored. At that point, why are you choosing a number in the range [0, 10000] anyway?

Effect on the original InputStream after wrapping with BufferedInputStream

Suppose I have a method that take in an InputStream.
This method need to wrap this InputStream with a BufferedInputStream to use its mark and reset functionality. However, the passed in InputStream might still be used by the caller of the method.
public static void foo(InputStream is) throws Exception {
BufferedInputStream bis = new BufferedInputStream(is);
int b = bis.read();
}
public static void main(String[] args) {
try {
InputStream is = new FileInputStream(someFile);
foo(is);
int b = is.read(); // return -1
}catch (Exception e) {
e.printStackTrace();
}
}
My questions is: what exactly happen to the original InputStream when the BufferedInputStream is read (or initialized)?
My assumption is that the original InputStream will also move forward if the BufferedInputStream is read. However, after debugging my code, I have found that the InputStream will return -1 instead when read.
If the original InputStream is not readable after such process, how should I go about achieving my purpose:
InputStream is;
foo(is); // Method only take in generic InputStream object
// Processing of the passed in InputStream object require mark and reset functionality
int b = is.read(); // Return the next byte after the last byte that is read by foo()
EDIT:
I suppose what I'm asking for is quite generic and therefore requires a lot of work. As for what I'm working on, I actually don't need the full mark & reset capability so I have found a small work around. However, I will leave the 2nd part of the question here, so feel free to attempt this problem :).
The default bufferSize of a BufferedInputStream is 8192, so when you're reading from BufferedInputStream, it tries to fill it's buffer. So, if you have to read from your InputStream less bytes, than the bufferSize, then the full content of your InputStream is read to the buffer, therefore you're getting -1 after reading from BufferedInputStream
Have a look at the BufferedInputStream source code: http://www.docjar.com/html/api/java/io/BufferedInputStream.java.html
http://docs.oracle.com/javase/7/docs/api/java/io/BufferedInputStream.html#BufferedInputStream%28java.io.InputStream%29
Looks like the BufferedInputStream uses the InputStream for the actions performed with the data stream. The Buffered class simply implements a buffer array for internal use.
Not sure what you could use instead, apart from perhaps copying the InputStream so that you have a second object to call.
BufferedInputStream will pre-load data from the underlying InputStream in batches, which will trigger respective move of the underlying InputStream position. If the buffer size is enough to consume all data from the underlying stream in one go you may well observe the behavior you describe.
Two things:
Any API that accepts a stream as input parameter is probably going to use that stream, so it is unreasonable for the caller to expect the stream to remain in any kind of usable state. Perhaps it would have been better for the java stream classes to enforce single ownership somehow to make that clearer.
As a special case, BufferedInputStream is going to use the underlying stream that it "wraps" because it achieves (a limited form of) mark and reset by buffering block reads, as others have pointed out.
private static class MybufferedInputStream extends BufferedInputStream {
public MybufferedInputStream(InputStream in) {
super(in);
}
public int getBufferSize(){
int i=0;
for (Byte byte1 : super.buf) {
if (byte1!=0) {
i++;
}
}
return i;
}
}
then you can call the getBufferSize() after read() to see the difference between a small file and a larger file.

replacing text in a printstream

Is it possible to have a regexp replace in a printstream?
I have a piece of code that logs all text that is shown in my console windows but it also logs ANSI escape codes.
I have found this regexp "s:\x1B\[[0-9;]*[mK]::g" to remove them but that only works with strings.
Is there a way to apply a regex replace to a constant stream of strings and filter out the ANSI escape codes?
If possible, dumb it down as much as possible, I am still a newbie when it comes to programming, I am just building upon a already program.
EDIT:
I have this code which I found somewhere else on stack overflow, this allows me to stream to a logfile and to the console at the same time.
This is what I use and then I set the out to tee after this.
Logging tee = new Logging(file, System.out);
.
package com.md_5.mc.chat;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
public class Logging extends PrintStream
{
private final PrintStream second;
public Logging(OutputStream main, PrintStream second)
{
super(main);
this.second = second;
}
public void close()
{
super.close();
}
public void flush()
{
super.flush();
this.second.flush();
}
public void write(byte[] buf, int off, int len)
{
super.write(buf, off, len);
this.second.write(buf, off, len);
}
public void write(int b)
{
super.write(b);
this.second.write(b);
}
public void write(byte[] b) throws IOException
{
super.write(b);
this.second.write(b);
}
}
Create create a subclass of FilterOutputStream, say RegexOutputStream. This class should buffer all data written to it (from the different write(...) methods). In the flush() method, it should apply the regex and then write the result to the underlying OutputStream.
Next, instantiate the PrintWriter to write to the RegexOutputStream. This way you don't need to alter the behaviour of the PrintWriter class. In case you don't want the filtering anymore, you can just take the RegexOutStream out of the chain, and everything will work again.
Note that, depending on how you use the PrintWriter, this might cause the RegexOutputStreams buffer to get quite big. If you create the PrintWriter to autoflush, it will flush after every line and after every byte array. See its JavaDoc for details.
You could subclass the print stream in question and perform your regexp replacing prior to calling the appropriate super method? E.g.
public void ExampleStream extends PrintStream {
#Override
public void print(String s) {
super(s.replaceAll(ANSI_PATTERN,""));
}
}
I think that the code in Logging class is not a good approach (at least as it is):
If you have access to the PrintStream source code you might find that the methods currently redefined might not being used at all: the PrintStream#print(...) methods delegate on textOut#write(...) (not on the redefined OutputStream#write(...) ).
Therefore, you should redefine the print(String) and print(char[]) methods in order to effectively filter the output.
There are a few examples of redefined methods in the answers (including further down on this one).
Alternatively, if you just want a PrintStream that filters out the ANSI codes (as I originally understood), then it would be more convenient to implement it on a FilterOutputStream (as mthmulders suggests, as you will have to redefine fewer stuff and will be easier to re-use):
Make a copy of BufferedOutputStream class. Name it however you prefer. (E.g. TrimAnsiBufferedStream)
Then redefine de flushBuffer() method:
private void flushBuffer() throws IOException {
if (count > 0) {
String s = new String(buf, 0, count); // Uses system encoding.
s.replaceAll(ANSI_PATTERN, "");
out.write(s.getBytes());
count = 0;
}
}
When you need to instantiate a PrintStream that replaces ANSI, invoke new PrintStream(new TrimAnsiBufferedStream(nestedStream)).
This is probably not bullet-proof (e.g. whatever may happen with encoding configuration, or if buffer size is not big enough, or flushing options in printstream), but I won't overcomplicate it.
By the way. Welcome kukelekuuk00. Just be sure to read the FAQ and feedback on the answers (we care about you, please reciprocate).

Encoding & decoding serialized XML in the class which the methods are in

I can't think of a way of describing it, basically I'm wondering if it is possible to write a method makes the current object become the decoded serialized XML.
I know that the saveTillXML works, as it generates an XML file which matches the state of the current Till object [but really I don't know that it does work, as the decoding fails]. However, I get these exceptions when I call the loadTillXML() method:
java.lang.reflect.InvocationTargetException
java.lang.IllegalStateException
java.lang.ArrayIndexOutOfBoundsException
I call the saveTillXML() method when the window is closed, & the loadTillXML method in the Till's constructor.
I have all the gets & sets & argumentless constructors in the Till, & in all the clases which the Till uses.
public void saveTillXML() throws IOException{
XMLEncoder encoder=new XMLEncoder(new BufferedOutputStream(new FileOutputStream("till.xml")));
encoder.writeObject(this);
encoder.close();
}
public static void loadTillXML() throws IOException{
XMLDecoder decoder=new XMLDecoder(new BufferedInputStream(new FileInputStream("till.xml")));
decoder.readObject();
decoder.close();
}
The only thing I can think of is the fact that decoder.readObject() doesn't go into anything, which is probably should if I want to make the current instance be the XML it's decoding.
Thanks in advance.
Okay, I've managed to solve my problem. The loadTillXML needed a return method - Till - which then prompted me to think that it needs to be called outside Till. So I used it instead of private Till till=new Till(); which was in the window.
The working method:
public static Till loadTillXML() {
try{
XMLDecoder decoder=new XMLDecoder(new BufferedInputStream(new FileInputStream("till.xml")));
return (Till) decoder.readObject();
}
catch(FileNotFoundException fNFE){
System.out.println("Cannot find file");
Till till=new Till();
return till;
}
}

Categories