How do I replace a line of text found within a text file?
I have a string such as:
Do the dishes0
And I want to update it with:
Do the dishes1
(and vise versa)
How do I accomplish this?
ActionListener al = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JCheckBox checkbox = (JCheckBox) e.getSource();
if (checkbox.isSelected()) {
System.out.println("Selected");
String s = checkbox.getText();
replaceSelected(s, "1");
} else {
System.out.println("Deselected");
String s = checkbox.getText();
replaceSelected(s, "0");
}
}
};
public static void replaceSelected(String replaceWith, String type) {
}
By the way, I want to replace ONLY the line that was read. NOT the entire file.
At the bottom, I have a general solution to replace lines in a file. But first, here is the answer to the specific question at hand. Helper function:
public static void replaceSelected(String replaceWith, String type) {
try {
// input the file content to the StringBuffer "input"
BufferedReader file = new BufferedReader(new FileReader("notes.txt"));
StringBuffer inputBuffer = new StringBuffer();
String line;
while ((line = file.readLine()) != null) {
inputBuffer.append(line);
inputBuffer.append('\n');
}
file.close();
String inputStr = inputBuffer.toString();
System.out.println(inputStr); // display the original file for debugging
// logic to replace lines in the string (could use regex here to be generic)
if (type.equals("0")) {
inputStr = inputStr.replace(replaceWith + "1", replaceWith + "0");
} else if (type.equals("1")) {
inputStr = inputStr.replace(replaceWith + "0", replaceWith + "1");
}
// display the new file for debugging
System.out.println("----------------------------------\n" + inputStr);
// write the new string with the replaced line OVER the same file
FileOutputStream fileOut = new FileOutputStream("notes.txt");
fileOut.write(inputStr.getBytes());
fileOut.close();
} catch (Exception e) {
System.out.println("Problem reading file.");
}
}
Then call it:
public static void main(String[] args) {
replaceSelected("Do the dishes", "1");
}
Original Text File Content:
Do the dishes0
Feed the dog0
Cleaned my room1
Output:
Do the dishes0
Feed the dog0
Cleaned my room1
----------------------------------
Do the dishes1
Feed the dog0
Cleaned my room1
New text file content:
Do the dishes1
Feed the dog0
Cleaned my room1
And as a note, if the text file was:
Do the dishes1
Feed the dog0
Cleaned my room1
and you used the method replaceSelected("Do the dishes", "1");,
it would just not change the file.
Since this question is pretty specific, I'll add a more general solution here for future readers (based on the title).
// read file one line at a time
// replace line as you read the file and store updated lines in StringBuffer
// overwrite the file with the new lines
public static void replaceLines() {
try {
// input the (modified) file content to the StringBuffer "input"
BufferedReader file = new BufferedReader(new FileReader("notes.txt"));
StringBuffer inputBuffer = new StringBuffer();
String line;
while ((line = file.readLine()) != null) {
line = ... // replace the line here
inputBuffer.append(line);
inputBuffer.append('\n');
}
file.close();
// write the new string with the replaced line OVER the same file
FileOutputStream fileOut = new FileOutputStream("notes.txt");
fileOut.write(inputBuffer.toString().getBytes());
fileOut.close();
} catch (Exception e) {
System.out.println("Problem reading file.");
}
}
Since Java 7 this is very easy and intuitive to do.
List<String> fileContent = new ArrayList<>(Files.readAllLines(FILE_PATH, StandardCharsets.UTF_8));
for (int i = 0; i < fileContent.size(); i++) {
if (fileContent.get(i).equals("old line")) {
fileContent.set(i, "new line");
break;
}
}
Files.write(FILE_PATH, fileContent, StandardCharsets.UTF_8);
Basically you read the whole file to a List, edit the list and finally write the list back to file.
FILE_PATH represents the Path of the file.
If replacement is of different length:
Read file until you find the string you want to replace.
Read into memory the part after text you want to replace, all of it.
Truncate the file at start of the part you want to replace.
Write replacement.
Write rest of the file from step 2.
If replacement is of same length:
Read file until you find the string you want to replace.
Set file position to start of the part you want to replace.
Write replacement, overwriting part of file.
This is the best you can get, with constraints of your question. However, at least the example in question is replacing string of same length, So the second way should work.
Also be aware: Java strings are Unicode text, while text files are bytes with some encoding. If encoding is UTF8, and your text is not Latin1 (or plain 7-bit ASCII), you have to check length of encoded byte array, not length of Java string.
I was going to answer this question. Then I saw it get marked as a duplicate of this question, after I'd written the code, so I am going to post my solution here.
Keeping in mind that you have to re-write the text file. First I read the entire file, and store it in a string. Then I store each line as a index of a string array, ex line one = array index 0. I then edit the index corresponding to the line that you wish to edit. Once this is done I concatenate all the strings in the array into a single string. Then I write the new string into the file, which writes over the old content. Don't worry about losing your old content as it has been written again with the edit. below is the code I used.
public class App {
public static void main(String[] args) {
String file = "file.txt";
String newLineContent = "Hello my name is bob";
int lineToBeEdited = 3;
ChangeLineInFile changeFile = new ChangeLineInFile();
changeFile.changeALineInATextFile(file, newLineContent, lineToBeEdited);
}
}
And the class.
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
public class ChangeLineInFile {
public void changeALineInATextFile(String fileName, String newLine, int lineNumber) {
String content = new String();
String editedContent = new String();
content = readFile(fileName);
editedContent = editLineInContent(content, newLine, lineNumber);
writeToFile(fileName, editedContent);
}
private static int numberOfLinesInFile(String content) {
int numberOfLines = 0;
int index = 0;
int lastIndex = 0;
lastIndex = content.length() - 1;
while (true) {
if (content.charAt(index) == '\n') {
numberOfLines++;
}
if (index == lastIndex) {
numberOfLines = numberOfLines + 1;
break;
}
index++;
}
return numberOfLines;
}
private static String[] turnFileIntoArrayOfStrings(String content, int lines) {
String[] array = new String[lines];
int index = 0;
int tempInt = 0;
int startIndext = 0;
int lastIndex = content.length() - 1;
while (true) {
if (content.charAt(index) == '\n') {
tempInt++;
String temp2 = new String();
for (int i = 0; i < index - startIndext; i++) {
temp2 += content.charAt(startIndext + i);
}
startIndext = index;
array[tempInt - 1] = temp2;
}
if (index == lastIndex) {
tempInt++;
String temp2 = new String();
for (int i = 0; i < index - startIndext + 1; i++) {
temp2 += content.charAt(startIndext + i);
}
array[tempInt - 1] = temp2;
break;
}
index++;
}
return array;
}
private static String editLineInContent(String content, String newLine, int line) {
int lineNumber = 0;
lineNumber = numberOfLinesInFile(content);
String[] lines = new String[lineNumber];
lines = turnFileIntoArrayOfStrings(content, lineNumber);
if (line != 1) {
lines[line - 1] = "\n" + newLine;
} else {
lines[line - 1] = newLine;
}
content = new String();
for (int i = 0; i < lineNumber; i++) {
content += lines[i];
}
return content;
}
private static void writeToFile(String file, String content) {
try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8"))) {
writer.write(content);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static String readFile(String filename) {
String content = null;
File file = new File(filename);
FileReader reader = null;
try {
reader = new FileReader(file);
char[] chars = new char[(int) file.length()];
reader.read(chars);
content = new String(chars);
reader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return content;
}
}
Sharing the experience with Java Util Stream
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public static void replaceLine(String filePath, String originalLineText, String newLineText) {
Path path = Paths.get(filePath);
// Get all the lines
try (Stream<String> stream = Files.lines(path, StandardCharsets.UTF_8)) {
// Do the line replace
List<String> list = stream.map(line -> line.equals(originalLineText) ? newLineText : line)
.collect(Collectors.toList());
// Write the content back
Files.write(path, list, StandardCharsets.UTF_8);
} catch (IOException e) {
LOG.error("IOException for : " + path, e);
e.printStackTrace();
}
}
Usage
replaceLine("test.txt", "Do the dishes0", "Do the dishes1");
//Read the file data
BufferedReader file = new BufferedReader(new FileReader(filepath));
StringBuffer inputBuffer = new StringBuffer();
String line;
while ((line = file.readLine()) != null) {
inputBuffer.append(line);
inputBuffer.append('\n');
}
file.close();
String inputStr = inputBuffer.toString();
// logic to replace lines in the string (could use regex here to be generic)
inputStr = inputStr.replace(str, " ");
//'str' is the string need to update in this case it is updating with nothing
// write the new string with the replaced line OVER the same file
FileOutputStream fileOut = new FileOutputStream(filer);
fileOut.write(inputStr.getBytes());
fileOut.close();
Well you would need to get a file with JFileChooser and then read through the lines of the file using a scanner and the hasNext() function
http://docs.oracle.com/javase/7/docs/api/javax/swing/JFileChooser.html
once you do that you can save the line into a variable and manipulate the contents.
just how to replace strings :) as i do
first arg will be filename second target string third one the string to be replaced instead of targe
public class ReplaceString{
public static void main(String[] args)throws Exception {
if(args.length<3)System.exit(0);
String targetStr = args[1];
String altStr = args[2];
java.io.File file = new java.io.File(args[0]);
java.util.Scanner scanner = new java.util.Scanner(file);
StringBuilder buffer = new StringBuilder();
while(scanner.hasNext()){
buffer.append(scanner.nextLine().replaceAll(targetStr, altStr));
if(scanner.hasNext())buffer.append("\n");
}
scanner.close();
java.io.PrintWriter printer = new java.io.PrintWriter(file);
printer.print(buffer);
printer.close();
}
}
So, my lecture powerpoint slides and even my book is not really doing a good job (for my understanding that is) of explaining how to use formulas from a text document, then when the code runs/compiles successfully it will create a "Results.txt" in the same folder.
These are the formulas in a notepad doc. Nothing to crazy, just a proof of concept
4 * 5 ..
3 / 4...
3 - 1..
2 + 3..
import java.io.*;
import java.util.*;
public class ReadFileLineByLine {
public static void main(String[] args) throws FileNotFoundException {
String line;
int numberOfLines = 3;
String[] textData = new String[numberOfLines];
int i;
for(i = 0; i < numberOfLines; i++){
textData[i] = textReader.readLine();
}
text.Reader.close();
return textData;
try {
File inputfile = new File(args[0]); //new File("formulas.txt")
Scanner input = new Scanner(new File("C:\Users\Frost\Documents\Question4"));
BuffredReader br = new BufferedReader(new FileReader("C:\Users\Frost\Documents\Question4"));
PrintWriter output = new PrintWriter("Results.txt");
while (input.hasNextLine()) {
line = input.nextLine();
System.out.println("read <" + line + ">"); // Display message to commandline
// Declare ArrayList of for storing tokenized formula from String line
double result = 0; // The variable to store result of the operation
// Determine the operator and calculate value of the result
System.out.println(formula.get(0) + ' ' + formula.get(1) + ' ' +
formula.get(2) + " = " + result); // Display result to command line
// Write result to file
}
// Need to close input and output files
}
catch (FileNotFoundException e) {
System.out.println("Error reading file named " + Formulas.txt);
}
}
}
Here's something to get you started. The //TODO: comments are where you need to build your logic. Be sure to change the file paths back to what you need. I changed them to a Temp location. Also change the messages printed as I just put something there as proof of concept. I tried to comment thoroughly but don't hesitate to ask questions.
import java.io.*;
import java.util.*;
public class ReadFileLineByLine {
public static void main(String[] args) throws FileNotFoundException {
String line = "";
//Declare Scanner and PrintWriter outside of try clause so they can be closed in finally clause
Scanner input = null;
PrintWriter output = null;
try {
//Instantiate input and output file
input = new Scanner(new File("C:\\Temp\\test.txt"));
output = new PrintWriter(new File("C:\\Temp\\Results.txt"));
//Loop through lines in input file
while (input.hasNextLine()) {
line = input.nextLine();
// Display message to commandline
System.out.println("read <" + line + ">");
// Populate ArrayList of tokenized formula from String line
//TODO:
// The variable to store result of the operation
double result = 0;
// Determine the operator and calculate value of the result
//TODO:
// Write result to file
output.println("Print result of " + line + " to Results.txt");
}
} catch (FileNotFoundException e) {
//Exception thrown, print message to console
System.out.println("File Not Found: " + e.getMessage());
} finally {
//close files in finally clause so it happens even if exception is thrown
//I also set to null as extra precaution
input.close();
input = null;
output.close();
output = null;
}
}
}
I am using java to import doubles from a excel file into doubles array, here is my code(I steal the second half of the code from another source: https://www.mkyong.com/java/how-to-read-and-parse-csv-file-in-java/):
private static int rows = 10;
private static double[][][] data10;
data10 = new double[rows][2][];
for (int i = 0; i<rows; i++) {
data10[i][0] = new double[16];
data10[i][1] = new double[1];
}
String csvFile = "data.csv";
BufferedReader br = null;
String line = "";
String cvsSplitBy = ",";
try {
br = new BufferedReader(new FileReader(csvFile));
for (int j = 0; j < rows; j++) {
line = br.readLine();
// use comma as separator
String[] values = line.split(cvsSplitBy);
for (int i = 0; i < values.length-1; i++) {
//String temp = values[i];
//System.out.println(temp.trim());
//System.out.println(2);
data10[j][0][i] = Double.valueOf(values[i]);
}
data10[j][1][0] = Double.valueOf(values[values.length - 1].trim());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
i had numberformatexception at this line:
data10[j][0][i] = Double.valueOf(values[i]);
the reason is that the the first cell in the csv file is number 2, however it was shown as " 2" in the exception message. I tried to trim the string, however the "whitespace" cannot be trimmed. I tried to assign values[i] to a String object and trim it yet without success.
Finally I realized that I have to save the file as "comma separated values(.csv)", but not "CSV UTF-8(comma delimited)(.csv)". After correcting this, the code works.
I hope this would help someone. I can't find the answer in other stackoverflow posts.
.trim() replaces whitespace which is represented by unicode '\u0020'. What you might be seeing is a nobreakspace( ) which is represented by '\u00A0'.
To remove it try: data10[j][0][i] = Double.valueOf(values[i].replaceAll("\\u00A0", ""));
In Java, here is the code to read a file with a table of integers:
public static int[][] getDataset() {
// open data file to read n and m size parameters
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(filePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
// count the number of lines
int i = -1;
String line = null, firstLine = null;
do {
// read line
try {
line = br.readLine();
i++;
if (i == 0) firstLine = line;
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
} while (line != null);
// close data file
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
// check the data for emptiness
if (i == 0) {
System.out.println("The dataset is empty!");
System.exit(1);
}
// initialize n and m (at least the first line exists)
n = i; m = firstLine.split(" ").length;
firstLine = null;
// open data file to read the dataset
br = null;
try {
br = new BufferedReader(new FileReader(filePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
// initialize dataset
int[][] X = new int[n][m];
// process data
i = -1;
while (true) {
// read line
try {
line = br.readLine();
i++;
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
// exit point
if (line == null) break;
// convert a line (string of integers) into a dataset row
String[] stringList = line.split(" ");
for (int j = 0; j < m; j++) {
X[i][j] = Integer.parseInt(stringList[j]);
}
}
// close data file
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
return X;
}
Dataset size parameters n and m are of type static final int and declared outside as well as static final String filePath.
I give you my solution (maybe will be useful for newbies later coming to read this) and ask if it is possible to make it faster in time and/or consuming less memory? I'm interested in perfect micro-optimization, any advice would be great here. In particular I do not like the way the file is opened twice.
Read the file only once and add all lines to an ArraList<String>.
ArrayList grows automatically.
Later process that ArrayList to split the lines.
Further optimisations:
Strimg.split uses a huge regular expression analyzer. Try it with StringTokenizer or your own stringsplit method.
Instead of ArrayList you could avoid overhead by using GrowingIntArray,or GrowingStringArray, these avoid some overhead but are less handy.
speed and mempory usage are contradicting, often you cannot optimize both.
You can save memor by using a one dimesnional array, in java 2d arrays need more space becauseeach column is an object.
access one dim array by X[col + row *rowsize].
I am trying to decode the data encoded in the image. The encoding works fine and the data size of image also changes but for some reason the decoded data is an empty string. Either the encoded data get lost or this code has some mistake.
int temp,tempText=0,x=0,p=0;
try
{
image= ImageIO.read(new File("C:\\Users\\Desktop\\Encoded.png"));
}
catch (IOException e)
{
e.printStackTrace();
}
for(int i=0;i<image.getWidth();i++)
{
for(int j=0;j<image.getHeight();j++)
{
pixels[i][j]=image.getRGB(i, j);
}
}
for(int i=0;i<Width;i++)
{
for(int j=0;j<Height;j++)
{
temp=pixels[i][j];
int change=0;
for(int k=0;k<4;k++) // 4 iterations for 4bytes of every pixel
{
if(k==0)
{
change=1;
}
else
if(k==1)
{
change=256;
}
else
if(k==2)
{
change=65536;
}
else
if(k==3)
{
change = 16777216;
}
tempText=tempText | (pixels[i][j] & change);
p++;
if(p==8) // because character is of 8bits
{
myString.concat(String.valueOf(tempText));// Writing decoded data in string
p=0;
tempText=0;
}
}
}
// Writing in file
try
{
file = new File("C:\\Users\\Desktop\\Retreive.txt");
fw = new FileWriter(file);
bw= new BufferedWriter(fw);
bw.write(myString);
bw.close();
}
catch (Exception e)
{
e.printStackTrace();
}
Kindly notify me if any mistake I am making or any thing this code is lacking.
String.concat doesn't change the string you call it on, but instead returns a new string. So if you use myString = myString.concat(...) instead, you might get better results. If tempText contains a character code, you could cast it to a char (since String.valueOf returns the string representation of the int):
// Writing decoded data in string
// myString = myString.concat(String.valueOf(tempText));
myString += (char) tempText;
instead of:
myString.concat(String.valueOf(tempText));// Writing decoded data in string