Reading and writing to the same file using try-with-resources - java

I am trying to make a program that receives a specified String, and removes every occurence of this String in a text document. The text file that is used to read / write is the same. The arguments used are received from cmd, in this order:
inputString filename
The program compiles fine, but after running it leaves the original text file blank. If i make a try-catch block for input handling, and a try-catch block for output handling, I am able to read and write to the same file. If i use a try-with-resources block, I am able to read a file, and save the output to a different file than the original, with all occurences of inputString from cmd removed. But it seems like I can't read and write to the same file using try-with-resources, and also the input.hasNext() statement returns false when I try to do it this way.
Code example below:
package ch12;
import java.io.*;
import java.util.*;
public class Chapter_12_E11_RemoveText {
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.out.println("Usage java ch12.Chapter_12_E11_RemoveText inputString filename");
System.exit(1);
}
File filename = new File(args[1]);
if (!filename.exists()) {
System.out.println("Target file " + args[1] + " does not exist");
System.exit(2);
}
try (
Scanner input = new Scanner(filename);
PrintWriter output = new PrintWriter(filename);
) {
System.out.println("hasNext() is " + input.hasNext());
System.out.println("hasNextLine() is " + input.hasNextLine());
while (input.hasNext()) {
String s1 = input.nextLine();
System.out.println("String fetched from input.nextLine() " + s1);
System.out.println("Attemping to replace all words equal to " + args[0] + " with \"\"");
String s2 = s1.replaceAll(args[0], "");
output.println(s2);
}
}
}
}
I am suspecting that when I create a new PrintWriter object with the argument filename, the original file is overwritten by a blank file before the while-loop executes. Am i right here? Is it possible to read and write to the same file using try-with-resources?

From the PrintWriter docs:
If the file exists then it will be truncated to zero size; otherwise, a new file will be created.
So you are correct, by the time you initialize your PrintWriter, your Scanner has nothing to scan.
I would remove the PrintWriter initialization from the resources initialization block, build your file representation in memory, then replace the file contents in another block (or nest it).
That is, if the file has a reasonable size for your memory to handle the replacement.

Related

How to replace specific String in a text file by java?

I'm writing a program with a text file in java, what I need to do is to modify the specific string in the file.
For example, the file has a line(the file contains many lines)like "username,password,e,d,b,c,a"
And I want to modify it to "username,password,f,e,d,b,c"
I have searched much but found nothing. How to deal with that?
In general you can do it in 3 steps:
Read file and store it in String
Change the String as you need (your "username,password..." modification)
Write the String to a file
You can search for instruction of every step at Stackoverflow.
Here is a possible solution working directly on the Stream:
public static void main(String[] args) throws IOException {
String inputFile = "C:\\Users\\geheim\\Desktop\\lines.txt";
String outputFile = "C:\\Users\\geheim\\Desktop\\lines_new.txt";
try (Stream<String> stream = Files.lines(Paths.get(inputFile));
FileOutputStream fop = new FileOutputStream(new File(outputFile))) {
stream.map(line -> line += " manipulate line as required\n").forEach(line -> {
try {
fop.write(line.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
You can try like this:
First, read the file line by line and check each line if the string you want to replace exists in that, replace it, and write the content in another file. Do it until you reach EOF.
import java.io.*;
public class Files {
void replace(String stringToReplace, String replaceWith) throws IOException {
BufferedReader in = new BufferedReader(new FileReader("/home/asn/Desktop/All.txt"));
BufferedWriter out = new BufferedWriter(new FileWriter("/home/asn/Desktop/All-copy.txt"));
String line;
while((line=in.readLine())!=null) {
if (line.contains(stringToReplace))
line = line.replace(stringToReplace, replaceWith);
out.write(line);
out.newLine();
}
in.close();
out.close();
}
public static void main(String[] args) throws IOException {
Files f = new Files();
f.replace("amount", "####");
}
}
If you want to use the same file store the content in a buffer(String array or List) and then write the content of the buffer in the same file.
If your file look similar to this:
username:username123,
password:password123,
After load file to String you can do something like this:
int startPosition = file.indexOf("username") + 8; //+8 is length of username with colon
String username;
for(int i=startPosition; i<file.length(); i++) {
if(file.charAt(i) != ',') {
username += Character.toString(file.charAt(i));
} else {
break;
}
System.out.println(username); //should prong username
}
After edit all thing you want to edit, save edited string to file.
There are much ways to solve this issue. Read String docs to get to know operations on String. Without your code we cannot help you enough aptly.
The algorithm is as follows:
Open a temporary file to save edited copy.
Read input file line by line.
Check if the current line needs to be replaced
Various methods of String class may be used to do this:
equals: Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
equalsIgnoreCase: Compares this String to another String, ignoring case considerations.
contains: Returns true if and only if this string contains the specified sequence of char values.
matches (String regex): Tells whether or not this string matches the given regular expression.
startsWith: Tests if this string starts with the specified prefix (case sensitive).
endsWith: Tests if this string starts with the specified prefix (case sensitive).
There are other predicate functions: contentEquals, regionMatches
If the required condition is true, provide replacement for currentLine:
if (conditionMet) {
currentLine = "Your replacement";
}
Or use String methods replace/replaceFirst/replaceAll to replace the contents at once.
Write the current line to the output file.
Make sure the input and output files are closed when all lines are read from the input file.
Replace the input file with the output file (if needed, for example, if no change occurred, there's no need to replace).

Store array data in a file on Java 9 text output/input

I just started learning how to write into file and read from a file on java oi. Now I can write simple text into a file and also can read it using system.out.print. The problem now is, I tried to create an array and store it in a file using the same way I learnt, but when I run the program the file is created but there was nothing to display. Please is there any thing I can do otherwise, below is the sample of my codes:
public static void main(String[] args) throws FileNotFoundException {
// TODO Auto-generated method stub
File Veggies= new File ("C:\\Users\\user\\Desktop\\My Java Files\\Product.txt");
if(Veggies.exists())
System.exit(0);
PrintWriter output= new PrintWriter(Veggies);
output.println("These are the list of our products.");
String[] VeggiesArray={"Apples","Bananas","Oranges","Avocados","Strawberries"};
for(int i=0;i<=VeggiesArray.length;i++){
output.println("(" + i + ")" +" "+ VeggiesArray[i]);
}
output.close();
}
File veggies= new File (".\\Product.txt");
PrintWriter output= new PrintWriter(veggies);
output.println("These are the list of our products.");
String[] veggiesArray={"Apples","Bananas","Oranges","Avocados","Strawberries"};
for(int i=0;(i<veggiesArray.length);i++) {
output.println("(" + i + ")" +" "+ veggiesArray[i]);
}
output.close();
Got rid of the veggies.Exists() because it would only allow you to generate the file one time, without first deleting it.
Fixed the loop condition as MadProgrammer pointed out.

Try/Catch For File Not Found Exception Nested inside a While Loop

I'm trying to code for a file not found exception in a while loop so that the program continues prompting the user for the file (test.txt). I wrote a try/catch block inside a while loop. However, when I delete the input file (test.txt), the program should catch this error and print "Error, cannot locate the 'test.txt' file, please try again:" and allow the user to input another file name. However, the program crashes and gives me a FileNotFoundException.
In this case it's probably better to ask for permission rather than forgiveness (e.g. check if the file exists before attempting to read it).
File file = new File("test_input.txt");
if (file.exists()) {
FileReader fileReader = new FileReader(file);
}
You should add another try and catch for the Scanner
// prompt user for name for output textfile
System.out.println();
System.out.print("What would you like to call your output file: ");
String outputName = inputReader.nextLine();
// scanner and printwriter objects for reading text file
try {
Scanner in = new Scanner(correctInputfile);
PrintWriter out = new PrintWriter(outputName);
// read input (values) and write the output (average)
// messages triggered by successful location of files.
if (fileName.equalsIgnoreCase(("test_input.txt"))) {
// code logic
}
} catch (FileNotFoundException ex) {
System.out.println();
System.out.println("***** ERROR *****");
System.out.println("\nCannot locate the input file " + "'" + fileName + "'" + "on your computer - please try again.");
System.out.print("\nInput file name (from your computer): ");
}
In your code, two lines raise FileNotFoundExceptions that you are not catching:
// scanner and printwriter objects for reading text file
Scanner in = new Scanner(correctInputfile);
PrintWriter out = new PrintWriter(outputName);
// read input (values) and write the output (average)
You can replace them with the following, and the code (should) work.
Scanner in = null;// Initialize to null, so they don't raise warnings.
PrintWriter out = null;
try { // Surround with try/catch to get the exception
in = new Scanner(correctInputfile);
out = new PrintWriter(outputName);
}catch(FileNotFoundException e){
/*TODO: something about the exception here!
Make sure the Scanner and PrintWriter get
properly initialized with valid file names.*/
}

Code that can read in letters in a .txt file

I am writing a program thats supposed to read a simple text file and output a list of all the letters in that .txt file, ordered with the most frequently used letter to the least frequently used letter.
I have finished coding a working Java program that asks for file name and outputs the text within the file. But I am unsure how to go about outputting a list of the letters. What I am not sure specifically is what methods(if any) within the reader class I could use that reads in each letter in the .txt file. Any help would be appreciated!
This is current code:
// Here I import the Bufered Reader and file reader Libraries
// The Buffered Reader library is similar to Scanner Library and
// is used here to read from a text file. File reader will allow
// the program to access windows file system, get the text file
// and allow the Buufered Reader to read it in.
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Scanner;
public class TextFileReaderApp
{
// I added "throws exception" in case there is an an error in the
// main method, throw an exception, so it can prevent further
// errors from occuring if java doesnt know the main methods going
// to throw an error.
public static void main(String[] args) throws Exception
{
// below I diplay a welcome messgae to the user
System.out.println();
System.out.println("Welcome to the Text File Reader application!");
System.out.println();
// Below I create an instance of the Scanner class to get
// input from the user.
Scanner userInput = new Scanner(System.in);
String selection = "y"; //this is the string variable that's used in
//the while loop to continue the program.
// Below I created a while loop that continues the program if the user
// keeps selecting y as their selecion
while (selection.equalsIgnoreCase("y"))
{
// this line of code is supposed to ask the user for text file name under
// the C:/ directory and must not be hidden in any foler.
System.out.print("Please enter the name of the .txt file: C/");
FileReader file = new FileReader("C:/" + userInput.next());
// file object is used as a parameter in buffered reader.
BufferedReader textReader = new BufferedReader(file);
// below I create and initialize an object of type string called text that will
// store whats inside of the text file.
String text = "";
// I use the readLine statement to read line after line of the text.
// Once it has read everything it will return null.
String lineText = textReader.readLine();
// code below is a test for me to see if the code above works and is able to read
// the text inside the file and output it.
while(lineText != null)
{
// this reads the text line for line and ads it to the text variable for output.
text = text + lineText + "\n";
lineText = textReader.readLine();
}
System.out.println(text);
}
// These 3 code lines ask the user if he/she would like to continue with the program.
System.out.println();
System.out.print("Continue using the Text File Reader? (y/n): ");
choice = user_input.next();
System.out.println();
}
}
If you need to count letters / characters you can do it just as well on lines / words etc. No need to involve the Reader here.
for (char c : someString.toCharArray ()) {
// handle the character
}
Should work once you have any String from your file.
This reads all characters from textReader until EOF is reached or an exception occurs.
try {
for(int i = textReader.read(); i != -1 /* EOF */; i = textReader.read()) {
char c = (char) i;
// do whatever you want with your char here
}
} catch(IOException)
textReader.close();
first of all you might want to use a StringBuilder instead of your String text because of alot better performance.
"text = text + lineText" will create another String object every time it is executed, StringBuilder works better in this case).
One way to achieve what you want is to read character for character of your textLine and use a switchcase block with all letters and add them to an array containing integers when they occur. Example:
int[] array = new int[26];
switch(character){
case "a":
array[0] += 1;
break;
case "b":
array[1] += 1;
break;
//....
}
and so on...
in the end you use a simple for loop and print the values of your array. Now you see how many times you have entered which character.

Writing to a new line in a .csv file without overwriting the first line

I'm trying to make it so whenever a user inputs a name and pass it will write that information(in the format of name,pass) to a .csv file specified by the location. However whenever I run the program, it keeps overwriting the first line. I tried adding "\n" and out.newLine(); but for some reason it doesn't write to the next line. I have no idea why it does this so I was hoping if someone knows why.
public class TestClass {
public static void main(String[] args) throws IOException {
String location = "my location to the file (.csv)";
Scanner sc = new Scanner(System.in);
System.out.print("Name: ");
String name = sc.next();
System.out.print("Pass: ");
String pass = sc.next();
BufferedWriter out = new BufferedWriter(new FileWriter(location));
out.write(name + "," + pass + "\n");
out.newLine();
out.close();
}
}
Currently in the file I have this:
test, one
and when I ran the program:
name: one
pass: two
exited the program and checked the file and the first line was replaced with one,two instead of making it like this:
test, one
one, two
Thank you for those who help :)
Use the second constructor of FileWriter:
FileWriter(String fileName, boolean append)
fileName - String The system-dependent filename.
append - boolean if true, then data will be written to the end of the file rather than the beginning.
BufferedWriter out = new BufferedWriter(new FileWriter(location, true));

Categories

Resources