Search and Replace a content in a file in JAVA - 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.

Related

Issues with FileReader and Java GUI/jForm

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"))

Find words in a text file and save them to a new file using Java

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

How to write test case readFile method which return type is void

I am new in writing test cases, Please help me for writing test case for below methods . Thanks in advance!!
public void readFile() throws IOException{
linesProcessed = 0;
FileInputStream fileInStream = new FileInputStream(filePath);
DataInputStream dataInStream = new DataInputStream(fileInStream);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(dataInStream));
String strLine;
fileData.clear();
while(StringUtils.isNotBlank((strLine = bufferedReader.readLine()))) {
++linesProcessed;
processLine(strLine);
}
bufferedReader.close();
dataInStream.close();
fileInStream.close();
}
Many things to say here.
First of all, to answer your question. When a method doesn't return something, you can still can check whether some "other state" gets updated accordingly.
In your case, one meaningful point of observation could be that call
processLine(strLine);
In other words: you could see what that method is doing, and somehow verify that the other method was called as you would expect it.
Then: you actually wrote hard-to-test code. One reason for that is because this method starts its work on a string (that points to a file). Instead, you could pass a reader object to that method already. Then there wouldn't be a need to use PowerMock for example. You simply prepare a reader object that has known content, and then you can verify that actions follow that match that prepared content!
Beyond that, you should learn about try-with-resources, and you should also study more how to do IO. There is no point in closing all 3 streams. When you create a reader on some other stream, and you close the outer reader, that "base" stream gets closed automatically along the way.

File contents getting deleted after reading it using FilerReader Java

Recently I am doing a code review, the code is like this:
File j = new File(aFile);
System.out.println(j.length());
BufferedReader fileReader = new BufferedReader(new FileReader(j));
BufferedWriter fileWriter = new BufferedWriter(new FileWriter(aFile.getPath());
System.out.println(j.length());
I have two questions:
Is j a duplicate of aFile, because I have seen other huge methods for copying files, like here.
The first System.out.println() prints 32 and the second, after creating a file reader, prints 0. So, why are the contents getting deleted? Could someone explain what's happening here?
I put those System.out.println() statements to check if the file is empty or not.
Solution:
After Reading through the answers, I think I found what's wrong with the code. If j is just a reference, then the fileWriter is trying to write into the same file and it is cyclic. Am I right here?
EDIT: This is not a duplicate of suggested question, as the whole confusion was thinking that the j is clone or duplicate of aFile.
You're not showing us everything, are you?
The presented code definitely does not change or delete the file, as is already indicated by the names of the classes you are using: BufferedReader, FileReader (note Reader in both).
I thought there might be a slim chance that some operating systems would lock the file once you create the Readers, hence not even allowing a File object to read the length() property anymore. However, I couldn't find that documented or reported anywhere, so I highly doubt it.
I ran the following code, where test is a plain text file containing 0123456789 (length 10):
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class StackOverflow {
public static void main(String[] args) {
File f = new File("test");
System.out.println("Length before: " + f.length());
try {
BufferedReader fileReader = new BufferedReader(new FileReader(f));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("Length after: " + f.length());
}
}
Result:
Length before: 10
Length after: 10
Hence, I suspect the issue lies elsewhere.
EDIT:
Now that OP updated the question, we finally have the relevant line:
BufferedWriter fileWriter = new BufferedWriter(new FileWriter(aFile.getPath());
That's why the file is empty and its length 0. FileWriter will open the file for writing and overwrite the existing contents, if any. You can prevent this by passing in a second parameter, making use of another constructor of FileWriter, one that accepts an append flag:
public FileWriter(String fileName, boolean append) throws IOException
public FileWriter(File file, boolean append) throws IOException
Constructs a FileWriter object given a File object/name. If the second argument is true, then bytes will be written to the end of the file rather than the beginning.
In other words, if you don't want the contents to be overridden, change your above line to:
BufferedWriter fileWriter = new BufferedWriter(new FileWriter(aFile.getPath(), true);
1) j is not a duplicate, it is a reference to a new file object that wraps the actual file.
2) There is no way this code should delete (or even change) the file. Is there any more code?
1) Is j a duplicate of aFile, because I have seen other huge methods for copying files, like here and here.
It is a File object constructed from aFile, whatever that may be. This process has nothing whatsoever to do with copying files, whether huge or hugely or otherwise. File just wraps a file name. Not its contents. Your first link has nothing to do with copying files either.
2) The first result prints 32 and the second result after creating a file reader prints 0. So, why are the contents getting deleted?
Obviously this is not the real code. The real test is whether fileReader.read() immediately returns -1.

How do I read a file again using buffered reader in Java?

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());
}
}

Categories