0

I'm trying to process an input file containing numbers that I must use for calculations and characters I need to use for comparisons. A quick example is a file like this:

6
foobar

and code like this:

n = readInInt
  while n > 0
    c = readInSingleChar
    if (c = 'f')
      doSomething
    n--

Currently I'm finding a lot of options on here and via Google, involving DataStream and BufferedReader and FileReader, but there seems like there are too many ways and I'm not sure they all work how I need them too. Please let me know if my need isn't clear.

In short, I need to read a file character by character, and interpret/use those that are numbers as ints, and those that are letters and symbols as chars.

What's the simplest way to do this? I know there are professional ways to do things, and "ok" ways to do things. This is for a one-time, hobby-like personal use thing and I'm not looking for solid or robust functionality. It just has to work alright.

Thanks!

Matthew
  • 13
  • 2
  • 5
  • 1
    Could you also put in some code that you have tried? Where are you facing a problem? Performance? Something else? – Sagar V Jul 28 '11 at 16:33
  • Do you have some lines of text and some of calculations (never mixing the two on one line)? Do you only have numbers on some lines, or numbers with "+" or "add"? – toto2 Jul 28 '11 at 16:40

2 Answers2

1

I feel the easiest way is to use StreamTokenizer This class gives you the utilities needed to parse ints or strings.

I would start with something like -

StreamTokenizer tokenizer = new StreamTokenizer(new BufferedReader(new FileReader("foo.in")));

while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {

                if (tokenizer.ttype == StreamTokenizer.TT_WORD)
                    // use tokenizer.sval
                else if (tokenizer.ttype == StreamTokenizer.TT_NUMBER)
                   // use tokenizer.nval
            }

Here is an example on how to use it. The above is a very common way for tokenizing files and reading char by char. You should of course use a FileReader or Buffer for performance reasons.

You can also use Scanner. Sample code would be like

Scanner s = new Scanner(file);
s.useDelimiter(""); // reads one char a time
while(s.hasNext()){
  if(s.hasNextInt(){
    // then do something with s.nextInt()
  }else{
    // then do something with s.next()
  }
}
Amir Raminfar
  • 32,592
  • 7
  • 83
  • 119
  • Also more help here http://stackoverflow.com/questions/2597841/scanner-method-to-get-a-char – Amir Raminfar Jul 28 '11 at 16:51
  • Great, I didn't know leaving the parameters for useDelimiter blank would do that. The only issue I have now is that it seems to break when it encounters a new line. How can I work around this? – Matthew Jul 28 '11 at 17:40
1

If you are looking for a simple solution, java.util.scanner would be a good thing to look at.

It has easy-to-use methods for reading in different data types (such as an int or a String).

The solutions you have found using I/O streams are a bit more complicated and probably not as useful for the task you have. They would work, though (and are great for larger-scale applications).

An example, using a custom delimiter:

Scanner s = new Scanner(new File("txtfile.txt");
s.useDelimeter(Pattern.compile("\n|"); //The newline character (\n) and null 
                                       //character are the delimeters.
while (s.hasNext()) {
    if (s.hasNextInt() {
        //Do something
    } else {
        //Handle characters
    }
}

(For reference: Pattern )

The problem with this direct approach is that it will not take multiple-digit integers.

Another approach would be to use the standard delimiter. Then, when you want to read characters, read the entire token in (in your example, you would read in "foobar") and then process each character individually in a loop.

String str = s.next();
for(char c : str.toCharArray()) {
    //handle characters
}
ty1824
  • 1,170
  • 9
  • 11
  • I was trying to use scanner originally, but I have a question. How do I make sure it only accepts one number, letter, or symbol at a time? The only thing I know about controlling input when reading from files is using delimiters. How would I ensure that when scanning in the letters as a string, that it's only taking in one letter and not a group of letters or a line? – Matthew Jul 28 '11 at 16:47
  • @Mathew, you need to use sc.useDelimiter(""). Look at my code for an example. – Amir Raminfar Jul 28 '11 at 16:51
  • The default delimiter character for Scanner is whitespace, defined by the [Character.isWhitespace()](http://download.oracle.com/javase/1,5.0/docs/api/java/lang/Character.html#isWhitespace(char) ) method. You can define it, as Amir just commented, as any character. – ty1824 Jul 28 '11 at 16:54
  • I can't comment on his post (not enough rep yet!) but in response to your last comment: the code is breaking at a newline because it is reading the newline character. You either will need to handle the newline character in your code or else use a custom delimeter pattern that also skips newline characters (I believe it would also break at a tab or other special characters). – ty1824 Jul 28 '11 at 18:52