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;
}
}
Related
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.
My app reads text file line by line and record offset of each line until the end of file. offset returns changed value when readLine is first executed. But it does not change any more after that. What is wrong with my code? I use RandomAccessFile instead of FileInputStream because seek() is faster than skip() when file is big.
String buffer;
long offset;
RandomAccessFile raf = new RandomAccessFile("data.txt", "r");
FileInputStream is = new FileInputStream(raf.getFD());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while (true) {
offset = raf.getFilePointer(); // offset remains the same after 1st readLine. why?
if ((buffer = br.readLine()) == null) // buffer has correct value.
return;
………………………………
}
Because BufferedReader is buffered. So it reads the data into it's buffer the first time and then just keeps it there until it needs more buffered data.
If you want to use a smaller buffer for testing purposes, try new BufferedReader(new InputStreamReader(is), 1000); or something. Your pointer should now increment by 1000 occasionally.
If you want your counter to work properly, you can do one of two things. Either you can count the characters you are receiving and then do some converting to byte lengths which you can use to make your own counter or you can use a FileReader with no buffering which will increment the counter the way you expect.
Update: It seems FileReader does something behind the scenes. I'd use something like new CountingInputStream(new BufferedInputStream(new FileInputStream(raf.getFD())) loop through the data in byte form, manually identify line endings while dumping the bytes into a String. Not the prettiest way, but the only way I can think of given Reader's internal buffering. I think CountingInputStream is provided by Apache freely and it contains a count method or something like that.
Something strange happens on a text parser that I am writing an I thought maybe you experts can find what I am doing wrong.
The parser is searching for several search-terms in the text and copy the found results to an output parsed file on the SD card.
The code is:
String line; // line reading buffer
…
Process process = Runtime.getRuntime().exec(commandLine.toArray(new String[0]));
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
…
while ((line = bufferedReader.readLine()) != null){
line = bufferedReader.readLine(); // reading the buffer
/*** parsing the buffer line by line ***/
if (line.contains("SearchTermA")){
// parsing the text in this line
}
if (line.contains("SearchTermB")){
// parsing the text in this line
}
// Check that we got to a cretin part in the file
if (line.contains("SearchTerm_text")){
textID = 1;
}
if (textID == 1){
if (line.contains("SearchTermC")){
// parsing the text in this line
}
}
Now, the issue is that at the beginning of the file (the file is very long) this works OK but sometimes along the way SearchTermB appears in the original text but is not deceted by the code. I tried stepping the code with Eclipse on the target android machin and I can clearly see that “line” contains SerchTermB but the debugger ignores this IF statement and continue to the next IF statement.
Could it be that line.containes() is missing a search-term?
Please help in finding what am I doing wrong since this prevents me from sleeping at night…..
Thanks,
Your while loop is reading two lines at a time...
while ((line = bufferedReader.readLine()) != null){
line = bufferedReader.readLine(); // reading the buffer
In other words you call readLine() in your while statement in order to check that it's not a null result and then you immediately call readLine() again.
Get rid of this...
line = bufferedReader.readLine(); // reading the buffer
...and see what happens.
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.