I want to read a file in java. And then, I want to delete a line from that file without the file being re-written.
How can I do this?
Someone suggested me to read/write to a file without the file being re-written with the help of RandomAccessFile. How to write data to a file through java?
Specifically, that files contains lines. One line contains three field - id, name and profession - separated by \t. I want to read that file through a Reader or InputStream or any other way and then search for a line that has the specified keyword (say 121) and then wants to delete that whole line.
This operation needs to be performed without the whole file being re-written
I don't think you can alter a file on a filesystem in any way without writing to it, including deleting a line.
Do you mean you want to write the file without altering the file's metadata, like the last modified time?
Based on your updated question:
I don't think you can do what you're asking to do here. You can't remove bytes from a file once the file has been written, note no deleteByte or removeByte methods in RandomAccessFile.
I suggest moving the content of your file to a database - that allows this kind of record-oriented operation.
The alternative is, you have to rewrite the file. Sorry!
"Lines" are an abstract concept -- they're just an arbitrary sequence of bytes terminated by "\n". BufferedWriters and their ilk don't support textual editing in this way, so you'll have to rewrite the file in its entirety.
In general, what you want to do is:
open a reader
read content into some suitable data structure
close the reader
change data/records which need to be changed in this data structure
open a FileWriter with append == false
write content of data structure to resulting file
close FileWriter
add a marker in your lines saying if your line is deleted or not : this will make a software delete instead od a hardware delete.
if you have to insert new lines, you then can reuse those that are marked as deleted.
The below code searchs the line or fields in a single text file reads the file line by line
then the line or fields can be replaced by " " or any other string. Here we use the pattern and Matcher classes.
If this not clearing your question do let me know.
import java.io.;
import java.util.regex.;
import java.util.Properties;
public class DeleteLine
{
public static void main(String[] args)
{
BufferedReader br = null;
try
{
String line=null;
File f = new File("d:/xyz.txt");
String replaceString=properties.getProperty("replaceAll.String");
;
br = new BufferedReader(new FileReader("d:/giri/scjp/");
while ( (line = br.readLine()) != null )//BufferedReader contains readline method
{
Pattern p=Pattern.compile(searchString);/*here u an specify the line u want to delete */
Matcher m=p.matcher(line);
line=m.replaceAll(replaceString);/*here replace String u can " " so that it will be emptied */
System.out.println(line);
}
//System.out.println(line);
}
}
}
br = new BufferedReader(new FileReader("d:/xyz.txt"));
String line = null;
}
catch (FileNotFoundException e)
{
System.out.println("File couldnt find");
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
Related
I have two csv files
File 1:
ID,NAME
1,FOO
2,BAR
3,XYZ
File 2:
ID,NAME,DOB
3,XYZ,02/03/1999
4,BAR,01/01/1995
1,FOO,01/01/1996
How can I select rows from CSV File 2 which has columns ID,NAME value matched in File 1 in java language.
Expected Result:
ID,NAME,DOB
3,XYZ,02/03/1999
1,FOO,01/01/1996
Basically you want to perform Vlookup operation .
You can get desired outcome by using Apache POI library. This library provides set of methods to perform Vlookup.
You can refer to the below resources for detailed understanding.
https://poi.apache.org/apidocs/dev/org/apache/poi/ss/formula/functions/Vlookup.html
There are a lot of API's that support functions like comparing .csv files. However, Java also has its own ways to do this.
I'll explain it step by step:
First, you should read the two files into the program. java.io provides some classes with this functionality.
Then, after the content of both files is stored in an appropriate data structure, you can compare them.
You can then simply store the matching lines in another data structure and return them.
Last but not least, you also have to write to a new or already existing file using classes from java.io.
Here is a method to read in files:
public ArrayList<String> readInFile(String absoluteFilePath) {
BufferedReader reader = null;
ArrayList<String> csvContent = new ArrayList<>();
String currentLine;
try {
reader = new BufferedReader(new FileReader(absoluteFilePath));
while((currentLine = reader.readLine()) != null) {
csvContent.add(currentLine);
}
reader.close();
}
catch (Exception e) {
e.printStackTrace();
}
return csvContent;
}
The method uses a BufferedReader to read the file and adds it line by line to the ArrayList
Writing to a .csv file is just as easy as reading from one. You just have to decide whether you want to write to an existing file or to a file that already exists.
Here is a method to write into files:
public void writeToFile(ArrayList<String> csvContent, String absoluteFilePath) {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(absoluteFilePath));
for (int i = 0; i < csvContent.size(); i++) {
writer.write(csvContent.get(i) + "\n");
}
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
This method uses a BufferedWriter to either create a file at the given path or overwrite an existing one and writes the contents of the ArrayList into the file.
Good luck!
I have to modify a text file in java.
eg this is the file before modify
line
line
line
line
line
line
and after it should look like:
line
line
this is another
line
line
line
line
So don't write over anything, only add a line between the 2. and 3. line, and the original 3. line will be the new 4. line.
A way is to make a temp file, write every line in it, and where I want to modify I do the modification. Than delet the original, and rename the temp file. Or read the temp file and write it to te original file.
But is there any way to read and modify a file like I want using the same class in java?
thx!
You can read and modify to and from a file in Java at the same time. The problem you have though is that you need to insert data here, in order to do that everything after the new line needs to be shuffled down and then the length of the file extended.
Depending on exactly what and why you are trying to do there are a number of ways to do this, the easiest is probably to scan the file copying it to a new location and inserting the new values as you go. If you need to edit in place though then it's more complicated but essentially you do the same thing: Read X characters to a buffer, overwrite the X characters in the file with the new data, read next X characters. Overwrite the just-read characters from the first buffer. Repeat until EOF.
Think of files on disk as arrays - if you want to insert some items into the middle of an array, you need to shift all of them to make room.
The only safe way is to create a new temp file, copy the old file line by line and then rename it, just as you suggested. By updating the same file directly on the disk you risk losing the data if anything goes wrong and you would use a lot of memory.
Try this:
public void writeAfterNthLine(String filename, String text, int lineno) throws IOException{
File file = new File(filename);
File temp = File.createTempFile("temp-file-name", ".tmp");
BufferedReader br = new BufferedReader(new FileReader( file ));
PrintWriter pw = new PrintWriter(new FileWriter( temp ));
String line;
int lineCount = 0;
while ((line = br.readLine()) != null) {
pw.println(line);
if(lineCount==lineno){
pw.println(text);
}
lineCount++;
}
br.close();
pw.close();
file.delete();
temp.renameTo(file);
}
The code is not tested, but it should work, you can improve the code with several validations and exception handling
I have two different ways to read the file but I am not sure how to proceed to converting the text to a string and then an if then statement like...
if string contains ":"
true string = "string"
false string = ,,"string"
package test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class ReadStringFromFileLineByLine {
public static void main(String[] args) {
try {
File file = new File("foo.txt");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuffer stringBuffer = new StringBuffer();
String line;
String trim;
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line);
stringBuffer.append("\n");
}
fileReader.close();
System.out.println("Contents of file:");
System.out.println(stringBuffer.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
But I don't believe I am using the trim command appropriately
Your question doesn't really communicate clearly the intent of the program. What exactly are you trying to do? If your file is text-based, there is no "conversion to String" needed. Also "save the file as an output" isn't clear either. Do you want to save a new file, overwrite the existing file, or append the existing file. All of these scenarios are handled differently. Taking this by parts:
First point: Your Scantest class works. Given a file foo.txt in the project folder, the class will print out the contents of the file.
Second point: Your class ReadStringFromFileLineByLine works with my own foo.txt just like the first class. So, there might be something wrong with your test.txt file. This is probably the most important thing when testing (making all conditions equal). If the conditions for testing are not equal, the tests will most likely be inconclusive (which is why I suspect happened in your case).
Third point: None of your classes attempted to make any modifications to the obtained strings or made modifications to the file. If you were to write to a file, you have to consider the following: Append vs. Overwrite. All it takes is the use of a simple boolean value:
FileWriter fw = new FileWriter(file.getAbsoluteFile()); // overwrites contents of file
FileWriter fw = new FileWriter(file.getAbsoluteFile(), true); // appends to file
The FileWriter single argument contructor calls the two-argument constructor passing false to it. Therefore, the FileWriter overwrites instead of appends. This is important because if you handle the file line by line, it is possible that at the end, your file will contain only the last line you "modified." If you choose to append, the new String will be added to the end of the line. So this is not good either. If you want to process a file line by line, made modifications to any given line, AND save the line to the same file, your best option is to use RandomAccessFile. This class allows you to write 'X' number of characters starting on a given offset. In this case, this "offset" is the "address" of the current line; putting it simply: the offset is equal to the number of characters already processed. So, for the first line, the offset is 0, for line 2 is the number of characters in line 1, and so forth.
I can add this as an update if you need it, but I did not see anything in your code that attempted to change the file in any way. I was just going by your title.
I have to modify a text file in java.
eg this is the file before modify
line
line
line
line
line
line
and after it should look like:
line
line
this is another
line
line
line
line
So don't write over anything, only add a line between the 2. and 3. line, and the original 3. line will be the new 4. line.
A way is to make a temp file, write every line in it, and where I want to modify I do the modification. Than delet the original, and rename the temp file. Or read the temp file and write it to te original file.
But is there any way to read and modify a file like I want using the same class in java?
thx!
You can read and modify to and from a file in Java at the same time. The problem you have though is that you need to insert data here, in order to do that everything after the new line needs to be shuffled down and then the length of the file extended.
Depending on exactly what and why you are trying to do there are a number of ways to do this, the easiest is probably to scan the file copying it to a new location and inserting the new values as you go. If you need to edit in place though then it's more complicated but essentially you do the same thing: Read X characters to a buffer, overwrite the X characters in the file with the new data, read next X characters. Overwrite the just-read characters from the first buffer. Repeat until EOF.
Think of files on disk as arrays - if you want to insert some items into the middle of an array, you need to shift all of them to make room.
The only safe way is to create a new temp file, copy the old file line by line and then rename it, just as you suggested. By updating the same file directly on the disk you risk losing the data if anything goes wrong and you would use a lot of memory.
Try this:
public void writeAfterNthLine(String filename, String text, int lineno) throws IOException{
File file = new File(filename);
File temp = File.createTempFile("temp-file-name", ".tmp");
BufferedReader br = new BufferedReader(new FileReader( file ));
PrintWriter pw = new PrintWriter(new FileWriter( temp ));
String line;
int lineCount = 0;
while ((line = br.readLine()) != null) {
pw.println(line);
if(lineCount==lineno){
pw.println(text);
}
lineCount++;
}
br.close();
pw.close();
file.delete();
temp.renameTo(file);
}
The code is not tested, but it should work, you can improve the code with several validations and exception handling
public static void main(String args[])
{
try
{
File file = new File("input.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = "000000", oldtext = "414141";
while((line = reader.readLine()) != null)
{
oldtext += line + "\r\n";
}
reader.close();
// replace a word in a file
//String newtext = oldtext.replaceAll("drink", "Love");
//To replace a line in a file
String newtext = oldtext.replaceAll("This is test string 20000", "blah blah blah");
FileWriter writer = new FileWriter("input.txt");
writer.write(newtext);writer.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
A couple suggestions on your sample code:
Have the user pass in old and new on the command line (i.e., args[0] and args1).
If it's sufficient to do this a line at a time, it's going to be much more efficient to read a line, replace old -> new, then stream it out.
Also check out StringUtils and IOUtils, which may make your life easier in this case.
Easiest is the String.replace(oldstring, newstring), or String.replaceAll(regex, newString) function, you can just read the one file and write the replacement into a new file (or do it line by line if you're concerned about file size).
After reading your last comment - that's a totally different story... the preferred solution would be to parse the css file into an object model (like DOM), apply the changes there and serialize the model to css afterwards. It's much easier to find all color attributes in DOM and change them compared to doing the same with search and replace.
I've found some CSS parser in the wild wild web, but none of them looked like being capable of writing CSS files.
If you wanted to replace the color names with search and replace, you'd search for 'color:<colorname>' and replace it with 'color:<youHexColorValue>'. You may have to do the same for 'color:"<colorname>"', because the color name can be set in double quotes (another argument for using a CSS parser..)
String.replaceAll() is the easiest way to do it. Just read the complete CSS file into one String, replace all as suggested above and write the new String to the same (or a temporary) file (first).