### wrick's blog

By wrick, history, 7 years ago,

In my previous post, I discussed a fast Scanner for Scala.

To benchmark it, I wrote the fastest possible Scanner I could in Java:

package better.files;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Arrays;

/**
* Hand built using a char buffer
*/
public class ArrayBufferScanner extends AbstractScanner {
private char[] buffer = new char[1 << 4];
private int pos = 0;

}

@Override
public boolean hasNext() {
return pos != -1;
}

pos = 0;
while (true) {
int i;
try {
} catch (IOException e) {
throw new UncheckedIOException(e);
}
if (i == -1) {
pos = -1;
break;
}
char c = (char) i;
if (c != ' ' && c != '\n' && c != '\t' && c != '\r' && c != '\f') {
if (pos == buffer.length) {
buffer = Arrays.copyOf(buffer, 2 * pos);
}
buffer[pos++] = c;
} else if (pos != 0) {
break;
}
}
}

@Override
public String next() {
return String.copyValueOf(buffer, 0, pos);
}

@Override
public String nextLine() {
try {
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

@Override
public int nextInt() {
int result = 0;
boolean didRun = false;
for (int i = buffer[0] == '-' || buffer[0] == '+' ? 1 : 0; i < pos; i++, didRun = true) {
int digit = buffer[i] - '0';
checkValidNumber(0 <= digit && digit <= 9);
result = result * radix + digit;
}
checkValidNumber(didRun);
return buffer[0] == '-' ? -result : result;
}

private void checkValidNumber(boolean condition) {
if(!condition) throw new NumberFormatException(String.copyValueOf(buffer, 0, pos));
}
}

Is this the best I can do?

It is barely faster than Java's StreamTokenizer (NOT StringTokenizer) inspite of being much simpler than it: http://docs.oracle.com/javase/8/docs/api/java/io/StreamTokenizer.html

Benchmark results: https://github.com/pathikrit/better-files/tree/master/benchmarks

• +6

 » 7 years ago, # |   0 You can do much better. Just take a look at what happens when you call nextInt() the first time. First the BufferedReader copies input to a buffer, then you copy that data to a new buffer, then you allocate a String object (not ideal if you only want a number) which essentially is just yet another buffer, then you actually parse the input.If you want to write your own efficient I/O class in Java, then byte[] and System.in.read will be your friends. If you think that's to much of a hassle, well then at least BufferedInputStream is preferable to BufferedReader (at least when it comes to reading integers).
•  » » 7 years ago, # ^ |   0 Ah, good point — I have not thought about optimizing the nextInt yet... Yes, this is purely an intellectual exercise at this point since it should be fast enough for CodeForces. Btw, what do you think of http://docs.oracle.com/javase/8/docs/api/java/io/DataInputStream.html ? I will include it in my benchmarks next.
•  » » » 7 years ago, # ^ |   0 I've actually never used it or evaluated its performance. But it does look promising indeed for your purposes.
•  » » 7 years ago, # ^ |   0 I just posted a version (see updated post) with updated nextInt() — much faster now. Anything else?
•  » » » 7 years ago, # ^ | ← Rev. 2 →   +5 Well there's really no point in using a buffer when you use BufferedReader, since it has its own buffer, so you unnecessarily end up doing the same work twice.As a reference I include below (more or less) the two classes I use for reading integers (most problems have integers as input) when I wanna make the highscore list on various online judges. BufferedInputStream based Array based method (do note that the buffer size has to be large enough to read the whole input of the problem in one go) So feel free to use them as inspiration when you design a more solid class with exception handling etc.
 » 7 years ago, # |   0 Not related to the post,but worth sharing.But I'd be careful when using Custom classes to read when the input is large ( especially on SPOJ and UVA). I remember one or two times where encapsulating a BufferedReader and StringTokenizer gave me TLE, yet them alone in the main method gave AC.Unless you are sure that your scanner is really significant for speed, don't use it when you need every second for your program.
•  » » 7 years ago, # ^ |   +5 What you are saying is basically "use this fast scanner of yours, but only if speed doesn't matter"
•  » » 7 years ago, # ^ |   0 As I said, at this point it's basically an intellectual exercise/code golfing. The regular Java one with BufferedReader + StringTokenizer should be just fine for every competition problems.And, yes, I do have tests for this: https://github.com/pathikrit/better-files/blob/master/benchmarks/src/test/scala/better/files/ScannerBenchmark.scala
•  » » » 7 years ago, # ^ | ← Rev. 2 →   0 I wasn't saying yours is slower, or not to use it. That's why I said it's not related to the post. It slowed me a lot sometimes when solving problems using JAVA so I thought it's worth sharing for JAVA users.
 » 7 years ago, # |   -18 Perform the following tasks: Write a program that calculates the area of a circle, use data type of double. Write a program to compute distance light travel in 1000 days using long variables. Write a program that accepts long text and a word. The program shows then number of word repetition and their positions. (hint use while loop and substring method). Write a program that accepts a number , the program uses for loop to find out if the number is a prime number or not. Write a program that reads a number "X", then the program calculates the following series : S = 1/2! — 1/3! + 1/4! – 1/5! + ……….. 1/X!, where 4! Is the factorial of 4 and it is equal to 4 *3*2*1> Write a program that accepts a number and prints the binary code of that number. (hint use loop and mode operator "%". Write a program for an online music and apps store offers all apps for 3$each and all songs for 7$ each. The store requires members to prepay any amount of money they wish, and then download as many apps or as many songs accordingly. You are required to write a program that would ask the user for the amount that he/she will pay, then display two messages indicating: the maximum number of apps that can be downloaded, and how much funds will remain in the account after that, if any
•  » » 7 years ago, # ^ |   0 I think this tutorial will help you: www.youtube.com/watch?v=dQw4w9WgXcQ
•  » » » 21 month(s) ago, # ^ |   0 ffs... this is the third time this happened to me. I think I'm taking you guys too seriously...ugggh
 » 7 years ago, # |   0 some times we just need nextInt , in such cases we can use only System.in and read integer very fast , here is my code that i write it before (3 years ago): http://ideone.com/00avHi really encourage you to test this (i love this problem , you will learn lots about I/O): http://www.spoj.com/problems/INTEST/