4

I have the following function , which counts the lines in a simple file. This file is consisting of integers separated by newlines , but the problem is that it's going one character at a time. And so if the last line has 2 digits, it will only return the 2nd digit as the final output:

Here is my code :

public static int countLines(String filename) throws IOException {
    InputStream is = new BufferedInputStream(new FileInputStream(filename));


    try {
        byte[] c = new byte[1024];
        int count = 0;
        int readChars = 0;
        int lastline = 0;

       boolean empty = true;
       while (  (readChars = is.read(c))  != -1) {

         //System.out.println (" The array is + readChars " + readChars + " !!!" );

            for (int i = 0; i < readChars; ++i){
                Byte b  = c[i];
                int xx = b.intValue();
                lastLine =  xx; 

                if (c[i] == '\n'){
                    ++count;
                    empty = true;

                } else {

                    empty  = false;
                }      
            }   // END inner- FOR-LOOP  

       }// END WHILE-LOOP
        if (!empty) {
        count++;
       }


   int asciiVal  = lastLine;
   int lastLine2 = Character.getNumericValue(asciiVal);
   System.out.println("the last line was "  + lastLine2);

   return count;


    } finally {
        is.close();
    }

}//END method countLines

Here's a sample text file of the input it's reading :

1
2
3
4
5
6
7
8
9
17

any tips appreciated. I want to learn better Java encoding, IO, etc topics related to this also. thank

Caffeinated
  • 11,982
  • 40
  • 122
  • 216

2 Answers2

2

Using a Scanner as opposed to your InputStream to read in lines and count/print them out could be done as so.

Scanner scan = new Scanner(System.in);
// All your stuff up until the while loop
while (scan.hasNext()) {
     if (sc.nextLine().equals("")) break;
     System.out.println (" The array is + scan.nextInt() " + readChars + " !!!" );
     count++;
}

The above would go through all lines in a text file (that contains only numbers) and prints them out and adds to count for each line passed (including the last line if there are numbers on it). Also with the above there is no need for the boolean empty.

BufferedReader uses slightly less memory than Scanner but Scanner is much easier to work with. I have no experience with InputStream as a method of scanning in input.

EDIT: Here is a BufferedReader example because I am bored. You will either need to add throws declarations or use a try-catch (shown) in order to use a BufferedReader.

    BufferedReader buff = new BufferedReader (new InputStreamReader(System.in));
    // All your stuff up until the while loop
    try {
        String read = buff.readLine();
        while (read.equals("") == false && read.equals("\n") == false) {

            int nextInt = Integer.parseInt(read);
            System.out.println (" The array is + scan.nextInt() " + nextInt + " !!!" );
             count++;
            read = buff.readLine();

        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

As you can see significantly more code is required for the BufferedReader but it is all really just preference.

Getting the last line in the file would just require minor modification. You would just keep track of each int as you go through them all and for each new int you scan in you write over the previous one and so fourth. When you run out of lines the int currently held in your variable would be the last one.

brettfazio
  • 1,136
  • 10
  • 25
  • BufferedReader.readLine returns null on end of input, not empty string. You'd get empty string on a line that just contains a line terminator. – pvg Dec 01 '15 at 02:22
  • Just tested it and it worked, will add a check for a new line character though. – brettfazio Dec 01 '15 at 02:24
  • Not exactly sure why he was using that in his code, but if he needs it, it is just a copy-paste and minor adjustment. @ApproachingDarknessFish – brettfazio Dec 01 '15 at 02:27
  • You don't need to add a check for new line, you'd never get it from readLine. Take a look at the docs, the terminating condition is 'returning null'. – pvg Dec 01 '15 at 02:28
  • @brettf put an empty line in the middle of your test input and check what happens. – pvg Dec 01 '15 at 02:31
  • Why a down vote, but no explanation for the down vote? – brettfazio Dec 02 '15 at 22:35
2

I prepared solution which is probably nearest to yours (in terms to editing distance)

import java.io.*;

public class Main {

    public static int countLines(String filename) throws IOException {
        InputStream is = new BufferedInputStream(new FileInputStream(filename));


        try {
            byte[] c = new byte[1024];
            int count = 0;
            int readChars = 0;
            int lastLine = 0;
            int lastNumber = 0;

            boolean empty = true;
            while (  (readChars = is.read(c))  != -1) {

                for (int i = 0; i < readChars; ++i){
                    Byte b  = c[i];
                    lastLine = b.intValue() - 48;

                    if (empty) {
                        lastNumber = 0;
                    }

                    if (c[i] == '\n'){
                        ++count;
                        empty = true;

                    } else {
                        lastNumber *= 10;
                        lastNumber += lastLine;
                        empty  = false;
                    }
                }   // END inner- FOR-LOOP

            }// END WHILE-LOOP
            if (!empty) {
                count++;
            }


            int asciiVal  = lastLine;
            int lastLine2 = Character.getNumericValue(asciiVal);
            System.out.println("the last line was "  + lastNumber);

            return count;


        } finally {
            is.close();
        }

    }//END method countLines

    public static void main(String[] args) throws IOException {
        System.out.print(countLines("/tmp/test.txt"));
    }
}

What happens here:

  • I'm reading as you do char by char
  • Because c[i] is ASCII byte intValue() return it's ASCII value. To get "real" value of this particular digit i reduce it with ASCII code of 0. E.g., for intValue() of '5' is 53 when we substract 48 (intValue() of '0') we get 5
  • Because we use decimal system to "add" new digit on the right, we need to multiply whole number by 10 and then add that digit
  • When new line is detectedm lastNumber is set to 0

This solution is not best, nor bullet proof. What happen when file does not exist, or contains letters? Probably Scanner is better tool for this. If you wan't to learn basics I really encourage you to take a look at CodeWars

janisz
  • 6,292
  • 4
  • 37
  • 70