Can someone say that code below is good way to read all file? Maybe the first code block is using the ready method in a wrong way.
try (var br = new BufferedReader(new FileReader("/some-file.txt"))) {
while (br.ready()) {
System.out.println(br.readLine());
}
}
Or maybe is better approach to read file without method ready?
try (var br = new BufferedReader(new FileReader("/some-file.txt"))) {
while (true) {
var line = br.readLine();
if (line == null) break;
System.out.println(line);
}
}
I tested that two blocks and all blocks print all file content, but I've never saw the first way over internet.
Here's the documentation of BufferedReader#ready():
Tells whether this stream is ready to be read. A buffered character stream is ready if the buffer is not empty, or if the underlying character stream is ready.
[...]
Returns:
True if the next read() is guaranteed not to block for input, false otherwise. Note that returning false does not guarantee that the next read will block.
So, this method is about whether or not the next read will block. You're trying to read the whole file in one go, which means you don't really care if the next read will block. Worse, what if the reader is not ready? Your loop will break, you'll close the file, and the code will continue on without having read the whole source.
A typical way to code what you're doing is:
try (var reader = new BufferedReader(new FileReader("/some-file.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
Since readLine() is contracted to return null only when the end of the stream is reached.
Note of caution though. The above did not specify a charset, which means the default charset is used (see documentation for Java 17 and before and Java 18+). You can use FileReader(String,Charset) to specify a charset.
There's also the java.nio.file.* API that you can use to do the same thing. For example:
try (var stream = Files.lines(Path.of("/some-file.txt"))) {
stream.forEachOrdered(System.out::println);
}
The above uses the UTF-8 charset. You can use Files#lines(Path,Charset) to use a specific charset.
I think everyone does it in a different way (you could also read each byte using loops) but there is a way to read the whole file at once without loops
String file = new String(Files.readAllBytes(Paths.get("file")));
You can also use Files.readAllLines depending on what you want to do with data in file.
edit. First comment under your question also shows a better way
Related
I am trying to make a smaller version of Pwned Passwords (https://haveibeenpwned.com/Passwords) for my Ap comp sci project. Everything is goo besides 2 things:
(Issue 1) (image of my code to show better)
I have this below my jForm source code which declares each button/etc and what they do. I get this error though: "Illegal static declaration in inner class PassCheck.check. I do not now how to resolve this issue.
The second issue is using FileReader and Buffered Reader. I want the program to read the text inputted from the jForm and compare it to a file which has a list of commonly used passwords. How can I do this? Here is my code so far of just practicing with FR and BR:
import java.io.*;
public class MainFileReader {
public static void main(String[] args) throws Exception{
String refpass, input;
input = "1234";
FileReader fr = new FileReader("C:\\Users\\tcoley\\Downloads\\207pass.txt");
BufferedReader br = new BufferedReader(fr);
while((input = br.readLine()) != null){
refpass = br.readLine();
And I stopped here. I apologize as Java is not my strong suit but any help is much appreciated!
For your issue #2 - input is the string variable that is to be used hold the password you want to find in the file yet you eliminate its contents when you apply it to reading a line: (input = br.readLine()). It will now hold the currently read file line (this is no good). You need to use the refPass variable instead, for example: (refPass = br.readLine()).
You only need to use br.readLine() once in your loop. What your code is effectively doing right now (if it runs) is reading two (2) file lines on each iteration of the while loop. It could potentially fall into an Exception since there is no protection for null in the second read. Again no good.
Once you've read a file line, ensure it actually contains something. A lot of times a file will have a blank line in it that can throw a monkey wrench into things if it's not handled. To check for this you can do something like what is shown below after a line is read into refPass:
while((refPass = br.readLine()) != null) {
// remove leading & trailing whitespaces (if any).
refPass = refPass.trim();
// Skip past blank lines in file (if any).
if (refPass.isEmpty()) {
continue;
}
// .... rest of code ...
}
Now to complete your loop block code, you just need to compare the password read in with the password contained within the input variable (ex: "1234"). To do this, you could have something like this:
if (refPass.equals(input) {
System.out.println("Password Found!")
break; // Break out of the 'while' loop and close file.
}
On a side: Don't use == to compare Strings for content equality, that may not always work as you expect. Use the String#equals() method instead. Give the supplied link a read.
At the end of and outside your while loop, be sure to close the reader, for example: br.close(); so as to release hold on the file and free up resources.
You don't need to use BufferedReader. Buffering is only for inefficient reading and writing (ie doing multiple reads and writes)
Use Path and Files instead
Path p = "C:\\Users\\tcoley\\Downloads\\207pass.txt";
String file = new String(Files.loadAllBytes(p));
What does the file look like? There are a lot of ways to format a file and for simplicities sake, this will just assume it's one word per line:
With the line
refpass = br.readLine();
You are taking in the line from the file
boolean isEqual = refpas.equals(input);
This allows you to assess the line individually.
Remember that '==' is not the way to use String comparisons in Java.
("cat" == "cat") != ("cat".equals("cat"))
I am using Java to run a program and reading the program's text output into a buffered reader. I then want to print out the results by doing this:
while((line=input.readLine()) != null){
System.out.println(line);
}
For some reason, when doing this the readLine() method does not return at all about halfway through the text, and the program waits indefinitely. Yet when running this program from the command line directly, its output is exactly as expected, just 100 lines or so of simple text. What could cause readLine() to not return halfway through reading simple text?
This may happen if nothing has been written to the stream.
You may often encounter the situation in which readLine() hangs is when you invoke a process that is supposed to write errors to stderr. When the process finishes you may try to read all the errors by doing:
BufferedReader brCleanUp = new BufferedReader(new InputStreamReader(stderr));
while ((line = brCleanUp.readLine()) != null) {
//process the error line
}
brCleanUp.close();
But if nothing at all was written to stderr, the above readLine() would hang as you described.
The way to avoid it is to check if there is any point of reading the stream (I don't know if it's a bug or not, but this worked for me:)
boolean available = stderr.available() >= 1;
if (available) {
BufferedReader brCleanUp = new BufferedReader(new InputStreamReader(stderr));
for( ; available && (line = brCleanUp.readLine()) != null;
available = stderr.available() >= 1) {
System.out.println ("[Stderr] " + line);
}
brCleanUp.close();
}
You need to encode the text document into UTF-8 like this, then use Scanner.
// specify file path
String filePath = "C:/path/path/file-location/file.txt";
// make a scanner with the UTF-8 param
Scanner scanner = new Scanner(new File(filePath),"UTF-8");
// loop through text
while (scanner.hasNextLine()){
System.out.println(scanner.nextLine());
}
There are actually a few ways to encode text like this, but the importance lies within the text encoding itself. Once you have the document in the correct format, the objects and classes you chose to read input are at your own discretion.
What could cause readLine() to not return halfway through reading simple text?
If you are reading from a file in a file system, this is possibly due to a problem with the file system; e.g. a remote file server is not responding.
If you are reading from a socket, either the remote server hasn't (yet) written / flushed the data you are trying to read, or a network problem is stopping the data from getting through.
If you are reading from a pipe (e.g. the output of another program), then the other program hasn't written / flushed the data you are trying to read.
(Another cases are reading from a "device file" or a file in the "/proc" file system, or a loopback file system. In these cases, the possible causes are difficult to enumerate.)
I am trying to run a .csh script and read it's output into a StringBuffer.
the output sometime returns empty although running the script from console returns some output. the same running flow can sometimes returns output and sometimes not, although nothing is changed in the way the process starts (same script, path , args) and the script isn't changed as well.
I'm not getting any exceptions thrown.
what might cause output now to be read correctly/successfully ?
the code segment is
public static String getOutpoutScript(Process p) {
InputStream outpout = p.getInputStream();
logger.info("Retrived script output stream");
BufferedReader buf = new BufferedReader(new InputStreamReader(outpout));
String line = "";
StringBuffer write = new StringBuffer();
try {
while ((line = buf.readLine()) != null) {
write.append(line);
}
} catch (IOException e) {
// do something
}
return write.toString().trim();
}
beside the fact not closing the streams is not good, could this or something else in the code might prevent output from being read correctly under some circumstances ?
thanks,
If you launch it with ProcessBuilder, you can combine the error stream into the output stream. This way if the program prints to stderr you'll capture this too. Alternatively you could just read both. Additionally, you may not want to use readLine, you could be stuck for awhile if the program does not print end of line character at the end.
Maybe you must replace p.getInputStream() with p.getOutputStream()
Besides this sometimes processes can block waiting on input, so you must read and write asynchronously - one possible solution is to use different threads - e.g. one thread is reading, other is writing and one that is monitoring the process.
If you have an error, this will write to getErrorStream() by default. If you have a problem, I would ensure you are reading this somewhere.
If the buffer for this stream fills, your program will stop, waiting for you to read it.
A simple way around these issues is to use ProcessBuilder.redirectErrorStream(true)
I have to edit the contents of a file and write the edited conted to another file.Here is the code iam using .
import java.io.*;
import java.util.*;
public class TestRef {
ArrayList<String> lines = new ArrayList<String>();
String line= null;
public void printThis(){
try{
FileReader fr = new FileReader("C:\\Users\\questions.txt");
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter("C:\\Users\\questions_out.txt");
BufferedWriter out = new BufferedWriter(fw);
while((line=br.readLine()) != null) {
if(line.contains("Javascript"))
line.replace("Javascript"," JAVA");
lines.add(line);
out.write(line);
}
}
catch(Exception e){}
}
public static void main(String [] args){
TestRef tr = new TestRef();
tr.printThis();
}
}
So this is like reading one line at a time and printing it back to the file. But when I execute this code the output file is blank.? Can you please provide me with a sample code, how to read from a file, make change in the content and write the whole file to a new file ?
Well, a few problems:
You're never closing either your input or your output. Closing will also flush - it's possible that something's just not being flushed. You should close stream-based resources in a finally block, so that they end up being closed even in the face of an exception. (Given that you should be closing, I wouldn't bother explicitly flushing as well. Just make sure you close the top-level abstraction - i.e. out (and br).
You're catching Exception and then swallowing it. It could well be that an exception is being thrown, but you're not able to tell because you've swallowed it. You should at least be logging it, and probably stopping at that point. (I'd also suggest catching IOException instead of Exception.)
You're using FileWriter and FileReader which doesn't allow you to specify the input/output encoding - not the issue here, but personally I like to take more control over the encodings I use. I'd suggest using FileInputStream and FileOutputStream wrapped in InputStreamReader and OutputStreamWriter.
You're calling String.replace() and ignoring the result. Strings are immutable - calling replace won't change the existing string. You want:
line = line.replace("Javascript"," JAVA");
You're never using your lines variable, and your line variable would be better as a local variable. It's only relevant within the method itself, so only declare it in the method.
Your code would be easier to follow if it were more appropriately indented. If you're using an IDE, it should be able to do this for you - it makes a huge difference in readability.
The first one is the most likely cause of your current problem, but the rest should help when you're past that. (The point about "replace" will probably be your next issue...)
You are missing out.flush().
BufferedWriters don't write anything until either you flush them, or their buffer fills up.
Close the print writer, outside the loop.
out.flush();
out.close();
Moreover you are writing strings to new lines, if you just want to replace javascript with Java, then you might also wanna write '\n', next line character to new file where old file contains new line.
I have a Java code that reads through an input file using a buffer reader until the readLine() method returns null. I need to use the contents of the file again indefinite number of times. How can I read this file from beginning again?
You can close and reopen it again. Another option: if it is not too large, put its content into, say, a List.
Buffer reader supports reset() to a position of buffered data only. But this cant goto the begin of file (suppose that file larger than buffer).
Solutions:
1.Reopen
2.Use RandomAccessFile
A single Reader should be used once to read the file. If you want to read the file again, create a new Reader based on it.
Using Guava's IO utilities, you can create a nice abstraction that lets you read the file as many times as you want using Files.newReaderSupplier(File, Charset). This gives you an InputSupplier<InputStreamReader> that you can retrieve a new Reader from by calling getInput() at any time.
Even better, Guava has many utility methods that make use of InputSuppliers directly... this saves you from having to worry about closing the supplied Reader yourself. The CharStreams class contains most of the text-related IO utilities. A simple example:
public void doSomeStuff(InputSupplier<? extends Reader> readerSupplier) throws IOException {
boolean needToDoMoreStuff = true;
while (needToDoMoreStuff) {
// this handles creating, reading, and closing the Reader!
List<String> lines = CharStreams.readLines(readerSupplier);
// do some stuff with the lines you read
}
}
Given a File, you could call this method like:
File file = ...;
doSomeStuff(Files.newReaderSupplier(file, Charsets.UTF_8)); // or whatever charset
If you want to do some processing for each line without reading every line into memory first, you could alternatively use the readLines overload that takes a LineProcessor.
you do this by calling the run() function recursively, after checking to see if no more lines can be read - here's a sample
// Reload the file when you reach the end (i.e. when you can't read anymore strings)
if ((sCurrentLine = br.readLine()) == null) {
run();
}
If you want to do this, you may want to consider a random access file. With that you can explicitly set the position back to the beginning and start reading again from there.
i would suggestion usings commons libraries
http://commons.apache.org/io/api-release/org/apache/commons/io/FileUtils.html
i think there is a call to just read the file into a byteArray which might be an alternate approach
Not sure if you have considered the mark() and reset() methods on the BufferedReader
that can be an option if your files are only a few MBs in size and you can set the mark at the beginning of the file and keep reset()ing once you hit the end of the file. It also appears that subsequent reads on the same file will be served entirely from the buffer without having to go to the disk.
I faced with the same issue and came wandering to this question.
1. Using mark() and reset() methods:
BufferedReader can be created using a FileReader and also a FileInputStream. FileReader doesn't support Mark and Reset methods. I got an exception while I tried to do this. Even when I tried with FileInputStream I wasn't able to do it because my file was large (even your's is I guess). If the file length is larger than the buffer then mark and reset methods won't work neither with FileReader not with FileInputStream. More on this in this answer by #jtahlborn.
2. Closing and reopening the file
When I closed and reopened the file and created a new BufferedReader, it worked well.
The ideal way I guess is to reopen the file again and construct a new BufferedReader as a FileReader or FileInputStream should be used only once to read the file.
try {
BufferedReader br = new BufferedReader(new FileReader(input));
while ((line = br.readLine()) != null)
{
//do somethng
}
br.close();
}
catch(IOException e)
{
System.err.println("Error: " + e.getMessage());
}
}