All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.cq.history.utils.ReverseFileReader Maven / Gradle / Ivy

/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2012 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/
package com.adobe.cq.history.utils;

import org.apache.commons.lang.ArrayUtils;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class ReverseFileReader {
    private static final int BUFFER_SIZE = 8192;

    private final RandomAccessFile randomAccessFile;
    private long filePosition;
    private final String encoding;

    private ByteBuffer buffer;
    private int bufferPosition;
    private byte lastLineBreak = '\n';
    private ByteArrayOutputStream baos = new ByteArrayOutputStream();

    public ReverseFileReader(File file, String encoding) throws IOException {
        this.randomAccessFile = new RandomAccessFile(file, "r");
        this.filePosition = randomAccessFile.length() - 1;
        this.encoding = encoding;
    }

    public String readLine() throws IOException {
        String line = "";

        while (true) {
            // Check if buffer is empty
            if (bufferPosition < 0) {
                // Check if file start reached
                if (filePosition <= 0) {
                    if (baos == null) {
                        return null;
                    }
                    line = readLineFromBuffer();
                    baos.close();
                    baos = null;
                    return line;
                }

                // Calculate next range to read
                long offset = Math.max(filePosition - BUFFER_SIZE, 0);
                long length = filePosition - offset;

                // Read next range
                buffer = randomAccessFile.getChannel().map(FileChannel.MapMode.READ_ONLY, offset, length);

                // Define new buffer position
                bufferPosition = (int) length;
                filePosition = offset;
            }

            // Iterate over buffer
            while (bufferPosition-- > 0) {
                byte c = buffer.get(bufferPosition);
                if (c == '\r' || c == '\n') {
                    if (c != lastLineBreak) {
                        lastLineBreak = c;
                        continue;
                    }
                    lastLineBreak = c;

                    // Line has been read
                    return readLineFromBuffer();
                }
                baos.write(c);
            }
        }
    }

    private String readLineFromBuffer() throws UnsupportedEncodingException {
        if (baos.size() == 0) {
            return "";
        }

        // Reverse bytes as we added them from end to start
        byte[] bytes = baos.toByteArray();
        ArrayUtils.reverse(bytes);

        baos.reset();

        return new String(bytes, encoding);
    }

    public void close() {
        try {
            randomAccessFile.close();
        } catch (IOException e) {
            // Ignore
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy