I want to read an InputStream in two passes, line by line. I use the following code for the first pass:
LineNumberReader reader = new LineNumberReader(new InputStreamReader(inputStream));
String line;
String eventId = null;
Set<Integer> artistIds = new HashSet<Integer>();
while((line = reader.readLine())!=null) {
// process first pass
}
// how do I reset reader so that I can read from the beginning again?
There is a reset() method available but it resets to the last mark in the file. I don't quite understand what that means. Can I use mark and reset to achieve the reset to beginning behavior? Something like
LineNumberReader reader = new LineNumberReader(new InputStreamReader(inputStream));
reader.mark(0); // mark at the 0th position
// process first pass: repeated calls to readline() until EOF
reader.reset(); // reset to 0th position??
// process second pass
While testing at my local machine, I was reader.close()-ing before the second pass and it worked. However, when I do this in HDFS, reader.close() probably closes the HDFS InputStream too and I get a java.io.IOException: Stream closed exception.
Mark and reset work, but don't call .mark(0) that sets the read ahead limit to 0 which means .reset() won't work reliably if you read more than 0 bytes.
EDIT: .mark() marks the current location in the stream. Unlike C++ where you can .seek() the beginning or end of a file and offsets, Java streams only allow you to mark a current location and then go back to it with .reset(). This can go "back to the beginning" but only if it was marked before processing started.
Try this:
import java.io.*;
public class StreamTwice
{
public static void printLines(LineNumberReader r) throws IOException
{
String line;
while( (line = r.readLine()) != null )
System.out.println(line);
System.out.println();
}
public static void main(String []args) throws Exception
{
ByteArrayInputStream s = new ByteArrayInputStream(
"one\ntwo\nthree".getBytes()
);
LineNumberReader r = new LineNumberReader(new InputStreamReader(s));
r.mark(5000); // more than the number of bytes being read.
// this is the read ahead limit.
printLines(r);
r.reset(); // go back to where mark was called.
printLines(r);
}
}
Try to make sure you don't read more bytes than the read ahead limit you set in .mark() before calling .reset().
P.S. - Not all streams (or readers) support .mark(), which you can check with .markSupported().
Reset() resets the line reader to the most recent mark (which is the last if you are going sequentially.) What you need to do is manually change the line by calling " reader.SetLineNumber(0); " the parameter indicates the line number that you want to go to.
Related
I am new to java so now I am using buffer reader in my program once I end the Loop the loop will break but again In the second loop I have called the same Buffer Reader now again I want to read from the first line so help me.
Now It Is reading as Null since It has Reached End of the Line
while ((s2 = br.readLine())!=null) {
if (s2.contains(keyword2)) {
s2 = s2.replaceAll(keyword2, " ");
Alternate_Account_Number = s2;
System.out.println(Alternate_Account_Number);
break;
}
}
String s3;
String Meter_Number = null;
String keyword3 = arra.get(8);
while ((s3 = br.readLine()) != null) {
if (s3.contains(keyword3)) {
s3 = s3.replaceAll("\\D+", " ");
Meter_Number = s3;
System.out.println(Meter_Number);
break;
}
}
// set the mark at the beginning of the buffer
bufferedReader.mark(0);
// read through the buffer here...
// reset to the last mark; in this case, it's the beginning of the buffer
bufferedReader.reset();
Reset buffer with BufferedReader in Java?
You can use
mark(int readAheadLimit)
Marks the present position in the stream.
You can use
close()
Closes the stream and releases any system resources associated with it. And read it again.(do as per the requirement)
reset()
Resets the stream. If the stream has been marked, then attempt to reposition it at the mark. If the stream has not been marked, then attempt to reset it in some way appropriate to the particular stream, for example by repositioning it to its starting point. Not all character-input streams support the reset() operation, and some support reset() without supporting mark().
Read More
I have a buffer reader working to read a text file then save the read data as a string. The buffer reader is in a continuous loop reading the text file every second. I would like to do a Thread.sleep if the buffer reader reads the same text two times in a row.
For example if the buffer reader reads "foo" then when it is ran again in the next second if it reads "foo" again then the thread sleeps for a certain amount of time.
I have the buffer reader within a try method but I do not know how to get it to do the above.
Could anyone help with this?
Thanks
Keep track of the previous line read in in a String variable, which you can initialize as an empty string. When you read in each line, check whether it's equals() to the previously stored line in that variable. If so, do what you want to do, like Thread.sleep(). Otherwise save the current line into that variable. In code:
BufferedReader reader = new BufferedReader(new FileReader("foo.txt"));
String foo = "";
String old = "";
while((foo = reader.readLine()) != null) {
if(foo.equals(old)) {
System.out.println("Sleeping...");
Thread.sleep(1000);
} else {
old = foo;
}
}
So this is a very simple problem with a simple solution that I'm just not seeing:
I'm trying to get a list of data through an InputStream, looping until I reach the end of the stream. On each iteration, I print the next line of text being passed through the InputStream. I have it working but for one small problem: I'm truncating the first character of each line.
Here's the code:
while (dataInputStream.read() >= 0) {
System.out.printf("%s\n", dataInputReader.readLine());
}
And the output:
classpath
project
est.txt
Now, I know what's going on here: the read() call in my while loop is taking the first char on each line, so when the line gets passed into the loop, that char is missing. The problem is, I can't figure out how to set up a loop to prevent that.
I think I just need a new set of eyes on this.
readLine for DataInputStream is deprecated. You may try wrapping it with a BufferedReader:
try
{
String line;
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader( dataInputStream ) );
while( (line = bufferedReader.readLine()) != null )
{
System.out.printf("%s\n", line);
}
}
catch( IOException e )
{
System.err.println( "Error: " + e );
}
Also, I`m not sure, that it is a good idea to use available() due to this specification:
* <p>Note that this method provides such a weak guarantee that it is not very useful in
* practice.
Use one BufferedReader and InputStreamReader, here is one example:
InputStream in=...;
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while (br.ready()) {
String line = br.readLine();
}
dataInputStream.read() reads the first character of the InputStream, the same as dataInputReader.readLine() reads the complete next line. Every read character or line is then gone. you can use the dataInputStream.available() to check if the InputStream has data available.
That should print the correct output:
while (dataInputStream.available()) {
System.out.printf("%s", dataInputReader.read());
}
String line;
while ((line = dataInputReader.readLine()) != null) {
System.out.println(line);
}
I have problem to read last n lines from url. How to do that ? I have url.openstream but there is no contrsuctor for RandomAccessFile which has input for stream. Can somebody help me ? Is there meybe already library for this. ( I know how to implement with RandomAccess when I have file but how to change stream to file ).
Open the URL stream as per usual.
Wrap the returned InputStream in a BufferedReader so you can read it line by line.
Maintain a LinkedList into which you will save the lines.
After reading each line from the BufferedReader:
Add the line to the list.
If the size of the list is greater than "n" then call LinkedList#removeFirst().
Once you have read all lines from the stream the list will contain the last "n" lines.
For example (untested, just for demonstration):
BufferedReader in = new BufferedReader(url.openStream());
LinkedList<String> lines = new LinkedList<String>();
String line = null;
while ((line = in.readLine()) != null) {
lines.add(line);
if (lines.size() > nLines) {
lines.removeFirst();
}
}
// Now "lines" has the last "n" lines of the stream.
Sorry. You're going to have to do this one yourself. But don't worry because it's pretty simple.
You just need to keep track of the last n lines you have encountered since you started reading from the UrlStream. Might I suggest using a Queue?
Basically you could do something like
public String[] readLastNLines(final URL url, final int n) throws IOException{
final Queue<String> q = new LinkedList<String>();
final BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
String line=null;
while ((line = br.readLine())!=null)
{
q.add(line);
if (q.size()>n) q.remove();
}
return q.toArray(new String[q.size()]);
}
readLastNLines returns an array containing the last n lines read from url.
Unfortunately, you cannot use a RandomAccessFile with a stream from the Internet because streams are, by definition, not random access.
I want to read a text file in Java. After I finish, some text will be appended by another application, and then I want to read that. Lets say there are ten lines. When the other app appends one more line, I dont want to read the whole file again; just the new line. How can I do this?
Something like this could work:
BufferedReader reader = .. // create a reader on the input file without locking it
while(otherAppWritesToFile) {
String line = reader.readLine();
while(line != null) {
processLine(line);
line = reader.readLine();
}
Thread.sleep(100);
}
Exception handling has been left out for the sake of simplicity.
Once you get an EOF indication, wait a little bit and then try reading again.
Edit: Here is teh codez to support this solution. You can try it and then change the control flow mechanisms as needed.
public static void main(final String[] args) throws IOException {
final Scanner keyboard = new Scanner(System.in);
final BufferedReader input = new BufferedReader(new FileReader("input.txt"));
boolean cont = true;
while (cont) {
String line = input.readLine();
while (line != null) {
System.out.println(line);
line = input.readLine();
}
System.out.println("EOF reached, add more input and type 'y' to continue.");
final String in = keyboard.nextLine();
cont = in.equalsIgnoreCase("y");
}
}
EDIT: Thanks for adding some code Tim. Personally, I would just do a sleep instead of waiting for user input. That would more closely match the users' requirements.
You could try using a RandomAccessFile.
Open the file and then invoke the length() to get the length of the file. Then you can use the readLine() method to get your data. Then the next time you open the file you can use the seek() method to position yourself to the previous end of the file. Then read the lines and save the new length of the file.