用Java比较文件

我正在为PACKT创建一系列有关Java网络编程的视频教程。 有整节关于Java NIO。 一个示例程序是通过原始套接字连接将文件从客户端复制到服务器。 客户端从磁盘读取文件,服务器将到达的字节保存到磁盘。 因为这是一个演示,所以服务器和客户端在同一台计算机上运行,​​并且文件从一个目录复制到完全相同的目录,但名称不同。 布丁的证明正在吃掉:文件必须进行比较。

我要复制的文件已创建为包含随机字节。 仅传输文本信息有时会在代码中留下一些棘手的错误。 随机文件是使用简单的Java类创建的:

package packt.java9.network.niodemo;import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;public class SampleMaker {public static void main(String[] args) throws IOException {byte[] buffer = new byte[1024 * 1024 * 10];try (FileOutputStream fos = new FileOutputStream("sample.txt")) {Random random = new Random();for (int i = 0; i < 16; i++) {random.nextBytes(buffer);fos.write(buffer);}}}
}

使用IntelliJ比较文件相当容易,但是由于文件是二进制文件且很大,因此这种方法并不是真正的最佳选择。 我决定编写一个简短的程序,该程序不仅可以表明文件不同,还可以表明不同之处。 代码非常简单:

package packt.java9.network.niodemo;import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;public class SampleCompare {public static void main(String[] args) throws IOException {long start = System.nanoTime();BufferedInputStream fis1 = new BufferedInputStream(new FileInputStream("sample.txt"));BufferedInputStream fis2 = new BufferedInputStream(new FileInputStream("sample-copy.txt"));int b1 = 0, b2 = 0, pos = 1;while (b1 != -1 && b2 != -1) {if (b1 != b2) {System.out.println("Files differ at position " + pos);}pos++;b1 = fis1.read();b2 = fis2.read();}if (b1 != b2) {System.out.println("Files have different length");} else {System.out.println("Files are identical, you can delete one of them.");}fis1.close();fis2.close();long end = System.nanoTime();System.out.print("Execution time: " + (end - start)/1000000 + "ms");}
}

在装有SSD的Mac Book上,比较这两个160MB文件的运行时间约为6秒,如果我指定一个较大的缓冲区(例如10MB)作为BufferedInputStream构造函数的第二个参数,则运行时间不会显着改善。 (另一方面,如果我们不使用BufferedInputStream那么时间大约是十倍。)这是可以接受的,但是如果我只是diff sample.txt sample-copy.txt发出diff sample.txt sample-copy.txt ,那么响应明显更快,而不是6秒。 可能有很多事情,例如Java启动时间, while循环开始时的代码解释,直到JIT编译器认为是开始工作的时候。 我的直觉是,代码会花费大部分时间将文件读入内存。 将字节读取到缓冲区是一个复杂的过程。 它涉及操作系统,设备驱动程序,JVM实现,它们将字节从一个位置移到另一位置,最后我们只比较字节,没有别的。 可以用更简单的方式完成。 我们可以要求操作系统为我们做这件事,并跳过大多数Java运行时活动,文件缓冲区和其他闪烁。

我们可以要求操作系统将文件读取到内存中,然后从它们所在的位置逐个读取字节。 我们不需要一个缓冲区,该缓冲区属于Java对象,并且会占用堆空间。 我们可以使用内存映射文件。 毕竟,内存映射文件使用Java NIO,而这正是当前正在制作的教程视频部分的主题。

操作系统将内存映射文件读入内存,并且字节可供Java程序使用。 内存是由操作系统分配的,它不会消耗堆内存。 如果Java代码修改了映射内存的内容,则操作系统会在认为适当时以优化方式将更改写入磁盘。 但是,这并不意味着如果JVM崩溃,数据就会丢失。 当Java代码修改内存映射文件的内存时,它将修改属于操作系统的内存,该内存在JVM停止运行后可用并且有效。 无法保证并100%防止电源中断和硬件崩溃,但这是非常低的水平。 如果有人对此感到恐惧,那么保护应该在Java无关的硬件级别上进行。 使用内存映射文件,我们可以确保将数据以一定的非常高的概率保存到磁盘中,只有通过容错硬件,群集,不间断电源等才能增加数据。 这些不是Java。 如果确实需要使用Java进行某些操作才能将数据写入磁盘,则可以调用MappedByteBuffer.force()方法,该方法要求操作系统将更改写入磁盘。 但是,过于频繁和不必要地调用它可能会影响性能。 (很简单,因为它会将数据写入磁盘,并且仅在操作系统提示已写入数据时才返回。)

对于大文件,使用内存映射文件读取和写入数据通常要快得多。 为了获得适当的性能,计算机应该有大量的内存,否则,只有部分文件保留在内存中,然后页面错误会增加。 一件好事是,如果同一文件通过两个或多个不同的进程映射到内存中,则将使用同一内存区域。 这样,进程甚至可以相互通信。

使用内存映射文件的比较应用程序如下:

package packt.java9.network.niodemo;import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;public class MapCompare {public static void main(String[] args) throws IOException {long start = System.nanoTime();FileChannel ch1 = new RandomAccessFile("sample.txt", "r").getChannel();FileChannel ch2 = new RandomAccessFile("sample-copy.txt", "r").getChannel();if (ch1.size() != ch2.size()) {System.out.println("Files have different length");return;}long size = ch1.size();ByteBuffer m1 = ch1.map(FileChannel.MapMode.READ_ONLY, 0L, size);ByteBuffer m2 = ch2.map(FileChannel.MapMode.READ_ONLY, 0L, size);for (int pos = 0; pos < size; pos++) {if (m1.get(pos) != m2.get(pos)) {System.out.println("Files differ at position " + pos);return;}}System.out.println("Files are identical, you can delete one of them.");long end = System.nanoTime();System.out.print("Execution time: " + (end - start) / 1000000 + "ms");}
}

为了对文件进行内存映射,我们必须首先使用RandomAccessFile类打开它们,然后从该对象中请求通道。 该通道可用于创建MappedByteBuffer ,它表示文件内容加载到的存储区。 该方法map中的示例映射在只读模式的文件,从该文件的文件的末尾的开始。 我们尝试映射整个文件。 仅当文件大小不超过2GB时,此方法才有效。 起始位置很long但是要映射的区域的大小受Integer大小的限制。

通常来说...哦,是的,比较160MB随机内容文件的运行时间约为1秒。

翻译自: https://www.javacodegeeks.com/2018/02/comparing-files-java.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348050.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java哈希_Java如何采用哈希码实现分类(以员工分配为例)

5.总程序&#xff1a;下面代码是我们获取的所有的程序代码&#xff0c;如下&#xff1a;public static void main(String[] args) {Scanner scannew Scanner(System.in);System.out.println("请输入员工姓名&#xff1a;");String namescan.nextLine();System.out.pr…

java反射的原理_java反射机制的实现原理

java反射机制的实现原理反射机制:所谓的反射机制就是java语言在运行时拥有一项自观的能力。通过这种能力可以彻底的了解自身的情况为下一步的动作做准备。下面具体介绍一下java的反射机制。这里你将颠覆原来对java的理解。Java的反射机制的实现要借助于4个类&#xff1a;class&…

java linkedlist 用法_Java LinkedList addLast()用法及代码示例

Java中的java.util.LinkedList.addLast()方法用于在LinkedList的末尾插入特定元素。用法:void addLast(Object element)参数&#xff1a;此函数接受单个参数element &#xff0c;如上面的语法所示。此参数指定的元素将附加在列表的末尾。返回值&#xff1a;此方法不返回任何值。…

spring 长轮询_Spring集成文件轮询和测试

spring 长轮询我最近实施了一个小项目&#xff0c;在该项目中&#xff0c;我们必须轮询文件夹中的新文件&#xff0c;然后在文件内容上触发服务流。 Spring Integration非常适合此要求&#xff0c;因为它带有一个通道适配器 &#xff0c;该适配器可以扫描文件夹中的新文件&…

java扫描指定package注解_java获取包下被指定注解的类

方案一&#xff1a; 采用reflections 框架(此框架依赖com.google.guava)2、项目依赖org.reflectionsreflections0.9.11com.google.guavaguava21.03、实现代码//入参 要扫描的包名Reflections f new Reflections("com.ggband.netty.execute.command");//入参 目标注解…

您将在下一个项目中使用JSF吗?

上周有一篇很棒的stackoverflow博客文章&#xff0c;主题是“ JavaScript框架的残酷生命周期” 。 这篇文章是关于Javascript UI框架&#xff08;angularjs&#xff0c;angular&#xff0c;jquery和react&#xff09;的流行和流行的速度。 这篇文章的关键指标是每月关于框架的问…

java dao层 service层_dao层与service层的区别

service是业务层&#xff0c;dao是数据访问层。这个问题我也曾经考虑过学java的时候&#xff0c;都是在service里直接调用dao&#xff0c;service里面就new一个dao类对象&#xff0c;调用&#xff0c;其他有意义的事没做&#xff0c;也不明白有这个有什么用然后百度了一下我们都…

java heapsort_排序算法笔记:堆排序 HeapSort in java

/*** 堆排序* 简述:* 首先使用建立最大堆的算法建立好最大堆&#xff0c;然后将堆顶元素(最大值)与最后一个值交换&#xff0c;同时使得堆的长度减小1 &#xff0c;调用保持最大堆性质的算法调整&#xff0c;使得堆顶元素成为最大值&#xff0c;此时最后一个元素已被排除在外* …

从Java 10中删除的API

在博客文章“ JDK 10 Release Candidate Phase ”中&#xff0c;我研究了JDK 10可能包含的十二个新功能。 在本文中&#xff0c;我介绍了一些可能会在JDK 10中删除的API&#xff0c;并探讨了一些在JDK 10中建议弃用的API。本文中的信息基于当前版本&#xff08;2018/1 / “ Jav…

使用java自带的日志管理_java日志管理

1.相关概念日志统一框架(日志门面)&#xff1a;apache commons logging、slf4j日志实现框架(实现层)&#xff1a;JDK自带的logging(java.util.logging)、log4j、Java Util Logging、log4j2、logback.(1)JDK自带的logging(java.util.logging)用法&#xff1a;1 importjava.util.…

在会话中使用JWT

在黑客新闻&#xff0c;reddit和博客上&#xff0c;该主题已经讨论了很多次。 共识是–请勿使用JWT&#xff08;用于用户会话&#xff09;。 而且我在很大程度上同意对JWT的典型论点 &#xff0c; 典型的“但我可以使其工作……”的解释以及JWT标准的缺陷的批评 。 。 我不会…

java案例源代码_求java案例源代码 越多越好!

展开全部import java.awt.*;import java.awt.event.*;import java.lang.*;import javax.swing.*;public class Counter extends Frame{//声明三个面板的布局GridLayout gl1,gl2,gl3;Panel p0,p1,p2,p3;JTextField tf1;TextField tf2;Button b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,…

安卓4.4玩java_Android4.4运行过程中闪退java.lang.NoClassDefFoundError

上周五项目测试时发现一个奇怪的Bug&#xff0c;项目中依赖了一个第三方框架&#xff0c;但是在android4.0-4.4.4之间的系统中运行会直接闪退&#xff0c;抛出错误异常为java.lang.NoClassDefFoundError。第一次遇到这样的问题&#xff0c;google了好久找到了以下几个原因&…

java method方法_Java Method.getTypeParameters方法代碼示例

import java.lang.reflect.Method; //導入方法依賴的package包/類private void validateRuleMethod(MethodRuleDefinition, ?> ruleDefinition, Method ruleMethod, RuleSourceValidationProblemCollector problems) {if (Modifier.isPrivate(ruleMethod.getModifiers())) …

update se_Java SE 7 Update 25 –发行说明进行了解释。

update se昨天是CPU日。 Oracle通过6月的Java重要补丁更新发布了Java SE更新25 。 在4月的最后一次重大更新之后&#xff0c;这是最后一次与Oracle其他所有Oracle产品都不适合的Oracle重要补丁更新计划。 从2013年10月开始 &#xff0c;Java安全修补程序将遵循四个年度安全发布…

java scavenge_请概述一下Java中都有哪些垃圾收集器

1、Serial(串行GC)收集器Serial收集器是一个新生代收集器&#xff0c;单线程执行&#xff0c;使用复制算法。它在进行垃圾收集时&#xff0c;必须暂停其他所有的工作线程(用户线程)。是Jvmclient模式下默认的新生代收集器。对于限定单个CPU的环境来说&#xff0c;Serial收集器由…

Java中的异步等待

编写异步代码很困难。 试图了解异步代码应该做什么的难度更大。 承诺是尝试描述延迟执行流程的一种常见方式&#xff1a;首先做一件事&#xff0c;然后再做另一件事&#xff0c;以防万一出错再做其他事情。 在许多语言中&#xff0c;承诺已成为协调异步行为的事实上的方法。 J…

java web ssh启动运行程序_[javaweb开发SSH] myeclipse启动tomcat时的bug

以前用的是myeclipse10.0的版本,我也不知道以前设置了什么,比较正常.由于以前的myeclipse无法装svn,所以装了一个10.7当连接数据库正常时,自然是好的一旦连接数据库不正常了(我故意将数...以前用的是myeclipse10.0的版本, 我也不知道以前设置了什么,比较正常.由于以前的myeclip…

java简单文本编译器_java -简易文本编辑器

import javax.swing.*;import java.awt.*;import java.awt.event.*;import java.io.*;/*** Title:java -简易文本编辑器 ** Description: 08.5.5 简易功能* 1。 打开文件时&#xff0c;无法选择文件&#xff0c;需手动输入* 2. 文件大小超出 多行文本域时&#xff0c;未实现滚动…

阿帕奇光束

Apache Beam是一个开放源代码统一模型&#xff0c;用于定义批处理和流数据并行处理管道。 使用一种开源的Beam SDK&#xff0c;您可以构建一个定义管道的程序。 然后&#xff0c;该管道由Beam支持的分布式处理后端之一执行&#xff0c;这些后端包括Apache Apex &#xff0c; Ap…