I have to accomplish a task of writing a set of data to file, use it, then overwrite it with new data. Thus overwrite of the file takes place repeatedly.I know i can accomplish the above by creating FileWriter object each time with the option to overwrite like below
FileWriter object = new FileWriter("fileName", false)
and close it to write to the file.
If i am supposed to overwrite the file n number of times , according to the above method i need to create n number of FileWriter objects. Is there any efficient way to overwrite a file repeatedly by only creating a single FileWriter object?
Not a direct answer, but anyway.
DON'T DO THAT!
What do you think will happen if for some reason writing the new data to the file fails?
You not only lose your original file, but also the new file contents...
Write the new content to another file, ensure that it is well written and closed, and then rename the new file atomically to the original file.
PS: and do not forget to correctly .close().
PS2: if you use Java 7, use the new Files API.
Its better to make a temp file and then rename the tempfile and delete the old like here:
public static void nachtragenTRA(File files) throws IOException{
Scanner sc=null;
File f= files;
String analyse = "";
String NTausgabe = "";
int max = 0;
int k = 0;
String updatedLine[] = new String [4];
int filenr = 1;
boolean sucess = false;
try{
sc= new Scanner(f);
}catch(FileNotFoundException x){
System.out.println("Error: File not found!");
}
while (sc.hasNextLine()){ //get next line
analyse = sc.nextLine();
max = analyse.length(); //get line lenght
StringBuffer sb = new StringBuffer(analyse); //write analyse in StringBuffer
//to change the string
if(k == 1)
{
sb.replace(Daten.NTdatapos[3],max, Daten.NTProbentypTextfield.getText());
updatedLine[0] =String.valueOf(sb);
}
else if(k == 2)
{
sb.replace(Daten.NTdatapos[4],max, Daten.NTPrueferTextfield.getText());
updatedLine[1] =String.valueOf(sb);
}
else if(k == 3)
{
sb.replace(Daten.NTdatapos[5],max, Daten.NTKundeTextfield.getText());
updatedLine[2] =String.valueOf(sb);
}
else if(k == 4)
{
sb.replace(Daten.NTdatapos[5],max, Daten.NTWerkstoffTextfield.getText());
updatedLine[3] =String.valueOf(sb);
}
if(k>3)
{
break;
}
k++;
}
sc.close();
//NTausgabe=DatenTextarea.getText()+"\n"+updatedLine[0]+"\n"+updatedLine[1];
//DatenTextarea.setText(String.valueOf(NTausgabe));
//NTausgabe=DatenTextarea.getText()+"\n"+NTKundeTextfield.getText()+"\n"+NTPrueferTextfield.getText();
//DatenTextarea.setText(String.valueOf(NTausgabe));
//create tmp file with the new data
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(String.valueOf(f)+".tmp")));
BufferedReader br = null;
FileReader reader = null;
try {
reader = new FileReader(String.valueOf(f));
br = new BufferedReader(reader);
String line;
while ((line = br.readLine()) != null)
{
//Change speciffic lines
if(filenr == 2)
{
writer.println(updatedLine[0]);
}
else if(filenr == 3)
{
writer.println(updatedLine[1]);
}
else if(filenr == 4)
{
writer.println(updatedLine[2]);
}
else if(filenr == 5)
{
writer.println(updatedLine[3]);
}
//Andere Zeilen beibehalten
else
{
writer.println(line);
}
filenr = filenr + 1;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally{
reader.close();
br.close();
File realName = new File(String.valueOf(f));
realName.delete(); //delete old file
writer.close();
sucess = new File(String.valueOf(f)+".tmp").renameTo(realName); //rename tmp File to the others name
if(sucess != true)
{
NTausgabe=Daten.DatenTextarea.getText()+"\n"+"Rename File failed";
Daten.DatenTextarea.setText(String.valueOf(NTausgabe));
}
else
{
NTausgabe=Daten.DatenTextarea.getText()+"\n"+"File renamed sucessfully";
Daten.DatenTextarea.setText(String.valueOf(NTausgabe));
}
}
}
Related
I typed 3 names in the file, and I wanted to write a code to count how many times each name was repeated (Example: Alex was repeated in the file 3 times..and so on). The code I wrote only counted each name once, and this is wrong because the names were repeated more than once. Can you help me with the part that could be the cause of this problem?
public class MainClass {
public static void readFile() throws IOException {
//File file;
FileWriter writer=null;
String name, line;
List <String> list = new ArrayList <>();
int countM = 0, countAl = 0, countAh = 0;
try
{
File file = new File("\\Users\\Admin\\Desktop\\namesList.txt");
Scanner scan = new Scanner(file);
while(scan.hasNextLine()) {
line = scan.nextLine();
list.add(line);
}
for (int i=0; i<list.size(); i++)
{
name=list.get(i);
if (name.equals("Ali"))
{
countAl= +1;
}
if (name.equals("Ahmed"))
{
countAh= +1;
}
if (name.equals("Muhammad"))
{
countM = +1;
}
}
Collections.sort(list);
writer = new FileWriter("\\Users\\Admin\\Desktop\\newNameList");
for(int i=0; i<list.size(); i++)
{
name = list.get(i);
writer.write(name +"\n");
}
writer.close();
System.out.println("How many times is the name (Ali) in the file? " + countAl);
System.out.println("How many times is the name (Ahmed) in the file? " + countAh);
System.out.println("How many times is the name (Muhammad) in the file? " + countM);
}
catch(IOException e) {
System.out.println(e.toString());
}
}
public static void main(String[] args) throws IOException {
readFile();
}
}
You an do this much simpler:
//Open a reader, this is autoclosed so you don't need to worry about closing it
try (BufferedReader reader = new BufferedReader(new FileReader("path to file"))) {
//Create a map to hold the counts
Map<String, Integer> nameCountMap = new HashMap<>();
//read all of the names, this assumes 1 name per line
for (String name = reader.readLine(); name != null; name = reader.readLine()) {
//merge the value into the count map
nameCountMap.merge(name, 1, (o, n) -> o+n);
}
//Print out the map
System.out.println(nameCountMap);
} catch (IOException e) {
e.printStackTrace();
}
try:
for (int i=0; i<list.size(); i++)
{
name=list.get(i);
if (name.equals("Ali"))
{
countAl += 1;
}
if (name.equals("Ahmed"))
{
countAh += 1;
}
if (name.equals("Muhammad"))
{
countM += 1;
}
}
This works with me.
+= is not same =+
You need to process each line bearing in mind that the file may be very large in some cases. Better safe than sorry. You need to consider a solution that does not take up so much resources.
Streaming Through the File
I'm going to use a java.util.Scanner to run through the contents of the file and retrieve lines serially, one by one:
FileInputStream inputStream = null;
Scanner sc = null;
try {
inputStream = new FileInputStream(file_path);
sc = new Scanner(inputStream, "UTF-8");
while (sc.hasNextLine()) {
String line = sc.nextLine();
// System.out.println(line);
}
// note that Scanner suppresses exceptions
if (sc.ioException() != null) {
throw sc.ioException();
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (sc != null) {
sc.close();
}
}
This solution will iterate through all the lines in the file – allowing for processing of each line – without keeping references to them – and in conclusion, without keeping them in memory:
Streaming With Apache Commons IO
The same can be achieved using the Commons IO library as well, by using the custom LineIterator provided by the library:
LineIterator it = FileUtils.lineIterator(your_file, "UTF-8");
try {
while (it.hasNext()) {
String line = it.nextLine();
// do something with line
}
} finally {
LineIterator.closeQuietly(it);
}
Since the entire file is not fully in memory – this will also result in pretty conservative memory consumption numbers.
BufferedReader
try (BufferedReader br = Files.newBufferedReader(Paths.get("file_name"), StandardCharsets.UTF_8)) {
for (String line = null; (line = br.readLine()) != null;) {
// Do something with the line
}
}
ByteBuffer
try (SeekableByteChannel ch = Files.newByteChannel(Paths.get("test.txt"))) {
ByteBuffer bb = ByteBuffer.allocateDirect(1000);
for(;;) {
StringBuilder line = new StringBuilder();
int n = ch.read(bb);
// Do something with the line
}
}
The above examples will process lines in a large file without iteratively, without exhausting the available memory – which proves quite useful when working with these large files.
I have this method here. I want to list all the files in a specific folder. I want to read them all and if a file has a line with more than 5 characters I want to delete it. What am I doing wrong?
public void read() throws IOException {
File[] fajllat = folder.listFiles((File f) -> f.isFile());
int count = 0;
String line = null;
for (File file : fajllat) {
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
while ((line = br.readLine()) != null) {
if (line.length() > 5) {
count++;
file.delete();
}
}
}
FileWriter fw = new FileWriter("C://Users//Admin//Desktop//foldtest123");
BufferedWriter bw = new BufferedWriter(fw);
try (PrintWriter pw = new PrintWriter(bw)) {
pw.println(count);
pw.close();
}
}
In order to see what is going wrong and the file does not being deleted, use Files.delete(file.toPath()); instead of File#delete method. java.nio.Files#delete method will throw an exception, and then you will be able to know...
Also, worth to read: this question.
Are you checking using the boolean result of file.delete() if the file is being deleted or not? I think you should do that. Also, once a file is deleted, break the while loop and go on to the next file. I have modified the code including the above two findings.
File directory = new File("XXXX/XXXX/XXXX/XXXX/");
if(!directory.isDirectory()) {
System.out.println("Given file is not a directory");
return;
}
String line;
int count = 0;
File[] fileList = directory.listFiles(File::isFile);
if(fileList != null && fileList.length > 0) {
for (File file : fileList) {
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
while ((line = br.readLine()) != null) {
if (line.length() > 5) {
count++;
boolean wasFileDeleted = file.delete();
if(wasFileDeleted) {
System.out.println("The file "+file.getName()+" was deleted");
} else {
System.out.println("The file "+file.getName()+" deletion did not succeed");
}
break;
}
}
}
}
System.out.println("A total of "+count+" files were deleted");
I was able to delete all files within a directory using the same code you are using. This was in a mac. Please post if you are getting any errors while deleting.
I am new to the programming please help me regarding this scenario.
I am trying to design a code for a program
I have a xml files which contains X number of lines and i need to put first 100 lines of that file to another sub file and next to another sub file and so on up to the end. naming convention should be like file1, file2,....
Input files will be of 5000, 10000 or even more lines
I need a dynamic code for this scenario using dom parser
i designed a code for a file with constant lines.
import java.io.*;
public class splitting
{
public static void main(String args[])throws Exception
{
int count = 0;
BufferedReader br = null;
FileWriter fileWriter1 = new FileWriter("C:\\senderoutput1.txt");
FileWriter fileWriter2 = new FileWriter("C:\\senderoutput2.txt");
FileWriter fileWriter3 = new FileWriter("C:\\senderoutput3.txt");
FileWriter fileWriter4 = new FileWriter("C:\\senderoutput4.txt");
try {
String currentLine;
br = new BufferedReader(new FileReader("C:\\senderinput.txt"));
while ((currentLine = br.readLine()) != null)
{
count++;
if (count <= 100)
{
fileWriter1.write(currentLine + System.getProperty("line.separator", "\r\n"));
} else if (count > 100 && count <= 200)
{
fileWriter2.write(currentLine + System.getProperty("line.separator", "\r\n"));
}else if (count > 200 && count <= 300)
{
fileWriter3.write(currentLine + System.getProperty("line.separator", "\r\n"));
}else if (count > 300 && count <= 400)
{
fileWriter4.write(currentLine + System.getProperty("line.separator", "\r\n"));
}
}
} finally
{
if (br != null)
{
br.close();
}
fileWriter1.close();
fileWriter2.close();
fileWriter3.close();
fileWriter4.close();
System.out.println("File Splitting was successful!!!");
}
}
}
this code is for the file which has 400 lines.
how to do it for n number of lines?
You can do something like this to achieve what you are trying to achieve:
BufferedReader br = null;
FileWriter fileWriter = new FileWriter("C:\\senderoutput1.txt");
try {
String currentLine = null;
br = new BufferedReader(new FileReader("C:\\senderinput.txt"));
while ((currentLine = br.readLine()) != null) {
/* Increment Counter */
++count;
/* Write Text To File */
fileWriter.write(currentLine + System.getProperty("line.separator", "\r\n"));
/* Check Split Condition */
if (count % 100 == 0) {
/* Close Already Open File */
fileWriter.close();
/* Point To New File */
fileWriter = new FileWriter("C:\\senderoutput" + (count/100 + 1) + ".txt");
}
}
/* Close Last Open File */
fileWriter.close();
} finally {
if (br != null) {
br.close();
}
System.out.println("File Splitting Completed Successfully!!!");
}
Please note that this is just to give you an idea and you can modify it as per your needs.
Beginner approach:
1) Read the next line in a loop.
2) Increment a counter & append the current line into a String.
3) Every time the counter hits a new 100 decimal value,
write out the String (which contains the collection of lines)
to a new file.
4) Clear the string.
I believe it's much better to make a description, then giving out code, especially for beginners.
Write the n lines in m no. of files (as User input) :
You should try this easiest code to achieve this dynamically.
I am using here Buffered Reader, Buffered Writer and java streams to get this :
//Code here :
String curpath = System.getProperty("user.dir");
List<String> list = null;
BufferedWriter bw1 = null;
Scanner sc = new Scanner(System.in);
System.out.println("How many lines you want per file, Please Enter");
String nfr = sc.nextLine();
int nfr1 = Integer.parseInt(nfr);
System.out.println("How many file you want, Please Enter");
String nfr2 = sc.nextLine();
int nfr3 = Integer.parseInt(nfr2);
sc.close();
int count = 1;
int i = nfr1; // no. of lines per file
int b = 0;
for (int j = 1; j <= nfr3; j++) { // nfr3 -- no. of files create
BufferedReader br = new BufferedReader(new FileReader(curpath + "//datafile.txt"));
list = br.lines().skip(b).limit(i).collect(Collectors.toList());
b = count * i; //skip the lines
File file1 = new File(curpath + "//Split_Line" + "//file" + j + ".txt" + " ");
file1.getParentFile().mkdirs();
file1.createNewFile();
bw1 = new BufferedWriter(new FileWriter(file1));
for (String record : list)
bw1.write((record + System.lineSeparator()));
br.close();
bw1.flush();
count++;
}
System.out.println("Split_line file complete");
bw1.close();
I suppose, it would be helpful to you. If you want to suggest anything to improve code. please comment
I have deciphering method that should open a test file with encrypted text, then read and decipher each line of text that I read in from the input file. The text file is called mystery.txt.
I can get the method to work when only inputting single characters but I can't get it to work where I open the .txt file and decipher line by line.
Dechiphering method:
public static String cipherDecipherString(String text)
{
// These are global. Put here for space saving
private static final String crypt1 = "cipherabdfgjk";
private static final String crypt2 = "lmnoqstuvwxyz";
// declare variables
int i, j;
boolean found = false;
String temp="" ; // empty String to hold converted text
readFile();
for (i = 0; i < text.length(); i++) // look at every chracter in text
{
found = false;
if ((j = crypt1.indexOf(text.charAt(i))) > -1) // is char in crypt1?
{
found = true; // yes!
temp = temp + crypt2.charAt(j); // add the cipher character to temp
}
else if ((j = crypt2.indexOf(text.charAt(i))) > -1) // and so on
{
found = true;
temp = temp + crypt1.charAt(j);
}
if (! found) // to deal with cases where char is NOT in crypt2 or 2
{
temp = temp + text.charAt(i); // just copy across the character
}
}
return temp;
}
My readFile method:
public static void readFile()
{
FileReader fileReader = null;
BufferedReader bufferedReader = null;
String InputFileName;
String nextLine;
clrscr();
System.out.println("Please enter the name of the file that is to be READ (e.g. aFile.txt: ");
InputFileName = Genio.getString();
try
{
fileReader = new FileReader(InputFileName);
bufferedReader = new BufferedReader(fileReader);
nextLine = bufferedReader.readLine();
while (nextLine != null)
{
System.out.println(nextLine);
nextLine = bufferedReader.readLine();
}
}
catch (IOException e)
{
System.out.println("Sorry, there has been a problem opening or reading from the file");
}
finally
{
if (bufferedReader != null)
{
try
{
bufferedReader.close();
}
catch (IOException e)
{
System.out.println("An error occurred when attempting to close the file");
}
}
}
}
Now I thought that I would just be able to call my readFile() method then go into the decipher code and it let work it's way through the file but I cannot get it to work at all.
In readFile() you aren't doing anything with the lines you read, you aren't calling cipherDecipherString() anywhere.
Edit: You can add all the lines from the file to an array and return the array from the fuction. Then iterate through that array and decipher line by line
Change the readFile() return type to ArrayList;
ArrayList<String> textLines = new ArrayList<>();
while(nextLine != null) {
textLines.add(nextLine);
nextLine = bufferedReader.readLine();
}
return textLines;
Then in cipherDecipherString() call readFile().
ArrayList<String> textLines = readFile();
I want to read in a file and create a duplicate of the file but my code only write the last line in the file. How do I make so that whenever I call write(), it writes to a new line. I want to create a new file for the duplicate so I can't add true to FileWriter constructor.
This is my code:
//Create file reader
BufferedReader iReader = new BufferedReader(new FileReader(args[1]));
//Create file writer
BufferedWriter oWriter = new BufferedWriter(new FileWriter(args[2], true));
String strLine;
//reading file
int iterate = 0;
while((strLine = iReader.readLine()) != null) {
instructions[iterate] = strLine;
}
//creating duplicate
for(int i = 0; i < instructions.length; i++) {
if(instructions[i] != null) {
oWriter.write(instructions[i]);
oWriter.newLine();
} else {
break;
}
}
try {
iReader.close();
oWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
You are not incrementing iterate
int iterate = 0;
while((strLine = iReader.readLine()) != null)
{
instructions[iterate] = strLine;
iterate++;
}
You're not updating the index of the instructions array.
In addition, it's not immediately clear why you're copying the file this way anyway; why bother doing it line-by-line? Or just use a utility class, like from Apache Commons.