Modify a .Txt File in Java

Modify a .txt file in Java

I haven't done this in Java recently, but writing an entire file into memory seems like a bad idea.

The best idea that I can come up with is open a temporary file in writing mode at the same time, and for each line, read it, modify if necessary, then write into the temporary file. At the end, delete the original and rename the temporary file.

If you have modify permissions on the file system, you probably also have deleting and renaming permissions.

Creating, writing and editing same text file in java

Change your code to that:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class EditFile {

public static void main(String[] args) {

try{
String verify, putData;
File file = new File("file.txt");
file.createNewFile();
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);
bw.write("Some text here for a reason");
bw.flush();
bw.close();
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);

while( (verify=br.readLine()) != null ){ //***editted
//**deleted**verify = br.readLine();**
if(verify != null){ //***edited
putData = verify.replaceAll("here", "there");
bw.write(putData);
}
}
br.close();

}catch(IOException e){
e.printStackTrace();
}
}

}

The Problem is that you are calling br.readLine() twice which is provoking the application to read line1 and then line2 and in your case you have just one line which means that your program read it in the conditional form and when it comes to declaring it to the variable verify, it is stopping because you don't have anymore data to read your file.

Modify contents of text file and write to new file in java

The String variable b is overwriten in each iteration of the loop. You want to append to it instead of overwriting (you may also want to add a newline character at the end):

b += (n + ". " + s + System.getProperty("line.separator"));

Better yet, use a StringBuilder to append the output:

StringBuilder b = new StringBuilder();
int n = 0;
while (file.hasNext()) {
s = file.nextLine();
n++;
System.out.println(n + ". " + s);
b.append(n).append(". ").append(s).append(System.getProperty("line.separator"));
}// end while
PrintWriter printer = new PrintWriter(output);
printer.println(b.toString());

How can I update specific parts of a text file in java?

If you are allowed for this project (i.e., not a school assignment), I recommend using JSON, YAML, or XML. There are too many Java libraries to recommend for using these types of files, but you can search "Java JSON library" for example.

First, need to address some issues...

It's not good practice to put Scanner scan = new Scanner(System.in); in a try-with-resource. It will auto-close System.in and won't be useable after being used in your Reader class. Instead, just do this:

Scanner scan = new Scanner(System.in);
Reader reader = new Reader(scan, path, fileWriter, fileReader);

Or, even better, don't pass it to the constructor, but just set scan to it in the constructor as this.scan = new Scanner(System.in);

Next, for fileReader, you can just initialize it similarly as you did for fileWriter:

BufferedReader fileReader = Files.newBufferedReader(path, StandardCharsets.UTF_8);

Next, this line:

BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)

Every time this program is run, this line will overwrite the file to empty, which is probably not what you want. You could add StandardOpenOption.APPEND, but then this means you'll only write to the end of the file.

When you update data, you also have the issue that you'll need to "push" down all of the data that comes after it. For example:

Bobby 1 2 3 4 5
Fred 1 2 3 4 5

If you change the name Bobby to something longer like Mr. President, then it will overwrite the data after it.

While there are different options, the best and simplest is to just read the entire file and store each bit of data in a class (name, scores, etc.) and then close the fileReader.

Then when a user updates some data, change that data (instance variables) in the class and then write all of that data to the file.

Here's some pseudo-code:

class MyProg {
// This could be a Map/HashMap instead.
// See updateData().
public List<Player> players = new ArrayList<>();

public void readData(String filename) throws IOException {
Path path = Paths.get(filename);

try(BufferedReader fileReader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
// Read each Player (using specific format)
// and store in this.players
}
}

public void writeData(String filename) throws IOException {
Path path = Paths.get(filename);

try(BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
// Write each Player from this.players in specific format
}
}

public void updateData() {
// 1. Find user-requested Player from this.players
// 2. Update that specific Player class
// 3. Call writeData()

// If you are familiar with Maps, then it would be faster
// to use a Map/HashMap with the key being the player's name.
}
}

class Player {
public String name;
public int games;
public int goals;
//...
}

How to edit a .txt file in Java

To create a new text file

FileOutputStream object=new FileOutputStream("a.txt",true);
object.write(byte[]);
object.close();

This will create a file if not available and if a file is already available it will append data to it.

What is the simplest way to open, modify and read the changes on a .txt file in Java?

In your context:

Path path = Paths.get("... .txt");
List<String> = Files.readAllLines(path, StandardCharsets.UTF_8);
user = lines.get(0);
password = lines.get(1);
code = lines.get(2);

List<String> lines = new LinkedList<>();
Collections.addAll(lines, user, password, code);
Files.write(path, lines, StandardCharsets.UTF_8);

You could also use .properties with key=value pairs, with a variant in XML form.

If you think of later changing your software with a new format, maybe a version number in the data would be nice too.

Modifying existing file content in Java

As proposed in the accepted answer to a similar question:

open a temporary file in writing mode at the same time, and for each line, read it, modify if necessary, then write into the temporary file. At the end, delete the original and rename the temporary file.

Based on your implementation, something similar to:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class ReplaceFileContents {
public static void main(String[] args) {
new ReplaceFileContents().replace();
}

public void replace() {
String oldFileName = "try.dat";
String tmpFileName = "tmp_try.dat";

BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(oldFileName));
bw = new BufferedWriter(new FileWriter(tmpFileName));
String line;
while ((line = br.readLine()) != null) {
if (line.contains("1313131"))
line = line.replace("1313131", ""+System.currentTimeMillis());
bw.write(line+"\n");
}
} catch (Exception e) {
return;
} finally {
try {
if(br != null)
br.close();
} catch (IOException e) {
//
}
try {
if(bw != null)
bw.close();
} catch (IOException e) {
//
}
}
// Once everything is complete, delete old file..
File oldFile = new File(oldFileName);
oldFile.delete();

// And rename tmp file's name to old file name
File newFile = new File(tmpFileName);
newFile.renameTo(oldFile);

}
}

Modify existing line in file - Java

Here is a way to do it, try it. In this example the file is C:/user.txt and i change the value of George by 1234

public class George {
private static List<String> lines;

public static void main (String [] args) throws IOException{
File f = new File("C:/user.txt");
lines = Files.readAllLines(f.toPath(),Charset.defaultCharset());
changeValueOf("Georges", 1234); // the name and the value you want to modify
Files.write(f.toPath(), changeValueOf("George", 1234), Charset.defaultCharset());
}

private static List<String> changeValueOf(String username, int newVal){
List<String> newLines = new ArrayList<String>();
for(String line: lines){
if(line.contains(username)){
String [] vals = line.split(": ");
newLines.add(vals[0]+": "+String.valueOf(newVal));
}else{
newLines.add(line);
}

}
return newLines;
}
}

This is a working solution, but i think there is some other way more efficient.

How do I edit multiple .txt files in Java

Start by taking a look at Passing Information to a Method or a Constructor

What you want to (try and do) is to make the core functionality "common". Let's face it, reading and writing the student data is basically the same for all the students, the only difference is, the source and destination.

To this end, I'd start with a POJO (plain old Java object), for example...

public class Student {

private String name;
private String id;
private int q1Score;
private int q2Score;
private int q3Score;
private int midTermScore;
private int finalScore;

public Student(String name, String id, int q1Score, int q2Score, int q3Score, int midTermScore, int finalScore) {
this.name = name;
this.id = id;
this.q1Score = q1Score;
this.q2Score = q2Score;
this.q3Score = q3Score;
this.midTermScore = midTermScore;
this.finalScore = finalScore;
}

public static Student loadByName(String name) throws IOException {
File file = new File(name + ".txt");
if (!file.exists()) {
throw new FileNotFoundException("No record exists for " + name);
}

try (Scanner input = new Scanner(file)) {
input.useDelimiter(",");
name = input.next();
String id = input.next();
int q1Score = input.nextInt();
int q2Score = input.nextInt();
int q3Score = input.nextInt();
int midTermScore = input.nextInt();
int finalScore = input.nextInt();

return new Student(name, id, q1Score, q2Score, q3Score, midTermScore, finalScore);
}
}

public void save() throws IOException {
File file = new File(getName() + ".txt");
StringJoiner joiner = new StringJoiner(",");
joiner.add(getName());
joiner.add(getId());
joiner.add(Integer.toString(getQ1Score()));
joiner.add(Integer.toString(getQ2Score()));
joiner.add(Integer.toString(getQ3Score()));
joiner.add(Integer.toString(getMidTermScore()));
joiner.add(Integer.toString(getFinalScore()));

try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(joiner.toString());
}
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public int getQ1Score() {
return q1Score;
}

public void setQ1Score(int q1Score) {
this.q1Score = q1Score;
}

public int getQ2Score() {
return q2Score;
}

public void setQ2Score(int q2Score) {
this.q2Score = q2Score;
}

public int getQ3Score() {
return q3Score;
}

public void setQ3Score(int q3Score) {
this.q3Score = q3Score;
}

public int getMidTermScore() {
return midTermScore;
}

public void setMidTermScore(int midTermScore) {
this.midTermScore = midTermScore;
}

public int getFinalScore() {
return finalScore;
}

public void setFinalScore(int finalScore) {
this.finalScore = finalScore;
}

}

nb: You could just use an array, but where's the fun in that

So, the above is just a container for the data we want to manage. It provides two convince methods for reading and writing the student information, so we don't "repeat" code and introduce possible bugs or maintenance issues along the way (there's only one place we read or write the data)

Next, any methods which need to interact with the student needs to accept an instance of the Student POJO, for example...

protected void editStuGrade(Student student) throws IOException {
//...
}

Then the rest of the code simply comes down to getting information from the user and feeding it into our workflow...

public class Main {

private Scanner command = new Scanner(System.in);

public static void main(String[] args) throws Exception {
new Main();
}

public Main() {
System.out.println("Enter a students name: ");
String commandInput = command.next();
try {
Student student = Student.loadByName(commandInput);
editStuGrade(student);
} catch (IOException ex) {
System.out.println("Could not read student record: " + ex.getMessage());
}
}

protected void editStuGrade(Student student) throws IOException {
System.out.println("Would you like to edit or quit (edit | quit)?");
String editInput = command.next();
if (editInput.equalsIgnoreCase("edit")) {
// Make some changes...
student.save();
} else if (editInput.equalsIgnoreCase("quit")) {
System.exit(0);
}

}
}

Runnable example...

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
import java.util.StringJoiner;

public class Main {

private Scanner command = new Scanner(System.in);

public static void main(String[] args) throws Exception {
new Main();
}

public Main() {
System.out.println("Enter a students name: ");
String commandInput = command.next();
try {
Student student = Student.loadByName(commandInput);
editStuGrade(student);
} catch (IOException ex) {
System.out.println("Could not read student record: " + ex.getMessage());
}
}

protected void editStuGrade(Student student) throws IOException {
System.out.println("Would you like to edit or quit (edit | quit)?");
String editInput = command.next();
if (editInput.equalsIgnoreCase("edit")) {
// Make some changes...
student.save();
} else if (editInput.equalsIgnoreCase("quit")) {
System.exit(0);
}

}

public static class Student {

private String name;
private String id;
private int q1Score;
private int q2Score;
private int q3Score;
private int midTermScore;
private int finalScore;

public Student(String name, String id, int q1Score, int q2Score, int q3Score, int midTermScore, int finalScore) {
this.name = name;
this.id = id;
this.q1Score = q1Score;
this.q2Score = q2Score;
this.q3Score = q3Score;
this.midTermScore = midTermScore;
this.finalScore = finalScore;
}

public static Student loadByName(String name) throws IOException {
File file = new File(name + ".txt");
if (!file.exists()) {
throw new FileNotFoundException("No record exists for " + name);
}

try (Scanner input = new Scanner(file)) {
input.useDelimiter(",");
name = input.next();
String id = input.next();
int q1Score = input.nextInt();
int q2Score = input.nextInt();
int q3Score = input.nextInt();
int midTermScore = input.nextInt();
int finalScore = input.nextInt();

return new Student(name, id, q1Score, q2Score, q3Score, midTermScore, finalScore);
}
}

public void save() throws IOException {
File file = new File(getName() + ".txt");
StringJoiner joiner = new StringJoiner(",");
joiner.add(getName());
joiner.add(getId());
joiner.add(Integer.toString(getQ1Score()));
joiner.add(Integer.toString(getQ2Score()));
joiner.add(Integer.toString(getQ3Score()));
joiner.add(Integer.toString(getMidTermScore()));
joiner.add(Integer.toString(getFinalScore()));

try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(joiner.toString());
}
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public int getQ1Score() {
return q1Score;
}

public void setQ1Score(int q1Score) {
this.q1Score = q1Score;
}

public int getQ2Score() {
return q2Score;
}

public void setQ2Score(int q2Score) {
this.q2Score = q2Score;
}

public int getQ3Score() {
return q3Score;
}

public void setQ3Score(int q3Score) {
this.q3Score = q3Score;
}

public int getMidTermScore() {
return midTermScore;
}

public void setMidTermScore(int midTermScore) {
this.midTermScore = midTermScore;
}

public int getFinalScore() {
return finalScore;
}

public void setFinalScore(int finalScore) {
this.finalScore = finalScore;
}

}
}


Related Topics



Leave a reply



Submit