I'm writing an InputStream that supplies lines from a file in constant intervals. I used BufferedReader before, but ran into buffering issues with it (wasn't getting anything until the entire file was read), and speed isn't an issue anyways (the intervals are something like every second, or every half second - along those lines). Is there a class with a readLine method like in BufferedReader, except unbuffered?
(Edit: I just checked - my class seems to work, apparently the problem was with the output)
Here's the code where I used the stream (OnlineDataSimulator). I already checked, the stream does exactly what I want, so apparently I'm doing something wrong with the output. (The actual problem is, I want output to occur every X milliseconds - X being the second parameter to OnlineDataSimulator. What happens when I run this code is, that I first get an X*lines wait and then the entire output at once instead.)
System.out.println("Testing:");
PrintStream fout = new PrintStream(new FileOutputStream("testfile"));
for(int i=0; i<20; ++i) {
fout.println(i);
}
fout.close();
BufferedReader fin = new BufferedReader(new InputStreamReader(
new OnlineDataSimulator("testfile",250)));
String line;
while((line=fin.readLine())!= null){
System.out.println(line);
System.out.flush();
}
fin.close();
(new File("testfile")).delete();
Try it this way.... This worked for me..
File f = new File("path");
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
String s = null;
while ((s=br.readLine())!=null)
{
System.out.println(s);
}
No, there is no other non-buffered option.
A solution would be to write your own Reader which has a InputStreamReader as an underlying stream and in the readLine() method you should call read() of the underlying input stream reader until "\n" is found. Aggregate all these and return them as a string.
If you don't want to have a real buffer but want to use the functionality of BufferedReader you could initialize it with buffer size 1. As you commented that speed isn't an issue maybe is the most reliable solution.
new BufferedReader(reader, 1)
public BufferedReader(Reader in, int sz)
and you can check the readLine() method source code here, in case you want to implement your own.
Related
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.
Can someone explain to me why can I use FileInputStream or FileReader for a BufferedReader? What's the difference? And at the same time what is the advantage of a Scanner over a BufferedReader? I was reading that it helps by tokenizing, but what does that mean?
try {
//Simple reading of bytes
FileInputStream fileInputStream = new FileInputStream("path to file");
byte[] arr = new byte[1024];
int actualBytesRead = fileInputStream.read(arr, 0, arr.length);
//Can read characters and lines now
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
String lineRead = bufferedReader.readLine();
char [] charArrr = new char[1024];
int actulCharsRead = bufferedReader.read(charArrr, 0, charArrr.length);
//File reader allows reading of characters from a file
FileReader fileReader = new FileReader("path to file");
actulCharsRead = fileReader.read(charArrr, 0, charArrr.length);
//It is a good idea to wrap a bufferedReader around a fileReader
BufferedReader betterFileReader = new BufferedReader(new FileReader(""));
lineRead = betterFileReader.readLine();
actulCharsRead = betterFileReader.read(charArrr, 0, charArrr.length);
//allows reading int, long, short, byte, line etc. Scanner tends to be very slow
Scanner scanner = new Scanner("path to file");
//can also give inputStream as source
scanner = new Scanner(System.in);
long valueRead = scanner.nextLong();
//might wanna check out javadoc for more info
} catch (IOException e) {
e.printStackTrace();
}
Dexter's answer is already useful, but some extra explanation might still help:
In genereal:
An InputStream only provides access to byte data from a source.
A Reader can be wrapped around a stream and adds proper text encoding, so you can now read chars.
A BufferedReader can be wrapped around a Reader to buffer operations, so instead of 1 byte per call, it reads a bunch at once, thereby reducing system calls and improving performance in most cases.
For files:
A FileInputStream is the most basic way to read data from files.
If you do not want to handle text encoding on your own, you can wrap it into a InputStreamReader, which can be wrapped into a BufferedReader.
Alternatively, you can use a FilerReader, which should basically do the same thing as FileInputStream + InputStreamReader.
Now if you do not want to just read arbitrary text, but specific data types (int, long, double,...) or regular expressions, Scanner is quite useful. But as mentioned, it will add some overhead for building those expressions, so only use it when needed.
Introduced in Java 8 is Files.lines. This supports sufficient simple file manipulation to relieve at least some Perl envy :-)
Files.lines(Paths.get("input.txt"))
.filter(line -> line.startsWith("ERROR:"))
.map(String::toUpperCase).forEach(System.out::println);
FileInputStream fstream = new FileInputStream("\\file path");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while (br.ready()) {
line = br.readLine();
}
Please let me know how to read a file from the last line to first provided the row number is not fixed and is varying with time? I know the above is useful for reading it from first row...
This might be helpfull for you [1]: http://mattfleming.com/node/11
read the file into a list, and process that list backwards...
files and streams are usually designed to work forward; so doing this directly with streams might turn out a lite awkward. Only advised when the files are really huge...
You cannot read a Buffer backwards, you can however count the lines of your buffer as explained in the link below
http://www.java2s.com/Code/Java/File-Input-Output/Countthenumberoflinesinthebuffer.htm
And afterwards select your line using this code:
FileInputStream fs= new FileInputStream("someFile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
for(int i = 0; i < 30; ++i)
br.readLine();
String lineIWant = br.readLine();
As you can see, you iterate, reading each line(and doing nothing) before you get to the one you want (here we got 31 lines passed and #32 is the one read). If your file is huge this will take a lot of time.
Other way to to this is to input everything in a List and then with a sizeof() and a for() you can select everything you want.
If you know the length of each line then you can work out how many lines there are by looking at the size of the file and dividing by the length of each line. (this of course ignores any possible metadata in the file)
You can then use some maths to get the start byte of the last line. Once you have then you can then open a RandomAccessFile on the file and then use seek to go to that point. Then using readline you can then read the last line
This does assume though that the lines are all the same length.
You can use FileUtils
and use this method
static List<String> readLines(File file)
Reads the contents of a file line by line to a
List of Strings using the default encoding for the VM.
This will return a List then use Collections.reverse()
Then simply iterate it to get the file lines in reverse order
Just save info backwards, that's all I did.just read Pryor to save and use \n
You can save the lines in a list (in my code a arraylist) and "read" the lines backwards from the arraylist:
try
{
FileInputStream fstream = new FileInputStream("\\file path");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = "";
ArrayList<String> lines = new ArrayList<String>();
//Read lines and save in ArrayList
while (br.ready())
{
lines.add(br.readLine());
}
//Go backwards through the ArrayList
for (int i = lines.size(); i >= 0; i--)
{
line = lines.get(i);
}
}
catch (Exception e)
{
e.printStackTrace();
}
ive tried many different things and this is the only thing that has worked with reading one line from a file so far...
try{
FileInputStream fstream = new FileInputStream("./Saves/Body.sav");
BufferedReader br = new BufferedReader(new InputStreamReader(infstream);
String strLine;
while ((strLine = br.readLine()) != null) {
System.out.println(strLine);
w1.Body = strLine;
}
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
I am trying to create a load function so i can load text from a file onto a string onto a jTextArea... Without any sort of openfiledialog
I'd personally use Guava:
File file = new File("Saves", "Body.sav");
String text = Files.toString(file, Charsets.UTF_8);
That's assuming it's a UTF-8 file, of course. Adjust accordingly.
Your current code has a number of issues:
It creates a DataInputStream for no obvious reason
You probably don't gain much from using BufferedReader
You're not specifying the character encoding, so you're getting the platform default, implicitly, which is almost never a good idea.
You're closing in which is in the middle of the chain of inputs for some reason... I'd expect to close either br or fstream
You're only closing in if there's no exception (use a finally block or a try-with-resources statement if you're using Java 7)
You appear to have a field called Body, violating Java naming conventions
You're catching Exception rather than IOException - prefer to catch specific exceptions
You're "handling" the exception by effectively ignoring it, which is almost never appropriate. (The code which reads a file is very rarely the right code to decide what to do with an exception.)
How do i read ... put in jTextArea?
Ignoring the entire middle of that statement, I suggest.
File file = new File("./Saves/Body.sav");
FileReader fileReader = new FileReader(file);
textArea.read(fileReader, file);
You can use a StringBuilder (or the synchronized version StringBuffer) and keep appending strLine to it. Declare it this way:
StringBuilder s = new StringBuilder();
and in the while loop:
s.append(strLine + "\n");
I have 2 classes who must read an InputStream, the first one should only interpret the first line of the stream BUT the first line should be removed from the stream so that class B can interpret everything after the first line. Which doesn't work when I pass my InputStream to a BufferedReader and do a readLine().
I know I could do a read on the stream until I've encountered a \b but maybe a more proper solution exists to do the job?
// Reads the first line from the stream and everything else
public String retrieveFileNameFromTheFirstLineInInputStream(InputStream in) throws IOException {
InputStreamReader isReader = new InputStreamReader(in);
BufferedReader reader = new BufferedReader(isReader);
return reader.readLine();
}
You can't remove something from an InputStream, you just can read from it. Don't use the BufferedReader to read the line, because it surely will read much more than the first line from the InputStreamReader (to fill its buffer) which itself reads from the InputStream.
I'd suggest to read using the InputStreamReader until the end of the line is reached, then pass the InputStream instance to your code which should read it.
BTW, you always should specify the encoding used by the InputStreamReader, otherwise the system encoding will be used to convert the bytes from the InputStream to characters which can differ on different machines.
I believe even InputStreamReader can buffer input, so Mike L's answer can miss input.
It's awkward, but you could use ReaderInputStream from Apache commons-io. So:
BufferedReader reader = new BufferedReader(
new InputStreamReader(in));
String firstLine = reader.readLine();
InputStream in2 = new ReaderInputStream(reader);
// continue with in2 ..