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"))
Related
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
I'm trying to write a program that will find the specific words in txt file, and write the whole line in separate file. For now my program just rewrites the whole file and saves it into the new one. This part is needed for the rest of the program where these lines will be replaced, but that I already created. I'm just a beginner in Java and I can't handle it. Will I need to use regex?
import java.io.*;
public class change {
public static void main(String[] args) {
try {
BufferedWriter bw = new BufferedWriter(
new FileWriter("path\\file.txt"));
BufferedReader br = new BufferedReader(
new FileReader("path\\newfile.txt"));
String s;
while((s = br.readLine()) != null){
bw.write(s + "\n");
}
br.close();
bw.close();
} catch(Exception ex){
return;
}
}
}
Multiple issues with this code.
Deplorable exception handling
This code, if a problem occurs, will take all useful information about your exception (which is at least 4 things: The exception's type, the exception's message, the stack trace, and the causual chain), and tosses it in the garbage.
You will write bugs. Loads of em. Your assumptions about where your app run will change on you.
Exceptions are crucial in managing this.
Stop writing code like this. The fix is easy, and even reduces and simplifies your code! Simply pile throws Exception at the end of your main declaration (public static void main(String[] args) throws Exception {) and remove the try, the catch, and the return in the catch.
This way, the exception bubbles up to whatever invokes main itself, and that will 'handle' it by printing all the various useful parts and exiting your app. Which is what you want.
charset violations
Files are bags of bytes, but Writer and Reader work in terms of characters. Anytime bytes are converted to characters or vice versa, an encoding is applied. UTF-8 is an encoding. So is ISO-8859-1, MacRoman, CP452, etcetera.
If you don't see the encoding being applied then usually that means 'platform default' is applied and you almost never want that. It leads to code that seems to work fine until you run it elsewhere or on different files and then all hell breaks loose.
The fix is to either use APIs which have baked into their specification that they default to UTF_8 (such as the new Files API), or to explicitly specify. In passing, unfortunately, FileWriter and FileReader are not fit for purpose; do not ever use these classes, they are effectively broken as designed. Their API is also obsolete, there's a newer API.
Using the old APIs, you'd fix it as follows:
new BufferedWriter(new InputStreamWriter(new FileInputStream("path\\file.txt"), StandardCharsets.UTF_8));
Using the new APIs, well, that's a bit more involved, see below.
Resource management violation
When you open resources, you must explicitly close them too. Java is a garbage collected language, but the 'point' of garbage collection is that the JVM will run collection when it deems neccessary, and it might be days before it does. Thus, any object that takes up more than simply memory if you leave it laying about needs explicit closing. "Handles" to files is one such resource: Your OS has a limited supply of these and will flat out refuse to let a process open more files once it has opened a certain amount. Your code opens files but may not close them anymore: If an exception occurs, that br.close() and bw.close() line will never be executed.
Java has a tool for this: Automatic Resource Management (ARM), also called 'try-with-resources'. Replace this:
BufferedWriter bw = ....;
// do stuff with the writer
bw.close();
with:
try (BufferedWriter bw = ....) {
// do stuff with the writer
}
The {} mark where you use the writer: Java ensures that no matter how you 'exit' out of these {}, the resource WILL be closed. Whether you just get to the end of this block, or you return/break/continue out of it, or an exception leads you out of it, the resource is closed.
Searching for strings
regexps is one way, but if you're looking for a specific exact string that's overkill. Strings have a .contains() method.
New API
There's a new API. The old File API has a nasty tendency to just return false when things can't be done instead of telling you about it like 'normal' java APIs. It's also got more flexibility: It can handle such things as managing file ownership, file creation stamps, access control, and links. It also has the nice property that the default charset encoding, if you don't specify anything, is UTF-8 instead of the dreaded and extremely useless 'platform default'.
Backslashes
Not neccessary, even on windows. path/file.txt works just as well. It reads easier and is far more common.
var
You can use var instead of writing out the type a second time which can come in handy. var x = new Foo(); is the same as Foo x = new Foo().
Putting it all together
public class Change {
public static void main(String[] args) throws Exception {
try (
var bw = Files.newBufferedWriter(Paths.get("path/newfile.txt"));
var br = Files.newBufferedReader(Paths.get("path/file.txt"));
) {
String s;
while ((s = br.readLine()) != null) {
if (s.contains("StringToFind")) {
// or: s.matches("^.*String[a-zA-Z]WithRegexpToFind.*$")
bw.write(s + "\n");
}
}
}
}
}
I made some code that will find the location of a certain string in a .txt file, which I think is what your looking for.
import java.io.*;
import java.util.*;
public class Help {
public static void main(String[] args) throws Exception {
Scanner input = new Scanner(System.in);
// To edit the string your searching for you can get rid input and edit the text variable
String text = input.nextLine();
String line;
BufferedReader br = new BufferedReader(new FileReader("testFile.txt"));
while((line = br.readLine()) != null){
if(line.indexOf(text) != -1){
// enter what you want to do if the string is found here I just put a println statement which you can get rid of
System.out.println("Found");
}else{
// enter what you want to do if the string is not found here I just put a println statement which you can get rid of
System.out.println("Not Found");
}
}
br.close();
}
}
Links: How to locate text in string, How to read and write files in java
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 want to read the last 2 lines in some files, and if the content of second last line matches a specific string, then delete the last line only.
Also, after the above operation, 2 lines of data have to be appended to the end of the modified file. I saw other questions on SO that deal with different parts of my problem, but is there an easy way of doing all of the above with minimal code, preferably in a single function? (I can combine the different functions available at SO but that would be messy...)
I would recommend you to do it "in memory". It's easy to read line by line into a List, check the last lines and update the lines and write it back to the file.
Example:
public static void main(String[] args) throws IOException {
String fileName = "test.txt";
List<String> lines = new ArrayList<String>();
// read the file into lines
BufferedReader r = new BufferedReader(new FileReader(fileName));
String in;
while ((in = r.readLine()) != null)
lines.add(in);
r.close();
// check your condition
String secondFromBottom = lines.get(lines.size() - 2);
if (secondFromBottom.matches("Hello World!")) {
lines.remove(lines.size() - 1);
lines.add("My fixed string");
}
// write it back
PrintWriter w = new PrintWriter(new FileWriter(fileName));
for (String line : lines)
w.println(line);
w.close();
}
Note: No exception handling is done in the example above... you need to handle cases where the file for example doesn't contain two lines and other problems!
If you have really big files and perfomance is an issue the way to go is to use a RandomAccessFile and read backwards looking for the line termination bytes to determine where the last two lines begin. Otherwise use dacwe's approach.
As Gandalf said you can:
take RandomAccessFile,
use method seek(long) to jump forward and read those lines. But you won't know exactly how big the jump should be.
to delete last lines you need the position of begin of last line so before reading each line store their file pointer position (method getFilePointer()). Deleting to that position you use setLength(long).
My example of reading and deleting last lines you have here:
Deleting the last line of a file with Java
Useful can be also:
Quickly read the last line of a text file?
at the moment I have this:
import java.util.*;
import java.io.*;
import java.io.BufferedReader;
import java.io.FileReader;
public class StudentID {
public static void main(String[] args)throws Exception{
System.out.println ("Please enter StudentID: ");
BufferedReader reader = new BufferedReader (new FileReader("CW2_data.csv"));
File file = new File("CW2_data.csv");
try {
BufferedReader r = new BufferedReader(
new InputStreamReader(
new FileInputStream("CW2_data.csv")));
String line;
while((line = r.readLine()) != null)
System.out.println(line);
r.close();
} catch(IOException e) {
System.out.println(" There was an Error Reading the file. " + e.getMessage());
}
}
}
I am trying to get the program to prompt the user for its StudentID, then search through the data file for that StudentId and return their marks for all the modules. Unfortunatly all my codes does is list the whole file back to me.
I tried to add StudetnID=Userinput.readstring; right after so that user was given an opertunity to type in the username but then I realise that wouldn't work unless I tell it scan the whole document for it. I was reading up on maps (as recomendeded by user on here) but I still haven't got to grips with it and I don't know if it would it even work here. The data file is in form of 3 columns and about 282 rows of data, ie
UserID: Module: Mark
ab006, GYH095, 56
Any help would appreciated.
As that this appears to be homework (and how it relates to your previous question) I will not give a full solution.
The buffered reader reads an entire line of text. So you'll get strings similar to this:
"ab006, GYH095, 56"
With that string you can use something like StringTokenizer or String.split to seperate the individual elements, which now become "ab06", "GYH095", "56" ...
The reason this program just writes the entire file back to you is that the program just scans through the file, without doing anything to what it reads.
Well, it is good progress that you are getting the file to be read properly. What you first want to do is get the user's input before reading the file. This can be done with the Java Scanner class. Take a look there for examples on how to use it (you will want to read a String from the user. Hint: the nextLine() method). The rest can be done via stevens explanation.
To load the data, how about you make a simple class that represents a line from your datafile, and then store it in a List. Yes, you'll have to scan through the entire list each time but it doesn't seem that large anyway (if there is a natural key you can use, which appears to be the case, you could indeed use a Map). Check out the java tutorial on collections.