java使用缓冲区读取文件_在Java中使用Google的协议缓冲区

java使用缓冲区读取文件

最近发布了 有效的Java第三版 ,我一直对确定此类Java开发书籍的更新感兴趣,该书籍的最新版本仅通过Java 6进行了介绍 。 在此版本中,显然存在与Java 7 , Java 8和Java 9密切相关的全新项目,例如第7章(“ Lambda和流”)中的项目42至48,项目9(“建议尝试使用资源”最终尝试”)和第55条(“明智地退还可选方案”)。 我(非常有点)惊讶地发现, Effective Java第三版中有一个新项目,并不是由Java的新版本专门驱动的,而是由独立于Java版本的软件开发领域的开发驱动的。 第85项(“ Java序列化的首选替代品”)是促使我撰写此介绍性文章的内容,内容涉及将Google的Protocol Buffers与Java结合使用 。

在第三版的有效Java的项目85中,Josh Bloch以粗体强调了以下两个与Java序列化有关的断言:

  1. 避免序列化攻击的最佳方法是永远不要反序列化任何东西。
  2. 您没有理由在您编写的任何新系统中使用Java序列化。

在概述了Java反序列化的危险并做出了这些大胆的声明后,Bloch建议Java开发人员使用他所谓的(跨平台的结构化数据表示形式)(以避免在讨论Java时与术语“序列化”相关的混淆)。 Bloch指出,该类别中的领先产品是JSON ( JavaScript对象表示法 )和协议缓冲区 ( protobuf )。 我发现提到协议缓冲区很有趣,因为最近我一直在阅读和使用协议缓冲区。 在线全面介绍了JSON(甚至Java)的用法。 我觉得Java开发人员对协议缓冲区的了解可能比对JSON的了解要少,因此感觉有必要在Java上使用协议缓冲区。

Google的协议缓冲区在其项目页面上被描述为“一种语言中立,平台中立的可扩展机制,用于序列化结构化数据。” 该页面添加了“思考XML,但是更小,更快,更简单”。 尽管协议缓冲区的优点之一是它们支持以可以被多种编程语言使用的方式表示数据,但本文的重点仅在于将协议缓冲区与Java结合使用。

有一些与协议缓冲区相关的有用在线资源,包括主项目页面 , GitHub protobuf项目页面 , proto3语言指南 (也提供proto2语言指南 ), 协议缓冲区基础:Java教程, Java生成的代码指南 , Java API(Javadoc)文档 ,“ 协议缓冲区”发布页面和“ Maven存储库”页面 。 本文中的示例基于协议缓冲区3.5.1 。

协议缓冲区基础:Java教程概述了将协议缓冲区与Java一起使用的过程。 与使用Java相比,它涵盖了使用Java时要考虑的更多可能性和事情。 第一步是定义独立于语言的协议缓冲区格式。 这是在扩展名为.proto的文本文件中完成的。 在我的示例中,我已经在下一个代码清单中显示的文件album.proto描述了协议格式。

原始专辑

syntax = "proto3";option java_outer_classname = "AlbumProtos";
option java_package = "dustin.examples.protobuf";message Album
{string title = 1;repeated string artist = 2;int32 release_year = 3;repeated string song_title = 4;
}

尽管上面对协议格式的定义很简单,但其中有很多内容。 第一行明确指出我使用的是proto3,而不是未明确指定时使用的默认默认proto2 。 以option开头的两行仅在使用该协议格式生成Java代码时才有意义,它们指示最外层类的名称以及该最外层类的软件包,该类将被生成以供Java应用程序使用此协议格式使用。

“ message”关键字表示此结构(此处称为“相册”)需要表示。 此构造中有四个字段,其中三个是string格式,一个是整数( int32 )。 四个字段中的两个在给定消息中可以不止一次存在,因为它们用repeated保留字注释。 请注意,我创建该定义时没有考虑Java,除了两个option s,它们指定了根据此格式规范生成Java类的详细信息。

所述album.proto上述未示出的文件需要被“编译”到Java源类文件( AlbumProtos.javadustin.examples.protobuf包),将允许写入和读出协议缓冲器的二进制格式的对应于定义的协议格式。 使用适当的基于操作系统的存档文件中包含的protoc编译器可以完成Java源代码文件的生成。 就我而言,因为我正在Windows 10中运行此示例,所以我下载并解压缩了protoc-3.5.1-win32.zip以便访问该protoc工具。 下一个图像使用命令protoc --proto_path=src --java_out=dist\generated album.proto描绘了我对album.proto运行protoc

对于运行上面的,我有我的album.proto在文件src目录中指出--proto_path和我有一个创建(但空)目录下名为build\generated生成的Java源代码被放置在由按规定--java_out标志。

指定包中生成的类的Java源代码文件AlbumProtos.java有1000行以上,我不会在此处列出生成的类源代码,但是可以在GitHub上找到 。 关于生成的代码,需要注意的几件有趣的事情是缺少导入语句(完全合格的包名称代替了所有类引用)。 Java生成的代码指南中提供了有关由protoc生成的Java源代码的更多详细信息。 重要的是要注意,这个生成的类AlbumProtos仍然不受我自己的任何Java应用程序代码的影响,并且仅由文章前面显示的album.proto文本文件生成。

有了可用于AlbumProtos的生成的Java源代码,我现在将在其中生成此类的目录添加到IDE的源路径中,因为现在我将其视为源代码文件。 我也可以将其编译为.class.jar用作库。 现在,在我的源路径中有了这个生成的Java源代码文件,我可以将其与自己的代码一起构建。

在继续本示例之前,我们需要一个简单的Java类来用Protocol Buffers表示。 为此,我将使用下一个代码清单(也在GitHub上提供 )中定义的Album类。

相册.java

package dustin.examples.protobuf;import java.util.ArrayList;
import java.util.List;/*** Music album.*/
public class Album
{private final String title;private final List<String> artists;private final int releaseYear;private final List<String> songsTitles;private Album(final String newTitle, final List<String> newArtists,final int newYear, final List<String> newSongsTitles){title = newTitle;artists = newArtists;releaseYear = newYear;songsTitles = newSongsTitles;}public String getTitle(){return title;}public List<String> getArtists(){return artists;}public int getReleaseYear(){return releaseYear;}public List<String> getSongsTitles(){return songsTitles;}@Overridepublic String toString(){return "'" + title + "' (" + releaseYear + ") by " + artists + " features songs " + songsTitles;}/*** Builder class for instantiating an instance of* enclosing Album class.*/public static class Builder{private String title;private ArrayList<String> artists = new ArrayList<>();private int releaseYear;private ArrayList<String> songsTitles = new ArrayList<>();public Builder(final String newTitle, final int newReleaseYear){title = newTitle;releaseYear = newReleaseYear;}public Builder songTitle(final String newSongTitle){songsTitles.add(newSongTitle);return this;}public Builder songsTitles(final List<String> newSongsTitles){songsTitles.addAll(newSongsTitles);return this;}public Builder artist(final String newArtist){artists.add(newArtist);return this;}public Builder artists(final List<String> newArtists){artists.addAll(newArtists);return this;}public Album build(){return new Album(title, artists, releaseYear, songsTitles);}}
}

在定义了Java“数据”类(“ Album )并使用协议缓冲区生成的Java类(可以表示该专辑)的情况下( AlbumProtos.java ),我准备编写Java应用程序代码以“序列化”专辑信息,而无需使用Java序列化。 此应用程序(演示)代码位于GitHub上可用的AlbumDemo类中, 在本文中 ,我将着重AlbumDemo该类。

我们需要生成一个用于示例的Album实例,并通过下一个硬编码列表来完成。

生成Album样本实例

/*** Generates instance of Album to be used in demonstration.** @return Instance of Album to be used in demonstration.*/
public Album generateAlbum()
{return new Album.Builder("Songs from the Big Chair", 1985).artist("Tears For Fears").songTitle("Shout").songTitle("The Working Hour").songTitle("Everybody Wants to Rule the World").songTitle("Mothers Talk").songTitle("I Believe").songTitle("Broken").songTitle("Head Over Heels").songTitle("Listen").build();
}

协议缓冲区生成的类AlbumProtos类包括一个嵌套的AlbumProtos.Album类,我将使用该类以二进制形式存储我的Album实例的内容。 下一个代码清单演示了如何完成此操作。

Album实例化AlbumProtos.Album

final Album album = instance.generateAlbum();
final AlbumProtos.Album albumMessage= AlbumProtos.Album.newBuilder().setTitle(album.getTitle()).addAllArtist(album.getArtists()).setReleaseYear(album.getReleaseYear()).addAllSongTitle(album.getSongsTitles()).build();

如前面的代码清单所示,“生成器”用于填充协议缓冲区生成的类的不可变实例。 参照该实例,我现在可以使用toByteArray()方法在该实例上以协议缓冲区的二进制形式轻松写出该实例的内容,如下面的代码清单所示。

写作AlbumProtos.Album二进制形式

final byte[] binaryAlbum = albumMessage.toByteArray();

如下面的代码清单所示,可以完成将byte[]数组读回Album实例的操作。

AlbumProtos.Album二进制形式实例化Album

/*** Generates an instance of Album based on the provided* bytes array.** @param binaryAlbum Bytes array that should represent an*    AlbumProtos.Album based on Google Protocol Buffers*    binary format.* @return Instance of Album based on the provided binary form*    of an Album; may be {@code null} if an error is encountered*    while trying to process the provided binary data.*/
public Album instantiateAlbumFromBinary(final byte[] binaryAlbum)
{Album album = null;try{final AlbumProtos.Album copiedAlbumProtos = AlbumProtos.Album.parseFrom(binaryAlbum);final List<String> copiedArtists = copiedAlbumProtos.getArtistList();final List<String> copiedSongsTitles = copiedAlbumProtos.getSongTitleList();album = new Album.Builder(copiedAlbumProtos.getTitle(), copiedAlbumProtos.getReleaseYear()).artists(copiedArtists).songsTitles(copiedSongsTitles).build();}catch (InvalidProtocolBufferException ipbe){out.println("ERROR: Unable to instantiate AlbumProtos.Album instance from provided binary data - "+ ipbe);}return album;
}

如最后一个代码清单所示,在调用生成的类中定义的static方法parseFrom(byte[])过程中,可能引发检查异常InvalidProtocolBufferException 。 获取生成的类的“反序列化”实例本质上是一行,其余几行从生成的类的实例中获取数据,并在原始Album类的实例中设置该数据。

演示类包括两行,这些行打印出原始Album实例的内容,以及最终从二进制表示形式检索到的实例。 这两行包括对两个实例的System.identityHashCode()调用,以证明即使内容匹配,它们也不是同一实例。 当使用前面显示的硬编码的Album实例详细信息执行此代码时,输​​出如下所示:

BEFORE Album (1323165413): 'Songs from the Big Chair' (1985) by [Tears For Fears] features songs [Shout, The Working Hour, Everybody Wants to Rule the World, Mothers Talk, I Believe, Broken, Head Over Heels, Listen]AFTER Album (1880587981): 'Songs from the Big Chair' (1985) by [Tears For Fears] features songs [Shout, The Working Hour, Everybody Wants to Rule the World, Mothers Talk, I Believe, Broken, Head Over Heels, Listen]

从此输出中,我们看到两个实例中的相关字段相同,并且两个实例确实是唯一的。 与使用Java的实现序列化接口的“近乎自动” 序列化机制相比,这需要付出更多的努力,但是与这种方法相关联的重要优势可以证明成本合理。 Josh Bloch在《 Effective Java,第三版》中讨论了Java默认机制中与反序列化相关的安全漏洞,并断言“ 没有理由在您编写的任何新系统中使用Java序列化。

翻译自: https://www.javacodegeeks.com/2018/01/using-googles-protocol-buffers-java.html

java使用缓冲区读取文件

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

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

相关文章

linux多用户运行同一程序_linux系统中CentOS有哪些优势,让它长盛不衰?

CentOS是目前评价和口碑都不错的linux系统&#xff0c;甚至很多公司安装的都是CentOS系统&#xff0c;对于初入门的小白可能不了解这个系统&#xff0c;今天我们就整理一下CentOS系统的七大优势。1. 开源、免费众所周知&#xff0c;不管是微软的 Windows 还是苹果的 macOS&…

浅析 Linux 初始化系统(系统服务管理和控制程序/init system) -- UpStart

文章目录一、Upstart 简介&#xff08;一&#xff09;开发 Upstart 的缘由&#xff08;二&#xff09;Upstart 的特点二、Upstart 概念和术语&#xff08;一&#xff09;Job&#xff08;二&#xff09;Job 生命周期&#xff08;三&#xff09;事件 Event1.Signals2.Methods3.Ho…

telnet到设备里 php_金融行业思科设备典型网络故障案例:76系列典型案例(一)...

一、Cisco 7606主备引擎自动切换01故障现象某行上联路由器cisco7606 x月x日引擎自行切换&#xff0c;这种情况是第一次发生&#xff0c;至今仍是备引擎是active&#xff0c;主引擎是standby。02分析过程思科TAC提取了log日志和crashinfo信息&#xff1a;Previous engine detect…

白盒测试方法静态分析_静态分析的教育方面

白盒测试方法静态分析加入我们项目的新程序员经常问我们是否有自动格式化工具&#xff0c;以使Java代码看起来完全像Qulice期望的那样。 &#xff08;Quili是我们使用的静态分析器。&#xff09;我总是回答说&#xff0c;拥有这样一个自动代码抛光器只会有害&#xff0c;并且不…

java javadoc_使用Java 9向Javadoc搜索添加术语

java javadoc有一个相对较旧的网页&#xff0c;称为“ Proposed Javadoc Tags ”&#xff0c;最初似乎是与Javadoc 1.2一起编写的&#xff0c;其中列出了“ Sun有朝一日可能会在Javadoc中实现的标签”。 在此列表中的标签是category &#xff0c; example &#xff0c; tutoria…

浅析 Linux 初始化系统(系统服务管理和控制程序/Init System) -- systemd

文章目录一、Systemd 的简介和特点&#xff08;一&#xff09;同 SysVinit 和 LSB init scripts 兼容&#xff08;二&#xff09;更快的启动速度&#xff08;三&#xff09;systemd 提供按需启动能力&#xff08;四&#xff09;Systemd 采用 Linux 的 Cgroup 特性跟踪和管理进程…

查询 service monitor 时发生内部错误_通过Service访问应用 (1)

目录通过Service访问应用通过Pod IP访问应用 通过ClusterIP Service在集群内部访问 通过Service访问应用通过之前的操作&#xff0c;应用部署完成了&#xff0c;我们的Demo网站已经成功启动了&#xff0c;那么如何访问网站呢&#xff1f;通过Pod IP访问应用我们可以通过Pod IP来…

c语言 方程改main的值_C语言编程笔记丨编写第一个C语言程序hello world,我教你哇...

如果用C语言输出&#xff1a;Hello&#xff0c;world&#xff01;&#xff0c;该如何编写程序&#xff1f;**代码如下&#xff1a;**#include//包含标准库的信息main()//定义名为main的函数&#xff0c;不接受参数值{//main函数的语句都放在花括号中&#xff0c;也表示函数体的…

linux定时创建文件,linux下如何创建定时任务

文/PM回忆录本篇文章不详细讲述cron服务的那种配置文件&#xff0c;只是应用层面的讲解&#xff0c;只求初步的掌握。说到定时任务&#xff0c;不能不介绍下cron&#xff1a;一、cron定时任务是什么在LINUX中&#xff0c;周期执行的任务一般由cron这个守护进程来处理[ps -ef|gr…

6-7 使用函数输出水仙花数_「Java」再议printf函数

System.out.printf() 是在JDK1.5版开始引入的方法&#xff0c;即在JDK1.5以后的版本才可以使用此函数&#xff0c;printf 方法有 printf(String format, Object ... args) 和 printf(Locale l, String format, Object ... args) 两种重载方式。其实学过C语言的小伙伴应该会觉得…

c语言命名规则_C语言的基本数据类型及变量

学习目标了解C语言的基本数据类型了解变量的基本概念了解变量的使用方法了解了变量的命名方法了解格式占位符了解变量的输出了解C语言程序的基本数据类型及概念的使用方法擦在C语言编程中&#xff0c;系统定义了多种数据类型&#xff0c;本节将讲解基本数据类型的分类。基本数据…

Linux 常用的软件包管理器/软件包管理工具详解

文章目录RPM 是什么&#xff1f;应用于哪些系统RPM 的前端工具有哪些RPM 包命名规范RPM 安装软件的默认路径RPM 安装原理图RPM 命令详解YUM 是什么&#xff1f;应用于哪些系统YUM 原理说明主要特点YUM 和 RPM 的区别YUM 命令详解DNF 是什么应用于哪些系统DNF 命令详解APT 是什么…

java world_Java World中的GraphQL简介

java world许多人认为GraphQL仅适用于前端和JavaScript&#xff0c;它在Java等后端技术中不占优势&#xff0c;但事实确实如此。 还经常将GraphQL与REST进行比较&#xff0c;但是这种比较是否合理&#xff1f; 首先&#xff0c;让我开始回答其中最重要的问题。 什么是GraphQL…

快速排序 动图_Java十大排序算法最强总结

看到一篇很不错的文章&#xff0c;不多说&#xff0c;看吧排序算法说明0.1 排序的定义对一序列对象根据某个关键字进行排序。0.2 术语说明稳定&#xff1a;如果a原本在b前面&#xff0c;而ab&#xff0c;排序之后a仍然在b的前面&#xff1b;不稳定&#xff1a;如果a原本在b的前…

feignclient注解使用_从 Feign 使用注意点到 RESTFUL 接口设计规范

最近项目中大量使用了Spring Cloud Feign来对接http接口&#xff0c;踩了不少坑&#xff0c;也产生了一些对RESTFUL接口设计的想法&#xff0c;特此一篇记录下。SpringMVC的请求参数绑定机制了解Feign历史的朋友会知道&#xff0c;Feign本身是Netflix的产品&#xff0c;Spring …

python写接口测试代码_python写运单接口测试(增改查)完整代码

importrequestsimportjsonfrom urllib importparseclassHttpWayBillRquest:运单的增改查 defaccess_token(self):获取tokenurl http://xxxxxxxxx.comusername 12333password 12334566res_json requests.get(url, auth(username, password)).json()print(access_token的结果为&a…

linux vim自动执行快捷键,Linux Vim快捷键操作命令整理

VIM中常用的替换模式总结1&#xff0c;简单替换表达式替换命令可以在全文中用一个单词替换另一个单词&#xff1a;:%s/four/4/g“%” 范围前缀表示在所有行中执行替换。最后的 “g” 标记表示替换行中的所有匹配点。如果仅仅对当前行进行操作&#xff0c;那么只要去掉%即可如果…

eclipse占用内存过大_Java性能调优学习(三)-jmap+mat分析内存溢出问题实战

上一节我们讲了jinfo&#xff0c;jstat&#xff0c;jmap的使用&#xff0c;还简单的讲了下如何使用jmap导出内存映像文件&#xff0c;这次&#xff0c;我们来实战一把内存溢出问题。环境准备首先我们先模拟一下内存溢出的场景&#xff0c;以下这段代码在访问后肯定会造成堆内存…

spring boot自测_将测微仪与Spring Boot 2一起使用

spring boot自测这是快速入门&#xff0c;介绍了如何使用出色的Micrometer库来检测基于Spring Boot 2的应用程序并在Prometheus中记录指标 介绍 Micrometer在不同监视工具提供的客户端库上提供了基于Java的外观。 以Prometheus为例&#xff0c;如果我要将Java应用程序与Prome…

微软和 Windows 的发展简史

20世纪60年代中期&#xff0c;美国达特茅斯学院院长、匈牙利人约翰凯梅尼&#xff08;J. Kemeny&#xff09;和数学系教授托马斯卡茨&#xff08;Thomas E. Kurtz&#xff09;认为&#xff0c;像FORTRAN&#xff08;世界上最早出现的计算机高级程序设计语言&#xff09;那样的语…