I have this method that gets the last line of a .txt file and creates a new temp file without that line. But when I try to delete the .txt that has the line I want to delete (so then I can rename the temp file) for some reason I can't. This is the code:
void removeFromLocal() throws IOException {
String lineToRemove = getLastLine();
File inputFile = new File("nexLog.txt");
File tempFile = new File("TempnexLog.txt");
BufferedReader reader = null;
BufferedWriter writer = null;
try {
reader = new BufferedReader(new FileReader(inputFile));
writer = new BufferedWriter(new FileWriter(tempFile));
String currentLine;
int i = 0;
while ((currentLine = reader.readLine()) != null) {
i++;
String trimmedLine = currentLine.trim();
if (!trimmedLine.equals(lineToRemove)) {
if (i != 1) {
writer.newLine();
}
writer.write(currentLine);
}
}
reader.close();
reader = null;
writer.flush();
writer.close();
writer = null;
System.gc();
inputFile.setWritable(true);
if (!inputFile.delete()) {
System.out.println("Could not delete file");
return;
}
if (!tempFile.renameTo(inputFile)) {
System.out.println("Could not rename file");
}
//boolean successful = tempFile.renameTo(inputFile);
} catch (IOException ex) {
Logger.getLogger(dropLog.class.getName()).log(Level.SEVERE, null, ex);
}
}
Whats funny is that when I press the button that calls the method once, nothing happens ("Could not delete file"), the second time it works fine and the 3rd I get "Could not rename file".
The file cannot be deleted when it's been opened by another process. E.g. in notepad or so or maybe even another FileReader/FileWriter on the file somewhere else in your code. Also, when you're executing this inside an IDE, you'll risk that the IDE will touch the file during the background scan for modifications in the project's folder. Rather store the files in an absolute path outside the IDE's project.
Also, the code flow of opening and closing the files has to be modified so that the close is performed in the finally block. The idiom is like this:
Reader reader = null;
try {
reader = new SomeReader(file);
// ...
} finally {
if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
}
Or, if you're already on Java 7, use the automatic resource management instead.
try (Reader reader = new SomeReader(file)) {
// ...
}
Further I recommend to use File#createTempFile() instead to create temp files. This way an unique temp filename will be generated and thus you prevent the very same temp file being written and renamed by multiple processes.
File tempFile = File.createTempFile("nexLog", ".txt");
Does BufferedReader close the nested reader (not mentioned in the doc)? You have to make sure, by checking if setWritable was successful.Otherwise you need to close FileReader too, and I would recommend because in case you close it twice there is no harm... by the way GC call is more harmful than useful.
Related
Unable to delete files even after closing the corresponding readers and writers.
Permissions are present on the files
file.delete() returns false
my code
main(){
try{
File file=new File(path);// Path where the file is present
FileReader reader = new FileReader(path);
BufferedReader br = new BufferedReader(reader);
FileWriter writer = new FileWriter(pathOther);
BufferedWriter wr = new BufferedWriter(writer);
// Readers and writers for i/o operations
while((String str=br.readLine())!=null){
wr.write(str); // Copying to another file
}
}catch(Exception e){}
finally{
reader.close(); //close reader
writer.close(); //close writer
file.delete(); //This returns false
}
My guess as to what is going on is that you close the FileInputStream but leave the BufferedReader open, which leaves something holding on to the file handle. Then, when you try to delete the file, it returns false because something else has a handle on it.
Try the following code:
File file = new File(path);
try {
br = new BufferedReader(new FileReader(file));
// use the reader ...
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
// now close the file
file.delete();
Update:
While testing the above code I noticed something else which could also cause the observations you were seeing. If the file at path does not exist, then logically calling file.delete will also fail for this reason. So you should make sure that the file actually exists before trying to delete it. You can call file.exists() to check for this.
First, you should close the BufferedReader instead of the FileReader (the BufferedReader will in turn call close() on the FileReader):
So instead of:
reader.close(); //close reader
do:
br.close();
(and leave out the complete redundant comment).
Also, since File.delete() simply returns a Boolean and doesn't tell you why it failed, you can get more information by calling Files.delete instead:
try {
Files.delete(file.toPath());
} catch (IOException e) {
// e now contains information about why it can't delete.
}
Nothing will work call System.gc();
I am trying to save the multiple line output in a text file from my jTextArea(named as "outputarea" in a code) to my desired path, Everything is OK but the file being saved do not contain the whole output, but only first line oof text. I am using "\n" to break the line in jtextarea while giving multiple line output, does that make any difference or any other problem in this code, This code is just the code on saveAs button, output is coming from another methods I've created. Thanks in Advance!
private void saveAs() {
FileDialog fd = new FileDialog(home.this, "Save", FileDialog.SAVE);
fd.show();
if(fd.getFile()!=null)
{
fn=fd.getFile();
dir=fd.getDirectory();
filename = dir + fn +".txt";
setTitle(filename);
try
{
DataOutputStream d=new DataOutputStream(new FileOutputStream(filename));
holdText = outputarea.getText();
BufferedReader br = new BufferedReader(new StringReader(holdText));
while((holdText = br.readLine())!=null)
{
d.writeBytes(holdText+"\r\n");
d.close();
}
}
catch (Exception e)
{
System.out.println("File not found");
}
outputarea.requestFocus();
save(filename);
}
}
You should put the d.close(); after the completion of while loop, because just after writing the first line in the file using DataOutputStream, you are closing it and you don't let it to fulfill the whole job.
You can see even an error is wrote in your console:
File not found
This is not because it doesn't find your file, it's because in the iterations after the first, it tries to write into a closed stream. So only the first line is wrote then. So change you code like this:
while ((holdText = br.readLine()) != null) {
d.writeBytes(holdText + "\r\n");
}
d.close();
Also I can advise to use a PrintWriter instead of DataOutputStream. Then you can easily change the writeBytes into println method. In this way you don't need to append \r\n manually to each line you write.
Another good hint is to use a try-with-resource (in case you use java 7 or later) or at least a finally block to close your streams either way:
String holdText = outputarea.getText();
try (PrintWriter w = new PrintWriter(new File(filename));
BufferedReader br = new BufferedReader(new StringReader(holdText))) {
while ((holdText = br.readLine()) != null) {
w.println(holdText);
}
} catch (Exception e) {
System.out.println("File not found");
}
Good Luck.
I have a program that saves on a file. The current code is set for the file to save on a specific path, but when I run the program from a different computer the program doesn't work and I need to change the path everytime.
public CreateCustomer() {
initComponents();
ArrayList<String> ConsIDList = new ArrayList<String>();
String csvFileToRead = "E:\\ryan_assignment_sit2\\ConsID\\consID.csv"; // Reads the CSV File.
BufferedReader br = null; // Creates a buffer reader.
String line = "";
String splitBy = ","; // Reader Delimiter
try {
br = new BufferedReader(new FileReader(csvFileToRead)); // Buffer Reader with file name to read.
Scanner reader = new Scanner(System.in);
while ((line = br.readLine()) != null) { //While there is a line to read.
reader = new Scanner(line);
reader.useDelimiter(splitBy);
while (reader.hasNext()) { // While there is a next value (token).
ConsIDList.add(reader.next());
}
}
} catch (FileNotFoundException exception) { // Exception Handler if the File is not Found.
exception.printStackTrace();
} catch (IOException exception) { // Input/Output exception
exception.printStackTrace();
} finally {
if (br != null) {
try {
br.close(); // Close the Scanner.
} catch (IOException exception) {
exception.printStackTrace();
}
}
I placed the file in the a subfolder in the program with the name ConsID and I tried changing the path file to
String csvFileToRead = "..\\ConsID\\consID.csv";
But the file can't be read from the program.
String csvFileToRead = "E:\ryan_assignment_sit2\ConsID\consID.csv";
The above path will only be applicable to windows. If you execute the program in linux environment you will get an Filenotfoundexception. Eventhough you change the file, again you are hardcoding the file path.
Better you can get it as runtime parameters so that the program will be executed irrespective of OS.
If you are running you program from command line then you can place the csv file in your classpath (root folder where the class files are generated) and refer to it as below:
BufferedReader br = new BufferedReader(ClassLoader.getResourceAsStream("consID.csv"));
So I'm trying to delete a line of data from a file, which I have successfully done by opening a new file and writing all the information that doesn't match with the data that I would like to remove. The problem is, after I have done that, I would like to delete my original file, and then rename the new file with excludes the information I wanted to delete, to the same name as the original file. I have added in the code to do this, but for some reason it's not working.
public static void delete() throws IOException
{
File inputFile = new File("Elements.txt");
File tempFile = new File("myTempFile.txt");
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
String element = JOptionPane.showInputDialog(null, "Enter the name of the Element you wish to delete.", "Remove an Element.", JOptionPane.INFORMATION_MESSAGE);;
String currentLine;
while((currentLine = reader.readLine()) != null) {
String trimmedLine = currentLine.trim();
if(trimmedLine.startsWith(element)) continue;
writer.write(currentLine + System.getProperty("line.separator"));
}
writer.close();
reader.close();
inputFile.delete();
tempFile.renameTo(inputFile);
JOptionPane.showMessageDialog(null, "Data has been removed from the file: Elements.txt");
}
As you can see near the bottom, I have these lines:
inputFile.delete();
tempFile.renameTo(inputFile);
These lines are meant to delete my original file(inputFile) and then rename my new file(tempFile) to the file name that the original file had. After running the code however, I simply get a file called "myTempFile.txt" which has succesfully deleted the line of data that I wanted, but my original file is still present and it wasn't deleted, neither was the new file renamed to the original file.
Any idea why this is happening?
Use the java.nio.file API. This is 2015.
final Path src = Paths.get("Elements.txt").toAbsolutePath();
final Path tmp = src.resolveSibling("Elements.txt.new");
try (
final BufferedReader reader = Files.newBufferedReader(src, StandardCharsets.UTF_8);
final BufferedWriter writer = Files.newBufferedWriter(tmp, StandardCharsets.UTF_8,
StandardOpenOption.CREATE_NEW);
) {
// yadda yadda
}
Files.move(tmp, src, StandardCopyOption.REPLACE_EXISTING);
File is unreliable. It has always been.
in such a case i would start fiddling around, reading documentation and maybe googling for a bit. But i will give you an answer, too!
inputFile.delete();
This could go wrong, for example if you have your file opened in a text editor.
Luckily delete() returns a boolean, try checking that!
Also as Niels correctly mentioned File.renameTo() is quite unrelieble if you have access to Java 7 use the files.nio alternative. In Java 7 you can use Files.move(Path source, Path target, CopyOption... options)
Docs for Java 7 Files: http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html
But your very code works correctly for me. I only change the path to the file and I make sure the file is not opened in editor
public class NewClass {
public static void main(String[] args) {
try {
delete();
} catch (IOException ex) {
Logger.getLogger(NewClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void delete() throws IOException {
File inputFile = new File("C:\\Users\\olyjosh\\Desktop\\Elements.txt");
File tempFile = new File("C:\\Users\\olyjosh\\Desktop\\myTempFile.txt");
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
String element = JOptionPane.showInputDialog(null, "Enter the name of the Element you wish to delete.", "Remove an Element.", JOptionPane.INFORMATION_MESSAGE);;
String currentLine;
while ((currentLine = reader.readLine()) != null) {
String trimmedLine = currentLine.trim();
if (trimmedLine.startsWith(element)) {
continue;
}
writer.write(currentLine + System.getProperty("line.separator"));
}
writer.close();
reader.close();
inputFile.delete();
tempFile.renameTo(inputFile);
JOptionPane.showMessageDialog(null, "Data has been removed from the file: Elements.txt");
}
}
This is code i Have written instead of editing a particular line new name gets appened at the last...
please help me out....
PrintWriter writer = new PrintWriter(new BufferedWriter(
new FileWriter("d:\\book.txt", true)));
BufferedReader br = null;
FileReader reader = null;
try {
reader = new FileReader("d:\\book.txt");
br = new BufferedReader(reader);
String line;
System.out.println((";;;;;;;;;;;;;;;;" + request
.getParameter("hname")));
System.out.println(request.getParameter("book"));
while ((line = br.readLine()) != null) {
if (request.getParameter("hname").equals(line)) {
line = line.replace(request.getParameter("hname"),
request.getParameter("book"));
writer.println(line);
writer.close();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally{
reader.close();
}
Unless you aren't changing the (byte) length of the line, you need to rewrite the whole file, adding the changed line where appropriate. This is actually just a simple change from your current code. First, initialize your FileWriter without the append (since you don't want to just append to the end of the file, which is what you're doing now).
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter("d:\\book.txt")));
Then, either read the whole file into memory (if the file is small enough) or else write a temp file as you go and then copy it over when you're done. The second way is more robust, and requires less code changing; just modify your while loop to write every line, modified or not.
// Open a temporary file to write to.
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter("d:\\book.temp")));
// ... then inside your loop ...
while ((line = br.readLine()) != null) {
if (request.getParameter("hname").equals(line)) {
line = line.replace(request.getParameter("hname"),
request.getParameter("book"));
}
// Always write the line, whether you changed it or not.
writer.println(line);
}
// ... and finally ...
File realName = new File("d:\\book.txt");
realName.delete(); // remove the old file
new File("d:\\book.temp").renameTo(realName); // Rename temp file
Don't forget to close all your file handles when you're done!