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);
Related
I need to read from a file that contain 9000 words, what is the best way to read from this file and what is the difference between bufferingreader aND regular scanner.. or is there other good class to use?
Thanks
If you are doing "efficient" reading, there is no benefit to buffering. If, on the other hand, you are doing "inefficient" reading, then having a buffer will improve performance.
What do I mean by "efficient" reading? Efficient reading means reading bytes off of the InputStream / Reader as fast as they appear. Imagine you wanted to load a whole text file to display in an IDE or other editor. "inefficient" reading is when you are reading information off of the stream piecemeal - ie Scanner.nextDouble() is inefficient reading, as it reads in a few bytes (until the double's digits end), then transforms the number from text to binary. In this case, having a buffer improves performance, as the next call to nextDouble() will read out of the buffer (memory) instead of disk
If you have any questions on this, please ask
Open the file using an input stream. Then read its content to a string using this code:
public static void main(String args[]) throws IOException {
FileInputStream in = null;
in = new FileInputStream("input.txt");
String text = inputStreamToString(is);
}
// Reads an InputStream and converts it to a String.
public String inputStreamToString(InputStream stream) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while((length = stream.read(buffer)) != -1)
byteArrayOutputStream.write(buffer,0,length);
return byteArrayOutputStream.toString("UTF-8");
}
Check this answer for comparisons between buffered readers:
Read/convert an InputStream to a String
I normally use Scanners when I want to read a file line by line, or based on a delimiter. For example:
try {
Scanner fileScanner = new Scanner(System.in);
File file = new File("file.txt");
fileScanner = new Scanner(file);
while (fileScanner.hasNextLine()) {
String line = fileScanner.nextLine();
System.out.println(line);
}
fileScanner.close();
} catch (Exception ex) {
ex.printStackTrace();
}
To scan based on a delimiter, you can use something similar to this:
fileScanner.userDelimiter("\\s"); // \s matches any whitespace
while(fileScanner.hasNext()){
//do something with scanned data
String word = fileScanner.next();
//Double num = fileScanner.nextDouble();
}
This question already has an answer here:
java reader vs. stream
(1 answer)
Closed 7 years ago.
I am going over input output section and there are so much classes and interfaces that I am confused a little bit.
As documentation says InputStream is a byte based stream whereas Reader is character-based stream. But as I understood correctly the only difference between them is that Reader reads two bytes per time instead of one byte at a time as InputStream does.
Therefore I don't understand is there any difference:
Using InputStream
byte[] bytes = new byte[2];
InputStream in = new FileInputStream("input.txt");
int bytesRead = in.read(bytes);
while(bytesRead != -1) {
doSomethingWithData(data);
bytesRead = inputstream.read(data);
}
Using Reader
Reader reader = new InputStreamReader(new FileInputStream("input.txt"));
int data = reader.read();
while (data != -1) {
doSomethingWithData(data);
data = reader.read();
}
I am really confusing about these aspects. Explain please in details. Thanks.
You can use a Reader to read text data. And it's supports some character encoding like - ISO, UTF-8. If you want to read a text file with some encoding then you can use Readers like - BufferedReader, StringReader etc.
And you can use Stream (InputStream, OutputStream) to manipulate binary data. For example you want to read a image file then you can use FileInputStream and when you want to save it to disk then you can use FileOutputStream.
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.
How can I convert InputStreamReader to InputStream? I have an InputStream which contains some string and byte data and I want to parse it. So I wrap my InputStream to BufferedReader. Then I read 3 lines from it. After that I want to get the rest of data(bytes) as is. But if I try to get it nothing happens.
Code snippet:
BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
String endOfData = br.readLine();
String contentDisposition = br.readLine();
String contentType = br.readLine();
file = new File(filename);
if(file.exists()) file.delete();
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
byte[] data = new byte[8192];
int len = 0;
while (-1 != (len = is.read(data)) )
{
fos.write(data, 0, len);
Log.e("len", len+"");
}
fos.flush();
fos.close();
is.close();
The file is empty. If I don't wrap InputStream it works fine, but I need to read 3 lines and remove it.
Thanks.
If you want to mix text and byte data together, you should use OutputStream.writeUTF to write out those 3 lines, this way one single InputStream will be able to retrieve all the data that you need.
Take a look at commons-io's ReaderInputStream: it is a little heavy handed, but you can wrap the BufferedReader with that and read it as an input stream again.
It's pretty hard to mix byte and character input correctly, especially once you start throwing buffered readers / streams into the mix. I'd suggest that you either pick one and stick with it (converting your bytes to strings as necessary; care with the encoding!) or wrap the entire thing in a ZipOutputStream so you can have multiple logical "files" with different contents.
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 ..