1

我对我应该使用哪个系列有一个疑问。已经讨论了很多,但想要更多的投入。

我有一个源系统,每 30 分钟就有 100,000 个交易文件进入我的应用程序。每个文件都有很多行代码(比如 1000 行)。我的应用程序应该只存储和处理最后 10 行交易细节。

如果我使用缓冲区阅读器逐行读取文件内容,那么我必须继续在某个集合中添加每一行的详细信息,最后一旦我到达最后一行,以某种方式删除所有内容并只保留最后 10 行。因此,即使我不需要全部,也将所有 1000 行都保留在集合中是一个性能问题。是否有任何收集或任何方法来改进这一点。

4

5 回答 5

2

您可以使用CircularFifoBuffer

CircularFifoBuffer 是一个具有固定大小的先进先出缓冲区,如果已满则替换其最旧的元素。

仅在内存中保留最后 10 行的用法:

CircularFifoBuffer buffer = new CircularFifoBuffer(10);
// read lines and add them to the buffer

在读取行结束时,缓冲区仅包含最后 10 行。

于 2013-08-23T09:43:11.183 回答
1

使用 RandomAccessFile,并尝试读取更大的缓冲区。我用tailline-length-hint 做了一个函数,来做个猜测。请注意,文件是否以换行符结尾或可能会对结果产生影响。也可以改进代码(两个块大小的幂等)。

        File textFile = new File("...");
        String[] lines = tail(textFile, "UTF-8", 10, 160);
        System.out.println("#Lines: " + lines.length);
        for (String line : lines) {
            System.out.println(line);
        }


String[] tail(File textFile, String charSet, int lines, int lineLengthHint)
        throws IOException {
    if (lineLengthHint < 80) {
        lineLengthHint = 80;
    }
    RandomAccessFile in = new RandomAccessFile(textFile, "r");
    try {
        long fileSize = in.length();
        int bytesCount = lines * lineLengthHint;
        // Loop allocating a byte array hopefully sufficiently large.
        for (;;) {
            if (fileSize < bytesCount) {
                bytesCount = (int)fileSize;
            }
            byte[] bytes = new byte[bytesCount];
            in.seek(fileSize - bytesCount);
            in.readFully(bytes);

            int startIndex = bytes.length; // Position of last '\n'.
            int lineEndsFromStart = 0;
            boolean bytesCountSufficient = true;
            while (lineEndsFromStart - 1 < lines) {
                int pos = startIndex - 1;
                while (pos >= 0 && bytes[pos] != '\n') {
                    --pos;
                }
                startIndex = pos; // -1 will do fine.
                ++lineEndsFromStart;
                if (pos < 0) {
                    bytesCountSufficient = false;
                    break;
                }
            }
            if (bytesCountSufficient || fileSize == bytesCount) {
                String text = new String(bytes, startIndex + 1,
                    bytes.length - (startIndex + 1), charSet);
                return text.split("\r?\n");
            }
            // Not bytesCountSufficient:
            //lineLengthHint += 10; // Average line length was larger.
            bytesCount += lineLengthHint * 4; // Try with more.
        }
    } finally {
        in.close();
    }
}
于 2013-08-23T10:44:11.233 回答
0

您可以轻松地制作一个仅保留最后 10 行的丢弃队列。对于这样的实施, ALinkedList将是一个良好的开端。请参阅有关该主题的上一个问题。

这不会解决读取整个文件的问题,但解决这个问题意味着更多的编码。您需要 aRandomAccessFile并从末尾开始搜索第 10 个换行符。此解决方案的适用性取决于文件的大小。

于 2013-08-23T09:46:36.137 回答
0

您可以使用大小为 10 的 String 数组,并且始终只存储最后 10 行:

BufferedReader in = ...
String[] buffer = new String[10];
int bufferStartIndex = 0;
for (String line; (line = in.readLine()) != null;) {
    buffer[bufferStartIndex++ % buffer.length] = line;
}

在 for 循环结束时,bufferStartIndex将指向文件最后 10 行中的第一行。但是,如果文件包含少于 10 行,则应重置bufferStartIndex为 0。

于 2013-08-23T09:49:06.437 回答
-1
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;

public class Test {
    private static Queue<String> bottom=new LinkedList<String>();
    private static int count=0;

    public static void main(String[] args) throws IOException{
        func(3);
    }

    //function to get count, bottom n lines
    private static void func(int n) throws IOException{
        FileInputStream fstream = new FileInputStream("abc.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(fstream));

        String strLine;

        //Read File Line By Line
        while ((strLine = br.readLine()) != null){
          count++;
          if(count<=n){
              //initialize bottom as top n 
              bottom.add(strLine);
          }else{
              bottom.remove();
              bottom.add(strLine);
               }
        }
        System.out.println(count);
        System.out.println(bottom.toString());
        br.close();    
    }
}

我已经使用 Queue 来获取底部的 n 行。有关详细信息,您可以访问:http ://blog.everestkc.com.np

于 2013-11-05T11:18:58.267 回答