Delete specific line from text file - java

I want to have a method that will take the file path and then delete a specific line from a text file and this is the code I came up with.
Method.java
public class Method {
static void deletefileline(String file, Integer line) throws IOException {
ArrayList<String> filecontent = new ArrayList<String>();
try {
File myObj = new File(file);
Scanner myReader = new Scanner(myObj);
while (myReader.hasNextLine()) {
String data = myReader.nextLine();
filecontent.add(data);
}
myReader.close();
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
File f = new File(file);
f.delete();
filecontent.remove(line);
try {
File newfile = new File(file);
newfile.createNewFile();
} catch (IOException e) {
System.out.println("An Error Occured");
}
for (Integer i = 0; i < filecontent.size(); i++) {
String textToAppend = "\r\n" + filecontent.get(i);
Path path = Paths.get(file);
Files.write(path, textToAppend.getBytes(), StandardOpenOption.APPEND);
}
}
public static void main(String[] args) {
deletefileline("src/test.txt", 1);
}
}
This is the text file
test.txt
hi
hello
hii
helloo
This is the text file after i ran Methods.java
Output:
hi
hello
hii
helloo
It won't show it but at the first "hi" before that there is a space so it only added a space at line 1.
So the problem is that when it is running it only adds an extra line at line 1.

Why is not the line removed?
https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html
E remove(int index) Removes the element at the specified position in this list.
boolean remove(Object o) Removes the first occurrence of the specified element from this list, if it is present.
Since Integer line is Object and not a primitive data type int, this call
filecontent.remove(line);
tries to remove the line with a content equal to new Integer(1).
Change the method argument to int line or add type cast to the call filecontent.remove((int) line).
Why is an empty line added?
The extra space is added by this statement:
String textToAppend = "\r\n" + filecontent.get(i);
Change it like this:
String textToAppend = filecontent.get(i) + "\r\n";

This is a small snippet to perform same function as mentioned in question (kotlin version, however same can be done in java)
import java.io.File
class RemoveFileContent {
fun deleteContentAtIndex(filePath: String, indexPos: Int) {
val bufferedWriter = File("/SampleOutputFile.txt").bufferedWriter()
File(filePath).readLines().filterIndexed { i, _ -> i != indexPos }.forEach {
bufferedWriter.appendLine(it)
}
bufferedWriter.flush()
}
}
fun main(args : Array<String>) {
RemoveFileContent().deleteContentAtIndex("/SampleFile.txt",2)
}
Input : Output:
hi hi
hello hello
hii helloo
helloo
Disclaimer : Note that if your file content are huge, this can lead to high memory consumption, as stated here - How to remove first line of a text file in java

Related

Printing an ArrayList using buffered writer in JFrame Form (Java)

I have these three methods and I am trying to write the contents of three lists to a file using the buffered writer.
First Method: To Save File:
public static String showSaveDialog()
{
String fileName = "";
JFileChooser chooser = new JFileChooser();
// Suggesting a name
chooser.setSelectedFile(new File("fileToSave.txt"));
int resultValue = chooser.showSaveDialog(null);
if (resultValue == JFileChooser.APPROVE_OPTION) {
fileName = chooser.getSelectedFile().getAbsolutePath();
Path = chooser.getSelectedFile().getAbsolutePath();
}
writeToTextFile(fileName, "");
return fileName;
}
Second Method: To write To File:
public static void writeToTextFile(String filePath, String toWrite)
{
BufferedWriter writer = null;
try {
writer = Files.newBufferedWriter(Paths.get(filePath),
StandardOpenOption.CREATE);
writer.write(toWrite);
writer.newLine();
writer.close();
}
catch (IOException ex) {
JOptionPane.showMessageDialog(null,
"Saving File Error: " + ex.getMessage(),
"Saving File Error", JOptionPane.ERROR_MESSAGE);
}
}
Third Method: Write Contents of three lists to text file:
public void saveAllQuestions() {
for (String q : questionList){
FileIO.writeToTextFile(FileIO.Path, "$" + q);
for (int i = 0; i < answerList.size(); i++) {
FileIO.writeToTextFile(FileIO.Path,
answerList.get(i) + ", " + correctAnswers.get(i));
}
}
}
When writing to the file the last line is the only one that shows. I am assuming this problem is due to the fact that it is writing to one line only instead of under each other. Can anybody give me some insight please? Thank you
You are opening and closing the file for every line you write. Each time you write a line you are deleting the previous version of the file and replacing it with that one line. You need to open the file, write all the lines, and then close the file.

Java, reading the file from input.txt has an issue

I am working on the project. For my purpose, I need to use them that find the median of medians.
At my point, I need to see the read
I also created the input.txt like that below
3 7
1 4 5 7 9 11 13
Below the snippet, I created the variable for the readpath.
// need the variable of filename to read
private static final String INPUT_FILE_PATH = "input.txt";
So, then I appended the code that needs to read the numerical integers in the input.txt in the main function as known below
public static void main(String args[]){
// read the input file
// TODO need to fix this readpath that gets the bad input
// ! ASAP
Path inputPath = Paths.get(INPUT_FILE_PATH);
Charset charset = Charset.forName("UTF-8");
List<String> fileLines = new ArrayList<>(0);
try {
fileLines = Files.readAllLines(inputPath, charset);
} catch (IOException ex) {
System.err.println("Error reading file: " + ex.getMessage());
System.exit(1);
}
int read_line = 0;
try {
read_line = Integer.parseInt(fileLines.get(0));
} catch (NumberFormatException ex) {
System.err.println("bad file input");
System.exit(1);
}
System.out.println("reading... " + read_line);
// end of reading the filename operation
}
As a result, this code suppose to work. I get the output that is bad file input. I do not understand why it gets bad file. By the way, I put all files together in the same directory.
int read_line = 0;
int read_line2 = 0;
try {
String[] words = fileLines.get(0).split("\\s+"); // Split on whitespace.
read_line = Integer.parseInt(words[0]);
read_line2 = Integer.parseInt(words[1]);
} catch (NumberFormatException ex) {
System.err.println("bad file input - not a number; " + e.getMessage());
System.exit(1);
}
The line contains two numbers, and results in a NumberFormatException.

Load Text file into array

Im writing a hotel console program, the problem i have at the moment is to load the saved file back to a String[], when the user presses option to load from file.
The text file includes the guest names saved earlier.
Here is the file data
tom
mo
jo
john
meg
bob
jack
veronica
jessica
angelica
And here is all the code I have
Yes thank you i know arrays are 0 index. for loops are starting from 1 because
i want to have
Room1 instead Room0 as first
THANK YOU PROBLEM SOLVED
public class FileLoad {
public String[] readLines(String filename) throws IOException {
FileReader fileReader = new FileReader(filename);
BufferedReader bufferedReader = new BufferedReader(fileReader);
List<String> lines = new ArrayList<String>();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
lines.add(line);
}
bufferedReader.close();
return lines.toArray(new String[lines.size()]);
}
public class Hotel_array {
if (Menu.equalsIgnoreCase("S")) {
save(hotel);
}
if (Menu.equalsIgnoreCase("L")) {
load(hotel);
}
}
}
private static void save(String hotel[]) {
try {
PrintWriter pr = new PrintWriter("data.txt");
for (int i = 1; i < 11; i++) {
pr.println(hotel[i]);
}
pr.close();
} catch (Exception e) {
e.printStackTrace();
System.out.println("No such file exists.");
}
}
public static void load(String[] args) {
FileLoad rf = new FileLoad();
String file = "data.txt";
try {
String[] hotel = rf.readLines(file);
for (String line : hotel) {
System.out.println(line); // IT PRINTS FILE NOT LOADS TO ARRAY
}
} catch (IOException e) {
System.out.println("Unable to create " + file + ": " + e.getMessage());
}
}
}
You could change your FileLoad class and add another method to write the array to the file, just to keep all the file IO in one class.
public class FileLoad {
public static String[] readHotelArray(String filename) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new FileReader(filename));
List<String> lines = new ArrayList<String>();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
lines.add(line);
}
bufferedReader.close();
return lines.toArray(new String[lines.size()]);
}
public static void writeHotelArray(String filename, String[] hotel) throws IOException {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filename, false));
//Write each string from the array to the file as a new line
for (String s : hotel)
bufferedWriter.write(s + "\n");
bufferedWriter.flush();
bufferedWriter.close();
}
}
Note: Both methods are static so you don't have to instantiate a new object since there will always be only one method call on that object
Now you have to change the way you save and load the array in your Hotel_array class. You could use something like this:
//...
private static void save(String[] hotel) {
try {
FileLoad.writeHotelArray("data.txt", hotel);
} catch (Exception e) {
e.printStackTrace();
System.out.println("No such file exists.");
}
}
public static String[] load() {
String file = "data.txt";
String[] hotelArray = null;
try {
hotelArray = FileLoad.readHotelArray(file);
} catch (IOException e) {
System.out.println("Unable to create " + file + ": " + e.getMessage());
}
return hotelArray;
}
//...
and since parameters in java are always pass-by-value (more about that here) you need to return the String array in your load() method. And therefore you also have to change a tiny bit of code in the main method.
From:
//...
if (Menu.equalsIgnoreCase("L")) {
load(hotel);
}
//...
To:
//...
if (Menu.equalsIgnoreCase("L")) {
hotel = load();
}
//...
Hope that helps a bit (:
tomaszsvd, I will leave this here for your review... I thought it might help your Java learning curve. I encourage you to compare the load() method below with your original code. Also study the example output to see what is different.
fwiw, I like scsere's answer, it is a clean design. You should pursue that and mark it as the answer.
Let's focus on the code for Hotel_array.load( String[] args ).
Once Hotel_array.load() calls rf.readLines() you have 2 arrays in memory.
1st array: Hotel_array's main()'s local variable "hotel".
2nd array: load()'s local variable "hotel", which is a temporary variable.
Inside Hotel_array.load() remember that the args parameter ties back to main()'s "hotel" variable.
So load()'s local variable "hotel" has nothing to do with main()'s "hotel" variable.
Just to make this a little more clear I'm going to tweak your load() method:
Sample Output
$ javac *.java
$ cat data.txt
alpha
beta
gamma
delta
$ java Hotel_array
WELCOME TO THE HOTEL BOOKING
Hotel Booking Options
A: To Add customer to a room
V: To View all rooms
E: To Display empty rooms
D: To Delete customer from a room
F: Find room from customer name
O: View rooms alphabetically by name
S: Save to file
L: Load from file
L
Loaded 4 lines from filedata.txt
args[1]=empty, will assign line=alpha
args[2]=empty, will assign line=beta
args[3]=empty, will assign line=gamma
args[4]=empty, will assign line=delta
Hotel Booking Options
A: To Add customer to a room
V: To View all rooms
E: To Display empty rooms
D: To Delete customer from a room
F: Find room from customer name
O: View rooms alphabetically by name
S: Save to file
L: Load from file
V
room 1 is occupied by alpha
room 2 is occupied by beta
room 3 is occupied by gamma
room 4 is occupied by delta
room 5 is empty
room 6 is empty
room 7 is empty
room 8 is empty
room 9 is empty
room 10 is empty
Hotel Booking Options
A: To Add customer to a room
V: To View all rooms
E: To Display empty rooms
D: To Delete customer from a room
F: Find room from customer name
O: View rooms alphabetically by name
S: Save to file
L: Load from file
^C$
Modified Hotel_array.load() method
public static void load(String[] args) {
FileLoad rf = new FileLoad();
String file = "data.txt";
try {
// ORIGINAL String[] hotel = rf.readLines(file);
String[] tempHotelData = rf.readLines(file); // Note the different var name.
System.out.println("Loaded "+tempHotelData.length+" lines from file"+file);
int i = 1; // Following your convetion of staring from index #1.
for (String line : tempHotelData ) {
// ORIGINAL: System.out.println(line); // IT PRINTS FILE NOT LOADS TO ARRAY
// NEW...
// Let's print out what is oging on...
// So let's assign "line" to the "args" array.
// Remember that "args" ties back to main()'s "hotel" variable.
System.out.println("args["+i+"]="+args[i]+", will assign line="+line);
args[i] = line;
i = i + 1;
}
} catch (IOException e) {
// probably should say "Unable to LOAD" vs "Unable to CREATE"...
System.out.println("Unable to create " + file + ": " + e.getMessage());
}
}
Some additional things for you to think about...
1) Do you want to assign a line from a file if somebody is already in a room?
(e.g. it isn't empty).
2) What happens if "data.txt" has more lines than you have rooms?

program only read last line in .txt file java

I have a problem and don't know what to do. This method is supposed to read all the text in a .txt document. My problem is when the document contains more then one line of text and the program only read the last line. The program don't need to worry about signs like . , : or spaces, but it have to read all the letters. Can anybody help me?
example text
hello my name is
(returns the right result)
hello my
name is
(returns only name is)
private Scanner x;
String readFile(String fileName)
{
try {
x = new Scanner (new File(fileName + (".txt")));
}
catch (Exception e) {
System.out.println("cant open file");
}
while (x.hasNext()) {
read = x.next();
}
return read;
}
It's because when you use read = x.next(), the string in the read object is always being replaced by the text in the next line of the file. Use read += x.next() or read = read.concat(x.next()); instead.
You replace every read with every read(). Also, you didn't close() your Scanner. I would use a try-with-resources and something like,
String readFile(String fileName)
{
String read = "";
try (Scanner x = new Scanner (new File(fileName + (".txt")));) {
while (x.hasNextLine()) {
read += x.nextLine() + System.lineSeparator(); // <-- +=
}
} catch (Exception e) {
System.out.println("cant open file");
}
return read;
}

take in different files

Hi I am writing a program that takes in a textfile and goes through it and if it finds the message #GetFile "filename.txt" goes and gets that and stores it in the same arraylist as the first textfile but I am not able to think through the problem because if a file calls another file which calls another file and that file might be able to call another file. And I am wondering if I can call a method that contains a scanner class over and over again.
This is file one
#GetFile "fileSecond.txt"
----------
this is file two
#GetFile "fileThird.txt"
----------
this is text file three
#GetFile "fileOne.txt"
this is how different text file have it the --- <- is different textfile not same page sorry I didn't know how to show it here
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class Project3
{
public static void main(String[] args)
{
ArrayList<String> text = new ArrayList<String>();
File dictionaryFile = null; // set default value
File dictionaryFileTwo = null;
Scanner inputFile = null; // set default value
Scanner inputFileTwo = null;
// use a try-catch block to handle situations when the file is not present
keyboard = new Scanner(System.in);
// fileName = keyboard.next();
String fileName = "test1.txt";
try {
dictionaryFile = new File(fileName); // declare the file
inputFile = new Scanner(dictionaryFile);
} catch (Exception e) {
// if File object creation failed (such as when file is not there)
// then this code gets executed.
// print the directory where this program expects to find dictionary
System.out.println(System.getProperty("user.dir"));
// ensure file exists and is in the correct directory
if (!dictionaryFile.exists()) {
System.out.println("*** Error *** \n"
+ "Your text file has the wrong name or is "
+ "in the wrong directory. \n"
+ "Aborting program...\n\n");
System.exit(-1); // Terminate the program
}
}// end catch
// while there are words in the input file, add them to the dictionary
while (inputFile.hasNext()) {
if(inputFile.next().startsWith("#GetFile")){
String filing = inputFile.next();
System.out.println("HEY THIS IS THE FILE THAT I FOUND "+ filing);
String fileNameSecond = filing;
try {
dictionaryFileTwo = new File(filing); // declare the file
inputFile = new Scanner(dictionaryFile);
}catch (Exception e) {
// if File object creation failed (such as when file is not there)
// then this code gets executed.
// print the directory where this program expects to find dictionary
System.out.println(System.getProperty("user.dir"));
// ensure file exists and is in the correct directory
if (!dictionaryFile.exists()) {
System.out.println("*** Error *** \n"
+ "Your text file has the wrong name or is "
+ "in the wrong directory. \n"
+ "Aborting program...\n\n");
System.exit(-1); // Terminate the program
}
}// end catch
} else {
text.add(inputFile.nextLine());
}
}
for(int i =0; i < text.size(); i++){
System.out.println(text.get(i));
}
}
}
The basic algorithm would be:
open the output-file
ExpandIncudes(input-file, output-file) {
open input-file
while (read line from input)
if (line is-a #include) then
ExpandIncudes(input-file)
else
write line to output-file
endif
next line
}
And no, I don't think you could keep reusing the same scanner for reading different files.
Cheers. Keith.
Your question is a little muddled but it seems you need to investigate how to use some recursion here.
You'd just need a method that upon finding the "#GetFile" directive would then grab the file name to get and call the method again with this name.
public void parseFile(String filename) {
//readline while not end of file...
//is line a #GetFile directive?
//parseFile(newFilename)
}
... or something like that
Sibghatuk,
I'm going to presume that your homework's been handed in, so it's "safe" to just hand you "the answer".
I'd do it something like this:
package forums;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
public class HashInclude
{
private static final String[] INCLUDE_PATH =
System.getenv("INCLUDE_PATH").split(File.pathSeparator);
public static void main(String... args) {
try {
for ( String filename : filenames ) {
hashInclude(filename);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void hashInclude(String filename)
throws FileNotFoundException, IOException
{
BufferedReader reader = new BufferedReader(new FileReader(filename));
try {
String line = null;
int lineCount = 0;
while ( (line=reader.readLine()) != null ) {
++lineCount;
if ( line.startsWith("#include ") ) {
String targetFilename = line.replaceFirst("^#include[ \t]*", "").trim();
if ( !targetFilename.matches("^[<\"][A-z0-9_]+\\.h[\">]$") )
// not a <valid.h> or a "valid.h"
throw new IncludeException(targetFilename, lineCount, filename);
// <valid.h> --> valid.h
targetFilename = targetFilename.substring(1, targetFilename.length()-1);
// search directories in the INCLUDE_PATH for targetFilename
for ( String dir : INCLUDE_PATH ) {
File targetFile = new File(dir, targetFilename); // c:/path/to/valid.h
if ( targetFile.exists() ) {
hashInclude( targetFile.getAbsolutePath() ); // <<-- recursive call
return;
}
} // next dir
throw new FileNotFoundException("File " + targetFilename
+ " not found in INCLUDE_PATH="+ System.getenv("INCLUDE_PATH"));
} else {
System.out.println(line);
}
} // next line
} finally {
reader.close();
}
}
}
class IncludeException extends RuntimeException {
private static final long serialVersionUID = 0L;
public IncludeException(String targetFilename, int lineCount, String filename) {
super("Invalid #include: " + targetFilename + " at " + lineCount + " " + filename);
}
}
I think that the above is a "reasaonbly elegant" solution to the problem... even if I do say so myself ;-)
Note that the hashInclude method recursively calls itself... recursion lends itself naturally to following an "arbitrary tree structure"... i.e. a tree whose precise structure is unknowable when you're writing the software... and therefore "recursion" is about the first thing pops into many programmers minds when they here the word "tree".
Please note that the above code implements a greatly-simplified version of the C preprocessor #include mechanism... but could (reasonably easily) be extended into a "proper preprocessor"... one that even (recursively) expands #defines.
Cheers. Keith.

Categories