how to read file from last line to first using java - java

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();
}

Related

Java - open txt file and clear all multiple spaces

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();
}

How to go back to the first line in a text file without reading it again?

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());
}

Java - printing lines from buffered reader

I'm writing an InputStream that supplies lines from a file in constant intervals. I used BufferedReader before, but ran into buffering issues with it (wasn't getting anything until the entire file was read), and speed isn't an issue anyways (the intervals are something like every second, or every half second - along those lines). Is there a class with a readLine method like in BufferedReader, except unbuffered?
(Edit: I just checked - my class seems to work, apparently the problem was with the output)
Here's the code where I used the stream (OnlineDataSimulator). I already checked, the stream does exactly what I want, so apparently I'm doing something wrong with the output. (The actual problem is, I want output to occur every X milliseconds - X being the second parameter to OnlineDataSimulator. What happens when I run this code is, that I first get an X*lines wait and then the entire output at once instead.)
System.out.println("Testing:");
PrintStream fout = new PrintStream(new FileOutputStream("testfile"));
for(int i=0; i<20; ++i) {
fout.println(i);
}
fout.close();
BufferedReader fin = new BufferedReader(new InputStreamReader(
new OnlineDataSimulator("testfile",250)));
String line;
while((line=fin.readLine())!= null){
System.out.println(line);
System.out.flush();
}
fin.close();
(new File("testfile")).delete();
Try it this way.... This worked for me..
File f = new File("path");
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
String s = null;
while ((s=br.readLine())!=null)
{
System.out.println(s);
}
No, there is no other non-buffered option.
A solution would be to write your own Reader which has a InputStreamReader as an underlying stream and in the readLine() method you should call read() of the underlying input stream reader until "\n" is found. Aggregate all these and return them as a string.
If you don't want to have a real buffer but want to use the functionality of BufferedReader you could initialize it with buffer size 1. As you commented that speed isn't an issue maybe is the most reliable solution.
new BufferedReader(reader, 1)
public BufferedReader(Reader in, int sz)
and you can check the readLine() method source code here, in case you want to implement your own.

Special characters from txt file

I am downloading a text file from ftp, with common ftp library.
The problem is when i read the file into an array line by line, it doesnt take characters such as æøå. Instead it just show the "?" character.
Here is my code
FileInputStream fstream = openFileInput("name of text file");
BufferedReader br = new BufferedReader(new InputStreamReader(fstream, "UTF-8"));
String strLine;
ArrayList<String> lines = new ArrayList<String>();
while ((strLine = br.readLine()) != null) {
lines.add(strLine);
}
String[] linjer = lines.toArray(new String[0]);
ArrayList<String> imei = new ArrayList<String>();
for(int o=0;o<linjer.length;o++)
{
String[] holder = linjer[o].split(" - ");
imei.add(holder[0] + " - " + holder[2]);
}
String[] imeinr = imei.toArray(new String[0]);
I have tried to put UTF-8 in my inputstreamreader, and i have tried with a UnicodeReader class, but with no success.
I am fairly new to Java, so might just be some stupid question, but hope you can help. :)
There is no reason to use a DataInputStream. The DataInputStream and DataOutputStream classes are used for serializing primitive Java data types ("serializing" means reading/writing data to a file). You are just reading the contents of a text file line by line, so the use of DataInputStream is unnecessary and may produce incorrect results.
FileInputStream fstream = openFileInput("name of text file");
//DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(fstream, "UTF-8"));
Professional Java Programmer Tip: The foreach loop was recently added to the Java programming language. It allows the programmer to iterate through the contents of an array without needing to define a loop counter. This simplifies your code, making it easier to read and maintain over time.
for(String line : linjer){
String[] holder = line.split(" - ");
imei.add(holder[0] + " - " + holder[2]);
}
Note: Foreach loops can also be used with List objects.
I would suggest that the file may not be in UTF-8. It could be in CP1252 or something, especially if you're using Windows.
Try downloading the file and running your code on the local copy to see if that works.
FTP has two modes binary and ascii. Make sure you are using the correct mode. Look here for details: http://www.rhinosoft.com/newsletter/NewsL2008-03-18.asp

Read last n line from url stream problem

I have problem to read last n lines from url. How to do that ? I have url.openstream but there is no contrsuctor for RandomAccessFile which has input for stream. Can somebody help me ? Is there meybe already library for this. ( I know how to implement with RandomAccess when I have file but how to change stream to file ).
Open the URL stream as per usual.
Wrap the returned InputStream in a BufferedReader so you can read it line by line.
Maintain a LinkedList into which you will save the lines.
After reading each line from the BufferedReader:
Add the line to the list.
If the size of the list is greater than "n" then call LinkedList#removeFirst().
Once you have read all lines from the stream the list will contain the last "n" lines.
For example (untested, just for demonstration):
BufferedReader in = new BufferedReader(url.openStream());
LinkedList<String> lines = new LinkedList<String>();
String line = null;
while ((line = in.readLine()) != null) {
lines.add(line);
if (lines.size() > nLines) {
lines.removeFirst();
}
}
// Now "lines" has the last "n" lines of the stream.
Sorry. You're going to have to do this one yourself. But don't worry because it's pretty simple.
You just need to keep track of the last n lines you have encountered since you started reading from the UrlStream. Might I suggest using a Queue?
Basically you could do something like
public String[] readLastNLines(final URL url, final int n) throws IOException{
final Queue<String> q = new LinkedList<String>();
final BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
String line=null;
while ((line = br.readLine())!=null)
{
q.add(line);
if (q.size()>n) q.remove();
}
return q.toArray(new String[q.size()]);
}
readLastNLines returns an array containing the last n lines read from url.
Unfortunately, you cannot use a RandomAccessFile with a stream from the Internet because streams are, by definition, not random access.

Categories