private static List<String> readKeys(final List<String> keys,
                                         final Stream<String> linesStream) {
        final List<String> keysToFind = new ArrayList<>(keys);
        final List<String> values = new ArrayList<>(keys.size());
        // Ensure we have a null value in all indexes, in case we don't find the key
        for (final String ignored : keys) {
            values.add(null);
        }

        final AtomicInteger keysRemaining = new AtomicInteger(keysToFind.size());
        linesStream
                .takeWhile(ignored -> keysRemaining.get() > 0)
                .filter(NullSafe::isNonBlankString)
                .map(String::trim)
                .forEach(line -> {
                    for (int keyIdx = 0; keyIdx < keysToFind.size(); keyIdx++) {
                        final String keyToFind = keysToFind.get(keyIdx);
                        if (NullSafe.isNonBlankString(keyToFind)) {
                            final boolean foundKey = line.regionMatches(
                                    true,
                                    0,
                                    keyToFind,
                                    0,
                                    keyToFind.length());
                            if (foundKey) {
                                // Extract the value. Null out keysToFind, so we don't look for
                                // this key again
                                keysToFind.set(keyIdx, null);
                                keysRemaining.decrementAndGet();
                                final int splitPos = line.indexOf(HEADER_DELIMITER);
                                final String value;
                                if (splitPos != -1) {
                                    value = line.substring(splitPos + 1);
                                    values.set(keyIdx, value.trim());
                                }
                                // break out to look for the next key in keysToFind
                                break;
                            }
                        }
                    }
                });
        return Collections.unmodifiableList(values);
    }
For when you just want the value for one or more keys.
Saves having to de-serialise the whole file to an {@link AttributeMap}.

@param path The file to extract values from.
@param keys The keys to find values for. Assumed to be already trimmed.
@return A list of values using the same indexing as the supplied keys. The length of the
returned list will always match that of the supplied keys list.
stroom-meta/stroom-meta-api/src/main/java/stroom/meta/api/AttributeMapUtil.java