This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Replace first line of a text file in Java
Java - Find a line in a file and remove
I am trying to find a way to remove the first line of text in a text file using java. Would like to use a scanner to do it...is there a good way to do it without the need of a tmp file?
Thanks.
If your file is huge, you can use the following method that is performing the remove, in place, without using a temp file or loading all the content into memory.
public static void removeFirstLine(String fileName) throws IOException {
RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
//Initial write position
long writePosition = raf.getFilePointer();
raf.readLine();
// Shift the next lines upwards.
long readPosition = raf.getFilePointer();
byte[] buff = new byte[1024];
int n;
while (-1 != (n = raf.read(buff))) {
raf.seek(writePosition);
raf.write(buff, 0, n);
readPosition += n;
writePosition += n;
raf.seek(readPosition);
}
raf.setLength(writePosition);
raf.close();
}
Note that if your program is terminated while in the middle of the above loop you can end up with duplicated lines or corrupted file.
Scanner fileScanner = new Scanner(myFile);
fileScanner.nextLine();
This will return the first line of text from the file and discard it because you don't store it anywhere.
To overwrite your existing file:
FileWriter fileStream = new FileWriter("my/path/for/file.txt");
BufferedWriter out = new BufferedWriter(fileStream);
while(fileScanner.hasNextLine()) {
String next = fileScanner.nextLine();
if(next.equals("\n"))
out.newLine();
else
out.write(next);
out.newLine();
}
out.close();
Note that you will have to be catching and handling some IOExceptions this way. Also, the if()... else()... statement is necessary in the while() loop to keep any line breaks present in your text file.
Without temp file you must keep everything in main memory. The rest is straight forward: loop over the lines (ignoring the first) and store them in a collection. Then write the lines back to disk:
File path = new File("/path/to/file.txt");
Scanner scanner = new Scanner(path);
ArrayList<String> coll = new ArrayList<String>();
scanner.nextLine();
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
coll.add(line);
}
scanner.close();
FileWriter writer = new FileWriter(path);
for (String line : coll) {
writer.write(line);
}
writer.close();
If file is not too big, you can read is into a byte array, find first new line symbol and write the rest of array into the file starting from position zero. Or you may use memory mapped file to do so.
Related
I have a txt file and what I am trying to do is open it and delete all multiple spaces so they become only one. I use:
br = new BufferedReader(new FileReader("C:\\Users\\Chris\\Desktop\\file_two.txt"));
bw = new BufferedWriter(new FileWriter("C:\\Users\\Chris\\Desktop\\file_two.txt"));
while ((current_line = br.readLine()) != null) {
//System.out.println("Here.");
current_line = current_line.replaceAll("\\s+", " ");
bw.write(current_line);
}
br.close();
bw.close();
However, as it seems correct according to me at least, nothing is written on the file. If I use a system.out.println command, it is not printed, meaning that execution is never in the while loop... What do I do wrong? Thanks
you are reading the file and at the same time writing contents on it..it is not allowed...
so better way to read the file first and store the processed text in another file and finally replace the original file with the new one..try this
br = new BufferedReader(new FileReader("C:\\Users\\Chris\\Desktop\\file_two.txt"));
bw = new BufferedWriter(new FileWriter("C:\\Users\\Chris\\Desktop\\file_two_copy.txt"));
String current_line;
while ((current_line = br.readLine()) != null) {
//System.out.println("Here.");
current_line = current_line.replaceAll("\\s+", " ");
bw.write(current_line);
bw.newLine();
}
br.close();
bw.close();
File copyFile = new File("C:\\Users\\Chris\\Desktop\\file_two_copy.txt");
File originalFile = new File("C:\\Users\\Chris\\Desktop\\file_two.txt");
originalFile.delete();
copyFile.renameTo(originalFile);
it may help...
There are few problems with your approach:
Main one is that you are trying to read and write to same file at the same time.
other is that new FileWriter(..) always creates new empty file which kind of prevents FileReader from reading anything from your file.
You should read content from file1 and write its modified version in file2. After that replace file1 with file2.
Your code can look more or less like
Path input = Paths.get("input.txt");
Path output = Paths.get("output.txt");
List<String> lines = Files.readAllLines(input);
lines.replaceAll(line -> line.replaceAll("\\s+", " "));
Files.write(output, lines);
Files.move(output, input, StandardCopyOption.REPLACE_EXISTING);
You must read first then write, you are not allowed to read and write to the same file at the same time, you would need to use RandomAccessFile to do that.
If you don't want to learn a new technique, you will need to either write to a separate file, or cache all lines to memory(IE an ArrayList) but you must close the BufferedReader before you Initialize your BufferedWriter, or it will get a file access error.
Edit:
In case you want to look into it, here is a RandomAccessFile use case example for your intended use. It is worth pointing out this will only work if the final line length is less than or equal to the original, because this technique is basically overwriting the existing text, but should be very fast with a small memory overhead and would work on extremely large files:
public static void readWrite(File file) throws IOException{
RandomAccessFile raf = new RandomAccessFile(file, "rw");
String newLine = System.getProperty("line.separator");
String line = null;
int write_pos = 0;
while((line = raf.readLine()) != null){
line = line.replaceAll("\\s+", " ") + newLine;
byte[] bytes = line.getBytes();
long read_pos = raf.getFilePointer();
raf.seek(write_pos);
raf.write(bytes, 0, bytes.length);
write_pos += bytes.length;
raf.seek(read_pos);
}
raf.setLength(write_pos);
raf.close();
}
I have a sentence in my text file,
Moreover, human serum could significantly enhance the LPS-induced DV suppression in a CD14-dependent manner, indicating that the "binding" of LPS to CD14 was critical for the induction of virus inhibition.
How do I replace the 2nd occurrence of CD14 to AB45 and write back to the text file?
For the algorithm itself,
file.indexOf("CD14", file.indexOf("CD14")+4)
can be used to locate the occurance (given that "file" is a string with all of the contents of your file). The second argument of "indexOf" asks for a start point. By calling indexOf twice, you find the first instance of the string than check for another instance skipping past the first instance (+4 since indexOf will return the start of the string, adding the length of the string skips over it). To replace the string,
int i = file.indexOf("CD14", file.indexOf("CD14")+4);
String s = file;
if(i != -1) s = file.substring(0,i) + "AD25" + file.substring(Math.min(i+4,file.length()), file.length());
If you're asking how to read/write a text file, try google. one example - Java: How to read a text file , another - http://www.javapractices.com/topic/TopicAction.do?Id=42
There are several approaches to take in solving this one. A very simple but verbose approach would be:
public static void replaceSecondOccurence(String originalText, String replacementText) throws IOException {
File file = new File("file.txt");
InputStreamReader reader = new InputStreamReader(new FileInputStream(file));
StringBuilder fileContent = new StringBuilder();
int content;
while ((content = reader.read()) != -1) {
fileContent.append((char) content);
}
reader.close();
int index = fileContent.lastIndexOf(originalText);
fileContent.replace(index, index + originalText.length(), replacementText);
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file));
writer.write(fileContent.toString());
writer.close();
}
I wrote this code and I think I went to the last line of the code while using line=input.nextLine(). Now I don't know how do I get back to the first line of the text file again. I am not allowed to read the file again.
File file = new File(fileName);
input = new Scanner(file);
bufRdr = new BufferedReader(new FileReader(file));
this.cols=bufRdr.readLine().length();
while (input.hasNext()){
this.rows++;
line=input.nextLine();
}
theMaze=new char[this.rows][this.cols];
int i=0;
while(i<this.rows){
line=input.nextLine();
for (int j=0;j<this.cols;j++){
theMaze[i][j]=line.charAt(j);
}
i++;
}
} catch(Exception e){
System.out.println("Error......" +e.getMessage());
}
You have to use RandomAccessFile and use seek to get to the top. BufferedReader reads sequentially; you cannot jump. You should check mark method of BufferedReader.
You don't need to. Instead of a 2-dimensional array of characters, you should use an ArrayList of Strings. ArrayLists can grow on demand, so with them, you only need to read through the file once - you don't need to count the number of lines first:
ArrayList<String> lines = new ArrayList<String>();
while (input.hasNext()) {
lines.add(input.nextLine());
}
I would like to receive some suggestions regarding a little problem I am going to solve in Java.
I have a file consisting in this format:
#
some text
some text
some text
#
some text
some text
some text
#
some text
some text
some text
...and so on.
I would need to read the next chunk of this text file, then to create an InputStream object consting of the read chunk and to pass the InputStream object to a parser. I have to repeat these operations for every chunk in the text file. Each chunk is written between the lines starting with #. The problem is to parse each section between the # tags using a parser which should read each chunk from an InputStream.
The text file could be big, so I would like to obtain good performance.
How could I solve this problem?
I have thought about doing something like this:
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
Scanner scanner = new Scanner(bufferedReader);
scanner.useDelimiter("#");
List<ParsedChunk> parsedChunks = new ArrayList<ParsedChunk>();
ChunkParser parser = new ChunkParser();
while(scanner.hasNext())
{
String text = scanner.next();
InputStream inputStream = new ByteArrayInputStream(text.getBytes("UTF-8"));
ParsedChunk parsedChunk = parser.parse(inputStream);
parsedChunks.add(parsedChunk);
inputStream.close();
}
scanner.close();
but I am not sure if it would be a good way to do it.
Thank you.
If I have understood correctly. This is what you are trying to achieve. FYI you will need JAVA 7 to get the below code running
public static void main(String[] args) throws IOException {
List<String> allLines = Files.readAllLines(new File("d:/input.txt").toPath(), Charset.defaultCharset());
List<List<String>> chunks = getChunks(allLines);
//Now you have all te chunks and you can process them
}
private static List<List<String>> getChunks(List<String> allLines) {
List<List<String>> result = new ArrayList<List<String>>();
int i = 0;
int fromIndex = 1;
int toIndex = 0;
for(String line : allLines){
i++;
if(line.startsWith("****") && i != 1){ // To skip the first line and the check next delimiter
toIndex = i-1;
result.add(allLines.subList(fromIndex, toIndex));
fromIndex = i;
}
}
return result;
}
didnt quite get the question but u could try using char at this moment as, storing all the character in char array & going thhrough a loop & condiional statement which breaks the string every time it encounters a'#'
FileInputStream fstream = new FileInputStream("\\file path");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while (br.ready()) {
line = br.readLine();
}
Please let me know how to read a file from the last line to first provided the row number is not fixed and is varying with time? I know the above is useful for reading it from first row...
This might be helpfull for you [1]: http://mattfleming.com/node/11
read the file into a list, and process that list backwards...
files and streams are usually designed to work forward; so doing this directly with streams might turn out a lite awkward. Only advised when the files are really huge...
You cannot read a Buffer backwards, you can however count the lines of your buffer as explained in the link below
http://www.java2s.com/Code/Java/File-Input-Output/Countthenumberoflinesinthebuffer.htm
And afterwards select your line using this code:
FileInputStream fs= new FileInputStream("someFile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
for(int i = 0; i < 30; ++i)
br.readLine();
String lineIWant = br.readLine();
As you can see, you iterate, reading each line(and doing nothing) before you get to the one you want (here we got 31 lines passed and #32 is the one read). If your file is huge this will take a lot of time.
Other way to to this is to input everything in a List and then with a sizeof() and a for() you can select everything you want.
If you know the length of each line then you can work out how many lines there are by looking at the size of the file and dividing by the length of each line. (this of course ignores any possible metadata in the file)
You can then use some maths to get the start byte of the last line. Once you have then you can then open a RandomAccessFile on the file and then use seek to go to that point. Then using readline you can then read the last line
This does assume though that the lines are all the same length.
You can use FileUtils
and use this method
static List<String> readLines(File file)
Reads the contents of a file line by line to a
List of Strings using the default encoding for the VM.
This will return a List then use Collections.reverse()
Then simply iterate it to get the file lines in reverse order
Just save info backwards, that's all I did.just read Pryor to save and use \n
You can save the lines in a list (in my code a arraylist) and "read" the lines backwards from the arraylist:
try
{
FileInputStream fstream = new FileInputStream("\\file path");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = "";
ArrayList<String> lines = new ArrayList<String>();
//Read lines and save in ArrayList
while (br.ready())
{
lines.add(br.readLine());
}
//Go backwards through the ArrayList
for (int i = lines.size(); i >= 0; i--)
{
line = lines.get(i);
}
}
catch (Exception e)
{
e.printStackTrace();
}