Replace string in text file using Java - java

I have a text file (file.txt) which contains multiple lines:
/location/test/file.csv
/location/test1/file2.csv
/location/test2/file.exe
Using ECMA, I would like to replace all instance of "/" with "\". However, the code below only replaces the first line and eliminate lines 2 and 3.
This is the result of the file.txt file after I run the code (as I said, lines 2 and 3 are missing):
\location\test\file.csv
Can anyone please help?
function ReadFile ()
{
var file = new java.io.BufferedReader(new java.io.FileReader("C:\\Test\\file.txt"));
var fileWriter = new java.io.FileWriter("C:\\Test\\file.txt",false);
while ((line = file.readLine()) != null)
{
println(line);
if (line.contains ("/"))
line = line.replace("/","\\");
fileWriter.write(line);
fileWriter.close();
}
}
ReadFile ();

So I managed to run this code using Rhino. It does in fact run. I made some changes to filenames in order to get it running on my mac, but it is essentially the same code:
function ReadFile () {
var file = new java.io.BufferedReader(new java.io.FileReader("file"));
var fileWriter = new java.io.FileWriter("file2",false);
while ((line = file.readLine()) != null) {
if (line.contains ("/"))
line = line.replace("/","\\");
fileWriter.write(line + "\n");
}
fileWriter.close();
file.close();
}
ReadFile ();
So the bugs you had were:
Reading and writing to the same file. This is awkward using streams. Basically, don't do it. I changed it to write to file2.
Closing the writer inside your reader loop. Close the writer at the end, once closed, you can no longer write to it.
Not closing the file you are reading from.
For those interested in how I got this running, on OS X, using rhino:
brew install rhino
rhino example.js
I had to remove the println because that wasn't recognised but that wasn't a critical part. JS on the JVM. Fun! Except nothing is async.....
There are other JS engines too, but rhino worked.

JavaScript String object has a replace method that takes a regular expression that can replace characters in a String. However, the Java in your JavaScript won't work because you are mixing up two languages.
http://www.w3schools.com/jsref/jsref_replace.asp

The problem is that you're writing over the file as you're reading it, so as soon as your first write(line) completes, the file no longer has the next two lines. Either use a second, temporary file to write to until you've finished processing the file, or keep a list/array of all the new lines in memory, and then write out the file at the end.
I'm really curious to know, though, how you managed to get your current program to even run. In my experience, Java and ECMA/Javascript are two completely separate languages, but it looks like you're using javascript code against Java libraries. What's up with that?

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 use input from a java code and transfer it into an external application (as well as retrieving output)?

I'm actually not that great and am relatively new at Java. I wish to receive input from the user, and want to input this data into an external application.
This application processes the data and provides an output. I wish to retrieve this output using the Java code.
I have attempted in doing this but, I haven't got the slightest idea on how to start this script.
Nothin' on the internet seems to answer this question. If you have any idea or any new functions that can be useful, please help me in doing so.
Since I'm starting from ground zero, any help is appreciated.
Thanks so much.
To communicate with an external application you need to first define the communication way. For example:
Will this application read the output from a file?
If that statement it's true, then you need to learn serialization:
Will this application read the input from the standard output (like a command-line application)
If that statement it's true then you need to send with System.out.print().
Will this application get the data over HTTP.
Then you need to learn about REST and or RPC architectures.
Assuming that it will be a command-line application, then you could use something like this:
public class App
{
public static void main(String... args)
{
// You need to implement your business logic here. Not just print whatever the user passes as arguments of the command-line.
for(String arg : args)
{
System.out.print(arg);
}
}
}
There's a lot going on here but I'll suggest an example for each part of this question and assume this is just going to be written in Java, and suggesting an iterative design/development approach.
receive input from the user::getting arguments from the command line can work, but I think most users want to use familiar user interfaces like excel to input large amounts of data. Have them export files to .csv or look into reading excel files directly with apache poi. The latter is not for beginners, but not terrible to figure out or find examples. The former should be easy to figure out if you look into reading files and splitting them line by line on the delimiter. Here's an example of that:
try (BufferedReader reader = new BufferedReader(new FileReader(new File("user_input.csv"))) {
String currentLine = reader.readLine();
while (currentLine != null) {
String splitLine[] = currentLine.split(","); //choose delimiter here
//process cells as needed
//write output somewhere so other program can read it later
currentLine = reader.readLine();
}
}
catch (IOException ex) {
System.out.println(ex.getMessage()); //maybe write to an error log
System.exit(1);
}
"input" data to other app::you can use pipes if you're at the command line. but I'd recommend you write to a file and have the other app read it. here's an expansion of the previous code snippet showing how to write to a file as that might be more practical and easier to log/archive/debug.
try (BufferedReader reader = new BufferedReader(new FileReader(new File("user_input.csv")));
BufferedWriter writer = new BufferedWriter(new FileWriter(new File("process_me.csv")))) {
String currentLine = reader.readLine();
while (currentLine != null) {
String splitLine[] = currentLine.split(","); //choose delimiter here
//process cells as needed
writer.write(processed_stuff);
currentLine = reader.readLine();
}
}
catch (IOException ex) {
System.err.println(ex.getMessage());
System.exit(1);
}
Then retrieving output::can just be reading another file with another Java program. This way you're communicating between programs using the file system. You must agree upon file formats and directories though. And you'll be limited to having both programs on the same server.
To make this at scale, you could use web services assuming the other program you're making requests to is a web service or has one wrapped around it. You can send your file and receive some response using URLConnection. This is where things will get much more complex, but now everything in your new program is just one Java program and the other code can live on another server.
Building the app first with those "intermediate" files between the user input code, the external code, and the final code will help you focus on perfecting the business logic, then you can worry about just communication over the network.

Iterate through a log file in Java. Pull files scanned

I currently have a log file(see bellow) that I need to iterate through and pull out a list of files that were scanned. Then by using that list of files copy the scanned files into a different directory.
So in this case, it would go through and pull
c:\tools\baregrep.exe
c:\tools\baretail.exe
etc etc
and then move them to a folder, say c:\folder\SafeFolder with the same file structure
I wish I had a sample of what the output was on a failed scan, but this will get me a good head start and I can probably figure the rest out
Symantec Image of Log File
Thanks in advanced, I really appreciate any help that you can lend me.
This question is tagged as Java, and as much as I love Java, this problem is something that would be easier and quicker to solve in a language such as Perl (so if you only want the end result and do not need to run in a particular environment then you may wish to use a scripting language instead).
Not a working implementation, but code along the lines of the below is all it would take in perl: (Syntax untested and likely broken as is, only serves as a guideline.. been awhile since I wrote any perl).
use File::Copy;
my $outdir = "c:/out/";
while(<>)
{
my ($path) = /Processing File\s+\'([^\']+)\'/;
my ($file) = $path =~ /(.*\\)+([^\\]+)/;
if (($file) && (-e $path))
{
copy($path,$outdir . $file);
}
}
This should do the trick. Now, just adapt for your solution!
public static void find(String logPath, String safeFolder) throws FileNotFoundException, IOException {
ArrayList<File> files = new ArrayList<File>();
BufferedReader br = new BufferedReader(new FileReader(logPath));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
Pattern pattern = Pattern.compile("'[a-zA-Z]:\\\\.+?'");
Matcher matcher = pattern.matcher(line);
if (matcher.matches()) {
}
if (matcher.find()) {
files.add(new File(matcher.group()));
System.out.println("Got a new file! " + files.get(files.size() - 1));
}
}
for (File f : files) {
// Make sure we get a file indeed
if (f.exists()) {
if (!f.renameTo(new File(safeFolder, f.getName()))) {
System.err.println("Unable to move file! " + f);
}
} else {
System.out.println("I got a wrong file! " + f);
}
}
}
Its straight forward.
Read the Log file line by line using NEW_LINE as your deliminator. If this is a small file, feel free to load it & process it via String.split("\n") or StringTokenizer
As you loop each line, you need to do a simple test to detect if that string contains 'Processing File '.
If it does, using Regular Expression (harder) or simple parsing to capture the file names. It should be within the ['], so detect the first occurrence of ['], and detect the second, and get the string in between.
If your string is valid (you may test using java.io.File) or existing, you could copy the file name to another file. I would not advise you against copying it in java for memory restrictions for starters.
Instead, copy the string of files to form a batch file to copy them at once using the OS Script like Windows BAT or Bash Script, eg cp 'filename_from' 'copy_to_dir'
Let me know of you need a working example
regards

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

Categories