I'm writing a program in java (already wrote a version in C too). I really need to put a character back to the input-stream after I read it. This can be accomplished by ungetc() in C/C++, and I was wonder how can I do the same thing in Java?
For those of you don't know C/C++:
char myc = (char)System.in.read();
and I check the value of myc and now I want to put back myc in to the System.in! so again when I call System.in, I get that value. (But How can I do this?)
NOTE: I'm looking for exact technique. Please do not advise me to catch it or log it somewhere else and read off from there, because I know how to those kinda stuff. What I'm interested in is equivalent of ungetc() in Java if there's any.
Cheers.
You are looking for PushbackInputStream
Java's IO library is designed so the primitives are really basic and additional functionality is added through composition. For example, if you wanted to buffer input from a file, you would call new BufferedInputStream(new FileInputStream("myfile.txt")); or if you wanted to read from the stream as text using UTF-8 encoding you'd call new InputStreamReader(new FileInputStream("myfile.txt"), "UTF-8");
So what you want to do is create a PushbackInputStream with new PushbackInputStream(System.in);
The caveat here is you're not actually pushing the bytes back onto standard input. Once you've read from System.in it's gone, and no other code accessing System.in will be able to get at that byte. Anything you push back will only ever be available from particular PushbackInputStream you created to handle the data.
If the input stream supports marking you can use the mark() and reset() methods to achieve what you intend.
You can wrap System.in into a BufferedInputStream or a BufferedReader to gain marking support.
A RandomAccessFile can .seek( .getFilePointer() - 1 ).
Related
I have some confusion if someone can help. Tried searching the web for it but didn't get any satisfying answer.
Why don't we simply use System.in.somemethod() to take input in Java just like we do for output? Like System.out.println() is used so why not System.in as it is? Why is there a long process for Input?
The only methods that System.in, an InputStream, provides are the overloads of read. Sure, you could do something like:
byte[] bytes = new byte[5];
System.in.read(bytes);
System.out.println(Arrays.toString(bytes));
to read five bytes from the console. But this has the following disadvantages:
You need to handle the checked IOException. (not shown in the code snippet above)
Hard to work with bytes. (unless you want them specifically)
You usually just want to read the input until the end of a line. With this it's hard to know where the end of a line is.
So that's why people use Scanners to wrap the System.in stream into something more user-friendly.
Taking input from the command line will always be trickier than just outputting data. This is because there is no way to know that the input is semantically correct, structured correctly or even syntactically correct.
If you just want to read bytes from System.in then a lot of the uncertainty of the input disappears. In that case there is only two things to take into account: I/O errors and end-of-input - both of which are also present for System.out. The only other thing that may be tricky is that InputStream may not return all the bytes that are requested in a single call to read.
So reading data from System.in isn't hard; interpreting the data - which often comes down to parsing the data or validating the data - is the hard part. And that's why often the Scanner class is used to make sense of the input.
Just as you cannot use System.out.somemethod() instead of System.out.println() in the same way you cannot use System.in.somemethod() instead of System.in.read().
When reading from Standard Input using System.in can wrapping it with a BufferedInputStream improve performance or is it already buffered already?
An example when used in combination with a Scanner
Scanner in = new Scanner(System.in);
//or
Scanner in = new Scanner(new BufferedInputStream(System.in));
The System.in javadoc does not explicitly state whether it is buffered or not.
Looking at the source code of my x64 Linux 1.8.0_111 java.lang.System#initializeSystemClass suggests it is buffered.
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
...
setIn0(new BufferedInputStream(fdIn));
Is there any platform/jdk implementation where System.in is unbuffered and it makes sense to wrap it?
Well a quick bit of debug:
System.out.println(System.in.getClass());
class java.io.BufferedInputStream
So no, wrapping System#in wouldn't help, as it is already a BufferedInputStream. This may be OS-dependent, as I haven't found an actual JLS/etc specification for what the InputStream for System#in will always be.
Will it hurt? Most likely not.
Will it help? Depends, but probably not.
Keep in mind that the operating system has a say here too. One should never forget that the JVM is just one layer in a whole stack of components. In other words : your Linux kernel might be doing all kinds of things behind the covers - so it really doesn't matter that much what your application code does here.
I currently use:
BufferedReader input = new BufferedReader(new FileReader("filename"));
Is there a faster way?
While what you've got isn't necessarily the absolute fastest, it's simple. In fact, I wouldn't use quite that form - I'd use something which allows me to specify a charset, e.g.
// Why is there no method to give this guaranteed charset
// without "risk" of exceptions? Grr.
Charset utf8 = Charset.forName("UTF-8");
BufferedReader input = new BufferedReader(
new InputStreamReader(
new FileInputStream("filename"),
utf8));
You can probably make it go faster using NIO, but I wouldn't until I'd seen an actual problem. If you see a problem, but you're doing other things with the data, make sure they're not the problem first: write a program to just read the text of the file. Don't forget to do whatever it takes on your box to clear file system caches between runs though...
If it's /fast/ you want, keep the character data in encoded form (and I don't mean UTF-16). Although disc I/O is generally slow (unless it's cached), decoding and keeping twice the data can also be a problem. Although the fastest to load is probably through java.nio.channels.FileChannel.map(MapMode.READ_ONLY, ...), that has severe problems with deallocation.
Usual caveats apply.
Look into java.nio.channels.FileChannel.
Have you benchmarked your other options? I imagine that not using a BufferedReader may be faster in some cases - like extremely small files. I would recommend that you at the very least do some small benchmarks and find the fastest implementation that works with your typical use cases.
Depends on what you want to read. The complete file, or from a specific location, do you need to able to seatch through it, or do you want to read the complete text in one go?
File file = new File("querySourceFileName");
Scanner s = new Scanner(file);
while (s.hasNext()) {
System.out.println(s.nextLine());
}
I want to read each line from a text file and store them in an ArrayList (each line being one entry in the ArrayList).
So far I understand that a BufferedInputStream writes to the buffer and only does another read once the buffer is empty which minimises or at least reduces the amount of operating system operations.
Am I correct - do I make sense?
If the above is the case in what situations would anyone want to use DataInputStream. And finally which of the two should I be using and why - or does it not matter.
Use a normal InputStream (e.g. FileInputStream) wrapped in an InputStreamReader and then wrapped in a BufferedReader - then call readLine on the BufferedReader.
DataInputStream is good for reading primitives, length-prefixed strings etc.
The two classes are not mutually exclusive - you can use both of them if your needs suit.
As you picked up, BufferedInputStream is about reading in blocks of data rather than a single byte at a time. It also provides the convenience method of readLine(). However, it's also used for peeking at data further in the stream then rolling back to a previous part of the stream if required (see the mark() and reset() methods).
DataInputStream/DataOutputStream provides convenience methods for reading/writing certain data types. For example, it has a method to write/read a UTF String. If you were to do this yourself, you'd have to decide on how to determine the end of the String (i.e. with a terminator byte or by specifying the length of the string).
This is different from BufferedInputStream's readLine() which, as the method sounds like, only returns a single line. writeUTF()/readUTF() deal with Strings - that string can have as many lines it it as it wants.
BufferedInputStream is suitable for most text processing purposes. If you're doing something special like trying to serialize the fields of a class to a file, you'd want to use DataInput/OutputStream as it offers greater control of the data at a binary level.
Hope that helps.
You can always use both:
final InputStream inputStream = ...;
final BufferedInputStream bufferedInputStream =
new BufferedInputStream(inputStream);
final DataInputStream dataInputStream =
new DataInputStream(bufferedInputStream);
InputStream: Base class to read byte from stream (network or file ), provide ability to read byte from the stream and delete the end of the stream.
DataInputStream: To read data directly as a primitive datatype.
BufferInputStream: Read data from the input stream and use buffer to optimize the speed to access the data.
You shoud use DataInputStream in cases when you need to interpret the primitive types in a file written by a language other Java in platform-independent manner.
I would advocate using Jakarta Commons IO and the readlines() method (of whatever variety).
It'll look after buffering/closing etc. and give you back a list of text lines. I'll happily roll my own input stream wrapping with buffering etc., but nine times out of ten the Commons IO stuff works fine and is sufficient/more concise/less error prone etc.
The differences are:
The DataInputStream works with the binary data, while the BufferedReader work with character data.
All primitive data types can be handled by using the corresponding methods in DataInputStream class, while only string data can be read from BufferedReader class and they need to be parsed into the respective primitives.
DataInputStream is a part of filtered streams, while BufferedReader is not.
DataInputStream consumes less amount of memory space being it is a binary stream, whereas BufferedReader consumes more memory space being it is character stream.
The data to be handled is limited in DataInputStream, whereas the number of characters to be handled has wide scope in BufferedReader.
I'm using the MIDP 2.0 (JSR 118) and I just noticed that there is no reader for strings in J2ME.
Does anyone know how you are supposed to read Strings from an InputStream or InputStreamReader in a platform independent way (i.e. between two java enabled cell phones of different models)?
Which profile are you using? The MID profile in JSR 118 specifies InputStreamReader (not StringReader, but that wouldn't help you read from an InputStream anyway).
EDIT: To reflect the change to the question :)
You use InputStreamReader.read(char[], int, int) and when you've read all you want to, create a new string from a char array. If you want to read a line at a time as you would from BufferedReader, you basically need to implement the functionality of BufferedReader yourself (keeping a buffer of "read but not consumed" chars) and keep reading until you hit a line break.
Alternatively have a look at DataInputStream.readUTF().
It does required that the string being read off the InputStream be encoded appropriately (as in by a corresponding DataOutputStream.writeUTF(String)) so it might not be what you're looking for - but it does work across different phones/models etc.
Well... I know this was a LONG time ago.
You need to do exactly what John said, and it is VERY simple. It almost took me 5 hours to figure this one out the first time...
I still wonder why j2ME didn't include something as essential as the BufferedReader method for sockets, it's not like the freakin cellphones will crash with it... and yes, I don't give a rat's ass if my app runs 1ms slower than it should.
(I'm just going to put the relevant code, I assume you know how to form classes and import the required libraries)
ServerSocketConnection listener
= (ServerSocketConnection)Connector.open("socket://:1235");
System.out.println("Waiting for connection...");
StreamConnection server = listener.acceptAndOpen();
InputStream is = server.openInputStream();
//Now comes the fake BufferedReader equivalent part
int ch = 0;
StringBuffer sb = new StringBuffer();
while ((ch = is.read()) != -1){
sb.append((char)ch);
if(sb.charAt(sb.length()-1) == 13 ) {
//Carriage return was received or ENTER was pressed
break; //Exit loop and print input
}
}
As you can see, the is.read() method will lock the thread till new input is received from the user ONE BYTE AT A TIME. This means if you use telnet to test, each keystroke will make the loop iterate once, hence, we simply concatenate char by char in a StringBuffer until char 13 is received.
System.out.println(sb.toString());
I hope this helps people trying to do a socket server on j2ME. I already crafted a fully functional multithreaded version of this for blackberry, in case anyone needs it.
Would you be able to provide an example of this?
You use InputStreamReader.read(char[], int, int) and when you've read all you want to, create a new string from a char array. If you want to read a line at a time as you would from BufferedReader, you basically need to implement the functionality of BufferedReader yourself (keeping a buffer of "read but not consumed" chars) and keep reading until you hit a line break.