1
\$\begingroup\$

I've got this function which reads an entry until the next starting Token determined through a function, as the nature of the token is flexible.

Usage:

// pattern is java.util.regex.Pattern object determined in function of the file which is read
Function<String, Boolean> startToken = s -> pattern.matcher(s).matches();

line = readNext(reader, startToken)

Implementation:

protected static String readNext(BufferedReader reader, Function<String, Boolean> startToken)
    throws IOException
{
    StringBuilder buf = new StringBuilder();
    String line = null;
    while (true)
    {
        reader.mark(81940);
        line = reader.readLine();

        if (line == null)
        {
            if (buf.length() > 0)
            {
                return buf.toString();
            }
            else
            {
                return null;
            }
        }

        if (startToken.apply(line))
        {
            if (buf.length() > 0)
            {
                reader.reset();
                return buf.toString();
            }
            else
            {
                buf.append(line);
            }
        }
        else
        {
            buf.append("\n" + line);
        }
    }
}

I have a concern with the usage of the readAheadLimit for the BufferedReader, as I needed already in the past to up the limit, and again recently, and I wonder if there would be any problem which would occur, were I to put the limit to an high number. but until now, I didn't have any luck in my search.

If it isn't an issue, can I set the limit dynamically depending on the file which is read?

\$\endgroup\$
2
  • 4
    \$\begingroup\$ It seems that you need help in figuring out how BufferedReader works. That means you don't quite know if your code is working and thus the question would belong to stackoverflow.com. \$\endgroup\$ Commented Mar 25, 2022 at 10:52
  • \$\begingroup\$ @TorbenPutkonen The code has been productive and working since a while, and I just up the limit to make it work in one case. So I do know it works, and understand roughly how it does it. I'm just not aware of the intricacies there might be and I must admit I never searched for any alternatives. In the end, I just want to future-proof my code. \$\endgroup\$
    – Eldros
    Commented Mar 25, 2022 at 14:23

2 Answers 2

1
\$\begingroup\$

You can use Predicate in place of a Function that returns Boolean - it's the same thing, but makes the intent a little more obvious to those who are comfortable with the terms.

Consider whether this should take a Reader instead of specifically a BufferedReader. You would need to check if markSupported() and document that it throws an exception if not. But then potentially it can be used with other types of Reader.

And another small style adjustment, which might be subjective, is to put the base case at the end of a function or block. I think with a small change, shown below, it can be a little clearer what the result of calling the function is: the reader is reset and the contents of the buffer are returned.

And in the loop, the special cases in the loop are described in their own if statement with no nesting. These are: no lines, no more lines, first line, instance of startToken. Then the base case at the end is to append the line to the buffer.

    protected static String readNext(BufferedReader reader, Predicate<String> isStartToken)
            throws IOException {
        StringBuilder buffer = new StringBuilder();
        while (true) {
            reader.mark(81940);
            String line = reader.readLine();

            if (line == null && buffer.length() == 0) {
                return null;
            }

            if (line == null) {
                return buffer.toString();
            }

            if (buffer.length() == 0) {
                buffer.append(line);
                continue;
            }

            if (isStartToken.test(line)) {
                break;
            }

            buffer.append("\n" + line);
        }

        reader.reset();
        return buffer.toString();
    }
\$\endgroup\$
1
\$\begingroup\$

Don't do this:

buf.append("\n" + line);

That is the equivalent of:

buf.append(new StringBuilder().append("\n").append(line));

Just call append twice (and use a character for \n instead of a String):

buf.append('\n').append(line);

Instead of using mark and reset, you could just remember the line that matched the start token and prepend it to the buffer for the next iteration.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.