Printing lines in reverse java

6.2k views Asked by At

I'm trying to wrap my head around a problem I have in a programming set.

We're supposed to write code that reads from a file and prints it out. I get that, I can do it.

What he wants us to do is have it print out in reverse.

the file reads:

abc
123
987

He wants:

987
123
abc

The code, as it is, is as follows:

{
    FileReader n=new FileReader("F:\\Java\\Set 8\\output1.txt");
    Scanner in=new Scanner(n);
    int l;
    while (in.hasNext())
    {
        l=in.nextInt();
        System.out.println(l);      
    }
    in.close(); 
}
}

Yes, I am using java.io.*; and Scanner.

What would be the simplest way to do this?

EDIT EDIT EDIT

Here's the improved code, where I try to put it into an array.

The data in the array isn't printing out.

public static void main(String[] args) throws IOException
{
    int[]Num=new int[20];
    Scanner in=new Scanner(new FileReader("F:\\Java\\Set 8\\output1.txt"));
    int k;
    for (k=0;k<20;k++)
    {
        Num[k]=in.nextInt();
    }
    //in.close();
    for (k=20;k<20;k--)
    {
        System.out.print(+Num[k]);
    }
    //in.close();   
}
8

There are 8 answers

0
Tuxxy_Thang On

try using org.apache.commons.io.input.ReversedLinesFileReader, it should do what you want.

0
Harish Sridharan On

The most simplest way is to construct a List and add each line to the list while reading from the file. Once done, print the list items in reverse.

Here is my version of code for your problem.

public static void main(String[] args) throws FileNotFoundException {

    FileReader n = new FileReader("/Users/sharish/Data/abc.xml");
    Scanner in = new Scanner(n);

    ArrayList<String> lines = new ArrayList<String>();

    while (in.hasNext()) {
        lines.add(in.nextLine());
    }

    in.close();
    for (int i = lines.size() - 1; i >= 0; i--) {
        System.out.println(lines.get(i));
    }

}
0
trooper On

If you are permitted the use of third party APIs, Apache Commons IO contains a class, ReversedLinesFileReader, that reads files similar to a BufferedReader (except last line first). Here is the API documentation: http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/input/ReversedLinesFileReader.html

Another (less efficient) solution is hinted at in the comments. You can read your entire file into an ArrayList, reverse that list (e.g. by pushing its contents onto a stack and then popping it off), and then iterate through your reversed list to print.

EDIT: Here is a crude example:

ArrayList<String> lines = new ArrayList<String>();

Scanner in = new Scanner(new FileReader("input.txt"));
while (in.hasNextLine())
{
    lines.add(in.nextLine());
}

Use an ArrayList instead of a static array. We don't necessarily know the length of the file in advance so a static array doesn't make sense here. http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html

Your example input 123, abc, etc, contains characters as well as ints, so your calls to hasNextInt and nextInt will eventually throw an Exception. To read lines use hasNextLine and nextLine instead. These methods return String and so our ArrayList also needs to store String. http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#hasNextLine()

Once the file is in a list (not a good solution if the file is large - we've read the entire file into memory) we can either reverse the list (if keeping a reversed form around makes sense), or just iterate through it backwards.

for (int i=lines.size()-1; i>=0; i--)  // from n-1 downTo 0
{
    String line = lines.get(i);
    System.out.println( line );
}
0
jotadepicas On

You could read the lines like you are already doing, but instead of printing them (because that would print them in order and you need it the other way around), add them to some memory structure like a List or a Stack, and then, in a second loop, iterate this structure to print the lines in the needed order.

0
Mark On

Using your code and the answers in the comments, here's an example of how you would store the strings into the arraylist and then print them out in reverse (building off of your own code)

{
    FileReader n=new FileReader("F:\\Java\\Set 8\\output1.txt");
    Scanner in=new Scanner(n);
    int l;
    ArrayList<String> reversed = new ArrayList<String>(); // creating a new String arraylist
    while (in.hasNext())
    {
        l=in.nextInt();
        System.out.println(l);      
        reversed.add(l); // storing the strings into the reversed arraylist
    }
    in.close(); 
    // for loop to print out the arraylist in reversed order
    for (int i = reversed.size() - 1; i >= 0; i--) {
        System.out.println(reversed.get(i));
    }
}
}
0
Raman Shrivastava On

Use Stack.

public static void displayReverse() throws FileNotFoundException {
        FileReader n=new FileReader("C:\\Users\\User\\Documents\\file.txt");
        Scanner in=new Scanner(n);
        Stack<String> st = new Stack<String>();
        while (in.hasNext()) {
            st.push(in.nextLine());      
        }
        in.close(); 

        while(!st.isEmpty()) {
            System.out.println(st.pop());
        }
    }
0
Jean Logeart On

Using Java 8:

try(PrintWriter out = 
        new PrintWriter(Files.newBufferedWriter(Paths.get("out.txt")))) {
    Files.lines(Paths.get("in.txt"))
         .collect(Collectors.toCollection(LinkedList::new))
         .descendingIterator()
         .forEachRemaining(out::println);
}
0
Faheem Ahmad On
public static void main(String[] args) throws Exception{

    String fileName = "F:\\Java\\Set 8\\output1.txt";
    RandomAccessFile raf = new RandomAccessFile(fileName,"r");
    int len = (int) raf.length();
    raf.seek(len);

    while(len >= 0){
        if(len == 0){
            raf.seek(0);
            System.out.println(raf.readLine());
            break;
        }
        raf.seek(len--);
        char ch = (char)raf.read();
        if(ch == '\n'){
            String str = raf.readLine();
            System.out.println(str);
        }

    }
    
}