tail-n handle UTF8 and ASCII
user_0606344
java
a year ago
3.8 kB
12
Indexable
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.Deque;
public class TailNWithByteBufferUTF8 {
private static final int BUFFER_SIZE = 4096; // Size of the ByteBuffer
private static final Charset UTF8 = StandardCharsets.UTF_8;
public static Deque<String> tail(String fileName, int n) throws IOException {
Deque<String> result = new ArrayDeque<>(n); // Efficient deque to store last n lines
CharsetDecoder decoder = UTF8.newDecoder(); // UTF-8 decoder for handling multi-byte chars
try (RandomAccessFile file = new RandomAccessFile(fileName, "r");
FileChannel channel = file.getChannel()) {
long fileSize = channel.size();
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
long pos = fileSize;
int lineCount = 0;
StringBuilder currentLine = new StringBuilder();
while (pos > 0) {
// Calculate the position and the amount of data to read
long readStart = Math.max(0, pos - BUFFER_SIZE);
int readSize = (int) (pos - readStart);
pos = readStart;
// Read data into the buffer
channel.position(pos);
buffer.clear();
channel.read(buffer);
buffer.flip(); // Prepare the buffer for reading
// Decode the buffer content as UTF-8
CharBuffer charBuffer = decodeUTF8Buffer(buffer, decoder);
// Process the characters from the end backwards
for (int i = charBuffer.length() - 1; i >= 0; i--) {
char c = charBuffer.charAt(i);
if (c == '\n') {
if (currentLine.length() > 0) {
result.addFirst(currentLine.reverse().toString());
currentLine.setLength(0); // Clear the buffer
lineCount++;
}
if (lineCount == n) {
return result; // Stop if we have the required number of lines
}
} else {
currentLine.append(c);
}
}
}
// Add the remaining line if the file doesn't end with a newline
if (currentLine.length() > 0) {
result.addFirst(currentLine.reverse().toString());
}
}
return result;
}
// Method to decode ByteBuffer to CharBuffer using UTF-8
private static CharBuffer decodeUTF8Buffer(ByteBuffer buffer, CharsetDecoder decoder) throws CharacterCodingException {
decoder.reset();
CharBuffer charBuffer = CharBuffer.allocate(buffer.remaining());
CoderResult result = decoder.decode(buffer, charBuffer, true);
if (result.isError()) {
result.throwException();
}
charBuffer.flip();
return charBuffer;
}
public static void main(String[] args) {
try {
String fileName = "your_static_file.txt"; // Replace with your file path
int n = 100; // Number of lines to retrieve
Deque<String> lastLines = tail(fileName, n);
for (String line : lastLines) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}Editor is loading...
Leave a Comment