Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 任何比缓冲读取器更好的提高文件读取性能的方法_Java_Io - Fatal编程技术网

Java 任何比缓冲读取器更好的提高文件读取性能的方法

Java 任何比缓冲读取器更好的提高文件读取性能的方法,java,io,Java,Io,我正在通过缓冲读取器机制读取日志文件,该机制占用的总执行时间为毫秒:12944,请告知我如何提高性能并降低此时间,请告知nio的性能比缓冲读取器更好。。!!文件大小为10MB,因为它是一个日志文件。。!!还请告知如何通过nio实现同样的目标 public class BufferedRedeem { public static void main(String[] args) { BufferedReader br = null; long s

我正在通过缓冲读取器机制读取日志文件,该机制占用的总执行时间为毫秒:12944,请告知我如何提高性能并降低此时间,请告知nio的性能比缓冲读取器更好。。!!文件大小为10MB,因为它是一个日志文件。。!!还请告知如何通过nio实现同样的目标

public class BufferedRedeem
{

    public static void main(String[] args)
    {

        BufferedReader br = null;
        long startTime = System.currentTimeMillis();

        try
        {
            String sCurrentLine;
            br = new BufferedReader(new FileReader("C://abc.log"));

            while ((sCurrentLine = br.readLine()) != null)
            {

            }
            long elapsedTime = System.currentTimeMillis() - startTime;

            System.out.println("Total execution time taken in millis: " + elapsedTime);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (br != null)
                    br.close();
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
    }
}

执行时间主要是由于
System.out.println(sCurrentLine)。我假设您希望进行一些处理或过滤,而不仅仅是sysout


如果要检查BufferedReader的速度,请使用计数器计算读取的行数,然后只打印计数。

您的执行时间主要是由于
系统.out.println(sCurrentLine)造成的。我假设您希望进行一些处理或过滤,而不仅仅是sysout


如果要检查BufferedReader的速度,请使用计数器计算读取的行数,然后只打印计数。

您有一个
System.out.println(sCurrentLine)在循环中,这通常是非常低效的,因为它基本上涉及在每次调用中刷新输出


你能试着把线放在一个数组列表中,而不是输出然后测量时间吗?这样花的时间也差不多吗?

您有一个
系统.out.println(sCurrentLine)在循环中,这通常是非常低效的,因为它基本上涉及在每次调用中刷新输出

你能试着把线放在一个数组列表中,而不是输出然后测量时间吗?这样花的时间也差不多吗

文件大小为10MB,因为它是一个日志文件

如果您有一台像样的计算机,一次读取整个文件应该不是问题(需要Java 7):

publicstaticvoidmain(字符串[]args){
试一试{
长启动=System.nanoTime();
列表行=Files.readAllLines(path.get(“C:/temp/test.log”),字符集。
forName(“UTF-8”);
System.out.println(“行读取:+Lines.size());
System.out.println(“以毫秒为单位的总执行时间:”
+((System.nanoTime()-start)/1000000));
}捕获(IOEX异常){
例如printStackTrace();
}
}
注意:用这种方法在我的计算机上读取6MB文件需要75毫秒

文件大小为10MB,因为它是一个日志文件

如果您有一台像样的计算机,一次读取整个文件应该不是问题(需要Java 7):

publicstaticvoidmain(字符串[]args){
试一试{
长启动=System.nanoTime();
列表行=Files.readAllLines(path.get(“C:/temp/test.log”),字符集。
forName(“UTF-8”);
System.out.println(“行读取:+Lines.size());
System.out.println(“以毫秒为单位的总执行时间:”
+((System.nanoTime()-start)/1000000));
}捕获(IOEX异常){
例如printStackTrace();
}
}

注意:在我的计算机上用这种方法读取6MB文件需要75毫秒。

因为OP很想知道如何使用NIO来完成这项工作

由于文件很小,很难看出差异,但可以测量

public static void main(String... args) throws IOException {
    PrintWriter pw = new PrintWriter("abc.log");
    for (int i = 0; i < 100 * 1000; i++) {
        pw.println("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
    }
    pw.close();

    long start2 = System.nanoTime();
    int count2 = 0;
    BufferedReader br = new BufferedReader(new FileReader("abc.log"));
    while (br.readLine() != null) count2++;
    br.close();
    long time2 = System.nanoTime() - start2;
    System.out.printf("IO: Took %,d ms to read %,d lines%n", time2 / 1000 / 1000, count2);

    long start = System.nanoTime();
    FileChannel fc = new FileInputStream("abc.log").getChannel();
    ByteBuffer bb = ByteBuffer.allocateDirect((int) fc.size());
    fc.read(bb);
    fc.close();
    bb.flip();

    CharBuffer cb = ByteBuffer.allocateDirect(bb.remaining() * 2).order(ByteOrder.nativeOrder()).asCharBuffer();
    CharsetDecoder cd = Charset.forName("UTF-8").newDecoder();
    cd.decode(bb, cb, true);
    cb.flip();
    StringBuilder sb = new StringBuilder();
    int count = 0;
    while (cb.remaining() > 0) {
        char ch = cb.get();
        if (isEndOfLine(cb, ch)) {
            // process sb
            count++;
            sb.setLength(0);
        } else {
            sb.append(ch);
        }
    }
    long time = System.nanoTime() - start;
    System.out.printf("NIO as UTF-8: Took %,d ms to read %,d lines%n", time / 1000 / 1000, count);

    long start3 = System.nanoTime();
    FileChannel fc2 = new FileInputStream("abc.log").getChannel();
    MappedByteBuffer bb2 = fc2.map(FileChannel.MapMode.READ_ONLY, 0, fc2.size());
    bb.flip();
    StringBuilder sb3 = new StringBuilder();
    int count3 = 0;
    while (bb2.remaining() > 0) {
        char ch = (char) bb2.get();
        if (isEndOfLine(bb2, ch)) {
            // process sb
            count3++;
            sb3.setLength(0);
        } else {
            sb3.append(ch);
        }
    }
    fc2.close();
    long time3 = System.nanoTime() - start3;
    System.out.printf("NIO as ISO-8859-1: Took %,d ms to read %,d lines%n", time3 / 1000 / 1000, count3);


}

private static boolean isEndOfLine(CharBuffer cb, char ch) {
    if (ch == '\r') {
        if (cb.remaining() >= 1 && cb.get() == '\n') {
            return true;
        }
        cb.position(cb.position() - 1);
        return true;
    } else if (ch == '\n') {
        return true;
    }
    return false;
}

private static boolean isEndOfLine(ByteBuffer bb, char ch) {
    if (ch == '\r') {
        if (bb.remaining() >= 1 && bb.get() == '\n') {
            return true;
        }
        bb.position(bb.position() - 1);
        return true;
    } else if (ch == '\n') {
        return true;
    }
    return false;
}
正如我前面提到的,使用NIO节省35毫秒的额外复杂性是不值得的


顺便说一句:如果你有一个硬盘驱动器,而文件不在内存中,那么只有驱动器的速度才重要。

因为OP很想知道如何使用NIO实现这一点

由于文件很小,很难看出差异,但可以测量

public static void main(String... args) throws IOException {
    PrintWriter pw = new PrintWriter("abc.log");
    for (int i = 0; i < 100 * 1000; i++) {
        pw.println("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
    }
    pw.close();

    long start2 = System.nanoTime();
    int count2 = 0;
    BufferedReader br = new BufferedReader(new FileReader("abc.log"));
    while (br.readLine() != null) count2++;
    br.close();
    long time2 = System.nanoTime() - start2;
    System.out.printf("IO: Took %,d ms to read %,d lines%n", time2 / 1000 / 1000, count2);

    long start = System.nanoTime();
    FileChannel fc = new FileInputStream("abc.log").getChannel();
    ByteBuffer bb = ByteBuffer.allocateDirect((int) fc.size());
    fc.read(bb);
    fc.close();
    bb.flip();

    CharBuffer cb = ByteBuffer.allocateDirect(bb.remaining() * 2).order(ByteOrder.nativeOrder()).asCharBuffer();
    CharsetDecoder cd = Charset.forName("UTF-8").newDecoder();
    cd.decode(bb, cb, true);
    cb.flip();
    StringBuilder sb = new StringBuilder();
    int count = 0;
    while (cb.remaining() > 0) {
        char ch = cb.get();
        if (isEndOfLine(cb, ch)) {
            // process sb
            count++;
            sb.setLength(0);
        } else {
            sb.append(ch);
        }
    }
    long time = System.nanoTime() - start;
    System.out.printf("NIO as UTF-8: Took %,d ms to read %,d lines%n", time / 1000 / 1000, count);

    long start3 = System.nanoTime();
    FileChannel fc2 = new FileInputStream("abc.log").getChannel();
    MappedByteBuffer bb2 = fc2.map(FileChannel.MapMode.READ_ONLY, 0, fc2.size());
    bb.flip();
    StringBuilder sb3 = new StringBuilder();
    int count3 = 0;
    while (bb2.remaining() > 0) {
        char ch = (char) bb2.get();
        if (isEndOfLine(bb2, ch)) {
            // process sb
            count3++;
            sb3.setLength(0);
        } else {
            sb3.append(ch);
        }
    }
    fc2.close();
    long time3 = System.nanoTime() - start3;
    System.out.printf("NIO as ISO-8859-1: Took %,d ms to read %,d lines%n", time3 / 1000 / 1000, count3);


}

private static boolean isEndOfLine(CharBuffer cb, char ch) {
    if (ch == '\r') {
        if (cb.remaining() >= 1 && cb.get() == '\n') {
            return true;
        }
        cb.position(cb.position() - 1);
        return true;
    } else if (ch == '\n') {
        return true;
    }
    return false;
}

private static boolean isEndOfLine(ByteBuffer bb, char ch) {
    if (ch == '\r') {
        if (bb.remaining() >= 1 && bb.get() == '\n') {
            return true;
        }
        bb.position(bb.position() - 1);
        return true;
    } else if (ch == '\n') {
        return true;
    }
    return false;
}
正如我前面提到的,使用NIO节省35毫秒的额外复杂性是不值得的


顺便说一句:如果您有一个HDD,而文件不在内存中,那么只有驱动器的速度才重要。

不要将文件打印到控制台。这就是你大部分时间将花在的地方。控制台非常慢。@PeterLawrey:或者至少在测量性能时不包括控制台写入…BufferedReader.readLine()包括将内存作为字符串分配给行和解码,这也需要时间。试试BufferedInputStream。@PeterLawrey是的,老兄,我已经删除了,现在需要218毫秒,但我想进一步改进@PunpunTyagi你是说通过删除
System.out.println
读取文件从12944毫秒到218毫秒?你还想提高218毫秒吗?我的数学可能已关闭,但在.218秒内读取10 MB的速度约为48 MB/秒。。。太快了!文件必须缓存在计算机内存中才能达到吞吐量。不要将文件打印到控制台。这就是你大部分时间将花在的地方。控制台非常慢。@PeterLawrey:或者至少在测量性能时不包括控制台写入…BufferedReader.readLine()包括将内存作为字符串分配给行和解码,这也需要时间。试试BufferedInputStream。@PeterLawrey是的,老兄,我已经删除了,现在需要218毫秒,但我想进一步改进@PunpunTyagi你是说通过删除
System.out.println
读取文件从12944毫秒到218毫秒?你还想提高218毫秒吗?我的数学可能已关闭,但在.218秒内读取10 MB的速度约为48 MB/秒。。。太快了!该文件必须缓存在计算机内存中才能实现吞吐量。非常感谢我更新了我的帖子,因为文件大小为10 mb,请建议使用比缓冲更好的方法reader@PunpunTyagi使用BufferedReader,您应该能够在不到250毫秒的时间内读取10 MB的文本文件。使用更快的驱动器和NIO,您可以使读取速度更快,但这会增加复杂性/成本。您的性能要求是什么?@Punpun-Tyagi我很确定使用
BufferedReader
读取10Mb不会导致性能下降
IO: Took 112 ms to read 100,000 lines
NIO as UTF-8: Took 207 ms to read 100,000 lines
NIO as ISO-8859-1: Took 87 ms to read 100,000 lines