/* * Copyright 2013 Eediom Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.araqne.log.api; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; public class TextFileReader { private String charsetName; private RandomAccessFile raf; private ByteArrayOutputStream bos = new ByteArrayOutputStream(); private byte[] buf = new byte[80960]; private int bufpos = 0; private int buflen = 0; private long readBytes; private boolean closed; private final boolean needLastNewLine; public TextFileReader(File file, long offset, String charsetName) throws IOException { this(file, offset, charsetName, false); } public TextFileReader(File file, long offset, String charsetName, boolean needLastNewLine) throws IOException { this.charsetName = charsetName; this.raf = new RandomAccessFile(file, "r"); this.raf.seek(offset); this.readBytes += offset; this.needLastNewLine = needLastNewLine; } public String readLine() throws IOException { if (closed) throw new IOException("Already closed"); long bytes = 0; if (buflen < 0) buflen = 0; bos.reset(); String line = null; boolean lineEnd = false; while (!lineEnd) { if (buflen < 0) { if (bos.size() == 0) return null; else if (needLastNewLine) { // back file pointer to last newline raf.seek(readBytes); raf.getFD().sync(); return null; } else return bos.toString(charsetName); } while (true) { if (bufpos >= buflen) { buflen = raf.read(buf, 0, buf.length); if (buflen < 0) break; bufpos = 0; } boolean found = false; int begin = bufpos; while (bufpos < buflen) { byte b = buf[bufpos++]; bytes++; if (b == 0xa) { found = true; break; } } int len = bufpos - begin; bos.write(buf, begin, len); if (found) break; } if (bos.size() == 0) { if (!needLastNewLine) { readBytes += bytes; bytes = 0; } return null; } line = bos.toString(charsetName); lineEnd = line.endsWith("\n"); if (lineEnd || !needLastNewLine) { readBytes += bytes; bytes = 0; } } int len = line.length(); if (line.endsWith("\r\n")) return line.substring(0, len - 2); return line.substring(0, len - 1); } public long getPosition() throws IOException { if (closed) throw new IOException("Already closed"); return readBytes; } public void close() { if (closed) return; closed = true; buf = null; bos = null; try { raf.close(); raf = null; } catch (IOException e) { } } }