转载自https://developers.google.com/protocol-buffers/docs/javatutorial,本文内使用的规范为proto2

This tutorial provides a basic Java programmer’s introduction to working with protocol buffers. By walking through creating a simple example application, it shows you how to

  • Define message formats in a .proto file.
  • Use the protocol buffer compiler.
  • Use the Java protocol buffer API to write and read messages.

This isn’t a comprehensive guide to using protocol buffers in Java. For more detailed reference information, see the Protocol Buffer Language Guide, the Java API Reference, the Java Generated Code Guide, and the Encoding Reference.

Why Use Protocol Buffers?

The example we’re going to use is a very simple “address book” application that can read and write people’s contact details to and from a file. Each person in the address book has a name, an ID, an email address, and a contact phone number.

How do you serialize and retrieve structured data like this? There are a few ways to solve this problem:

  • Use Java Serialization. This is the default approach since it’s built into the language, but it has a host of well-known problems (see Effective Java, by Josh Bloch pp. 213), and also doesn’t work very well if you need to share data with applications written in C++ or Python.
  • You can invent an ad-hoc way to encode the data items into a single string – such as encoding 4 ints as “12:3:-23:67”. This is a simple and flexible approach, although it does require writing one-off encoding and parsing code, and the parsing imposes a small run-time cost. This works best for encoding very simple data.
  • Serialize the data to XML. This approach can be very attractive since XML is (sort of) human readable and there are binding libraries for lots of languages. This can be a good choice if you want to share data with other applications/projects. However, XML is notoriously space intensive, and encoding/decoding it can impose a huge performance penalty on applications. Also, navigating an XML DOM tree is c
  • onsiderably more complicated than navigating simple fields in a class normally would be.

Protocol buffers are the flexible, efficient, automated solution to solve exactly this problem. With protocol buffers, you write a .proto description of the data structure you wish to store. From that, the protocol buffer compiler creates a class that implements automatic encoding and parsing of the protocol buffer data with an efficient binary format. The generated class provides getters and setters for the fields that make up a protocol buffer and takes care of the details of reading and writing the protocol buffer as a unit. Importantly, the protocol buffer format supports the idea of extending the format over time in such a way that the code can still read data encoded with the old format.

Where to Find the Example Code

The example code is included in the source code package, under the “examples” directory. Download it here.

Defining Your Protocol Format

To create your address book application, you’ll need to start with a .proto file. The definitions in a .proto file are simple: you add a message for each data structure you want to serialize, then specify a name and a type for each field in the message. Here is the .proto file that defines your messages, addressbook.proto.

syntax = "proto2";package tutorial;option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";message Person {required string name = 1;required int32 id = 2;optional string email = 3;enum PhoneType {MOBILE = 0;HOME = 1;WORK = 2;}message PhoneNumber {required string number = 1;optional PhoneType type = 2 [default = HOME];}repeated PhoneNumber phones = 4;
}message AddressBook {repeated Person people = 1;
}

As you can see, the syntax is similar to C++ or Java. Let’s go through each part of the file and see what it does.

The .proto file starts with a package declaration, which helps to prevent naming conflicts between different projects. In Java, the package name is used as the Java package unless you have explicitly specified a java_package, as we have here. Even if you do provide a java_package, you should still define a normal package as well to avoid name collisions in the Protocol Buffers name space as well as in non-Java languages.

After the package declaration, you can see two options that are Java-specific: java_package and java_outer_classname. java_package specifies in what Java package name your generated classes should live. If you don’t specify this explicitly, it simply matches the package name given by the package declaration, but these names usually aren’t appropriate Java package names (since they usually don’t start with a domain name). The java_outer_classname option defines the class name which should contain all of the classes in this file. If you don’t give a java_outer_classname explicitly, it will be generated by converting the file name to upper camel case. For example, “my_proto.proto” would, by default, use “MyProto” as the outer class name.

Next, you have your message definitions. A message is just an aggregate containing a set of typed fields. Many standard simple data types are available as field types, including bool, int32, float, double, and string. You can also add further structure to your messages by using other message types as field types – in the above example the Person message contains PhoneNumber messages, while the AddressBook message contains Person messages. You can even define message types nested inside other messages – as you can see, the PhoneNumber type is defined inside Person. You can also define enum types if you want one of your fields to have one of a predefined list of values – here you want to specify that a phone number can be one of MOBILE, HOME, or WORK.

The " = 1", " = 2" markers on each element identify the unique “tag” that field uses in the binary encoding. Tag numbers 1-15 require one less byte to encode than higher numbers, so as an optimization you can decide to use those tags for the commonly used or repeated elements, leaving tags 16 and higher for less-commonly used optional elements. Each element in a repeated field requires re-encoding the tag number, so repeated fields are particularly good candidates for this optimization.

Each field must be annotated with one of the following modifiers:

  • required: a value for the field must be provided, otherwise the message will be considered “uninitialized”. Trying to build an uninitialized message will throw a RuntimeException. Parsing an uninitialized message will throw an IOException. Other than this, a required field behaves exactly like an optional field.
  • optional: the field may or may not be set. If an optional field value isn’t set, a default value is used. For simple types, you can specify your own default value, as we’ve done for the phone number type in the example. Otherwise, a system default is used: zero for numeric types, the empty string for strings, false for bools. For embedded messages, the default value is always the “default instance” or “prototype” of the message, which has none of its fields set. Calling the accessor to get the value of an optional (or required) field which has not been explicitly set always returns that field’s default value.
  • repeated: the field may be repeated any number of times (including zero). The order of the repeated values will be preserved in the protocol buffer. Think of repeated fields as dynamically sized arrays.

Required Is Forever You should be very careful about marking fields as required. If at some point you wish to stop writing or sending a required field, it will be problematic to change the field to an optional field – old readers will consider messages without this field to be incomplete and may reject or drop them unintentionally. You should consider writing application-specific custom validation routines for your buffers instead. Some engineers at Google have come to the conclusion that using required does more harm than good; they prefer to use only optional and repeated. However, this view is not universal.

You’ll find a complete guide to writing .proto files – including all the possible field types – in the Protocol Buffer Language Guide. Don’t go looking for facilities similar to class inheritance, though – protocol buffers don’t do that.

注意,proto3的规范里是没有require这个修饰符的,没有修饰符的字段默认为require的,但proto3之中仍然有optionalrepeated

Compiling Your Protocol Buffers

Now that you have a .proto, the next thing you need to do is generate the classes you’ll need to read and write AddressBook (and hence Person and PhoneNumber) messages. To do this, you need to run the protocol buffer compiler protoc on your .proto:

  1. If you haven’t installed the compiler, download the package and follow the instructions in the README.
  2. Now run the compiler, specifying the source directory (where your application’s source code lives – the current directory is used if you don’t provide a value), the destination directory (where you want the generated code to go; often the same as $SRC_DIR), and the path to your .proto. In this case, you…:
protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.proto

Because you want Java classes, you use the --java_out option – similar options are provided for other supported languages.
This generates com/example/tutorial/AddressBookProtos.java in your specified destination directory.

The Protocol Buffer API

Let’s look at some of the generated code and see what classes and methods the compiler has created for you. If you look in AddressBookProtos.java, you can see that it defines a class called AddressBookProtos, nested within which is a class for each message you specified in addressbook.proto. Each class has its own Builder class that you use to create instances of that class. You can find out more about builders in the Builders vs. Messages section below.

Both messages and builders have auto-generated accessor methods for each field of the message; messages have only getters while builders have both getters and setters. Here are some of the accessors for the Person class (implementations omitted for brevity):

// required string name = 1;
public boolean hasName();
public String getName();// required int32 id = 2;
public boolean hasId();
public int getId();// optional string email = 3;
public boolean hasEmail();
public String getEmail();// repeated .tutorial.Person.PhoneNumber phones = 4;
public List<PhoneNumber> getPhonesList();
public int getPhonesCount();
public PhoneNumber getPhones(int index);

Meanwhile, Person.Builder has the same getters plus setters:

// required string name = 1;
public boolean hasName();
public java.lang.String getName();
public Builder setName(String value);
public Builder clearName();// required int32 id = 2;
public boolean hasId();
public int getId();
public Builder setId(int value);
public Builder clearId();// optional string email = 3;
public boolean hasEmail();
public String getEmail();
public Builder setEmail(String value);
public Builder clearEmail();// repeated .tutorial.Person.PhoneNumber phones = 4;
public List<PhoneNumber> getPhonesList();
public int getPhonesCount();
public PhoneNumber getPhones(int index);
public Builder setPhones(int index, PhoneNumber value);
public Builder addPhones(PhoneNumber value);
public Builder addAllPhones(Iterable<PhoneNumber> value);
public Builder clearPhones();

As you can see, there are simple JavaBeans-style getters and setters for each field. There are also has getters for each singular field which return true if that field has been set. Finally, each field has a clear method that un-sets the field back to its empty state.

Repeated fields have some extra methods – a Count method (which is just shorthand for the list’s size), getters and setters which get or set a specific element of the list by index, an add method which appends a new element to the list, and an addAll method which adds an entire container full of elements to the list.

Notice how these accessor methods use camel-case naming, even though the .proto file uses lowercase-with-underscores. This transformation is done automatically by the protocol buffer compiler so that the generated classes match standard Java style conventions. You should always use lowercase-with-underscores for field names in your .proto files; this ensures good naming practice in all the generated languages. See the style guide for more on good .proto style.

For more information on exactly what members the protocol compiler generates for any particular field definition, see the Java generated code reference.

Enums and Nested Classes

The generated code includes a PhoneType Java 5 enum, nested within Person:

public static enum PhoneType {MOBILE(0, 0),HOME(1, 1),WORK(2, 2),;...
}

The nested type Person.PhoneNumber is generated, as you’d expect, as a nested class within Person.

Builders vs. Messages

The message classes generated by the protocol buffer compiler are all immutable. Once a message object is constructed, it cannot be modified, just like a Java String. To construct a message, you must first construct a builder, set any fields you want to set to your chosen values, then call the builder’s build() method.

You may have noticed that each method of the builder which modifies the message returns another builder. The returned object is actually the same builder on which you called the method. It is returned for convenience so that you can string several setters together on a single line of code.

Here’s an example of how you would create an instance of Person:

Person john =Person.newBuilder().setId(1234).setName("John Doe").setEmail("jdoe@example.com").addPhones(Person.PhoneNumber.newBuilder().setNumber("555-4321").setType(Person.PhoneType.HOME)).build();

Standard Message Methods

Each message and builder class also contains a number of other methods that let you check or manipulate the entire message, including:

  • isInitialized(): checks if all the required fields have been set.
  • toString(): returns a human-readable representation of the message, particularly useful for debugging.
  • mergeFrom(Message other): (builder only) merges the contents of other into this message, overwriting singular scalar fields, merging composite fields, and concatenating repeated fields.
  • clear(): (builder only) clears all the fields back to the empty state.

These methods implement the Message and Message.Builder interfaces shared by all Java messages and builders. For more information, see the complete API documentation for Message.

Parsing and Serialization

Finally, each protocol buffer class has methods for writing and reading messages of your chosen type using the protocol buffer binary format. These include:

  • byte[] toByteArray();: serializes the message and returns a byte array containing its raw bytes.
  • static Person parseFrom(byte[] data);: parses a message from the given byte array.
  • void writeTo(OutputStream output);: serializes the message and writes it to an OutputStream.
  • static Person parseFrom(InputStream input);: reads and parses a message from an InputStream.

These are just a couple of the options provided for parsing and serialization. Again, see the Message API reference for a complete list.

Protocol Buffers and O-O Design Protocol buffer classes are basically dumb data holders (like structs in C); they don’t make good first class citizens in an object model. If you want to add richer behaviour to a generated class, the best way to do this is to wrap the generated protocol buffer class in an application-specific class. Wrapping protocol buffers is also a good idea if you don’t have control over the design of the .proto file (if, say, you’re reusing one from another project). In that case, you can use the wrapper class to craft an interface better suited to the unique environment of your application: hiding some data and methods, exposing convenience functions, etc. You should never add behaviour to the generated classes by inheriting from them. This will break internal mechanisms and is not good object-oriented practice anyway.

Writing A Message

Now let’s try using your protocol buffer classes. The first thing you want your address book application to be able to do is write personal details to your address book file. To do this, you need to create and populate instances of your protocol buffer classes and then write them to an output stream.

Here is a program which reads an AddressBook from a file, adds one new Person to it based on user input, and writes the new AddressBook back out to the file again. The parts which directly call or reference code generated by the protocol compiler are highlighted.

import com.example.tutorial.AddressBookProtos.AddressBook;
import com.example.tutorial.AddressBookProtos.Person;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;class AddPerson {// This function fills in a Person message based on user input.static Person PromptForAddress(BufferedReader stdin,PrintStream stdout) throws IOException {Person.Builder person = Person.newBuilder();stdout.print("Enter person ID: ");person.setId(Integer.valueOf(stdin.readLine()));stdout.print("Enter name: ");person.setName(stdin.readLine());stdout.print("Enter email address (blank for none): ");String email = stdin.readLine();if (email.length() > 0) {person.setEmail(email);}while (true) {stdout.print("Enter a phone number (or leave blank to finish): ");String number = stdin.readLine();if (number.length() == 0) {break;}Person.PhoneNumber.Builder phoneNumber =Person.PhoneNumber.newBuilder().setNumber(number);stdout.print("Is this a mobile, home, or work phone? ");String type = stdin.readLine();if (type.equals("mobile")) {phoneNumber.setType(Person.PhoneType.MOBILE);} else if (type.equals("home")) {phoneNumber.setType(Person.PhoneType.HOME);} else if (type.equals("work")) {phoneNumber.setType(Person.PhoneType.WORK);} else {stdout.println("Unknown phone type.  Using default.");}person.addPhones(phoneNumber);}return person.build();}// Main function:  Reads the entire address book from a file,//   adds one person based on user input, then writes it back out to the same//   file.public static void main(String[] args) throws Exception {if (args.length != 1) {System.err.println("Usage:  AddPerson ADDRESS_BOOK_FILE");System.exit(-1);}AddressBook.Builder addressBook = AddressBook.newBuilder();// Read the existing address book.try {addressBook.mergeFrom(new FileInputStream(args[0]));} catch (FileNotFoundException e) {System.out.println(args[0] + ": File not found.  Creating a new file.");}// Add an address.addressBook.addPerson(PromptForAddress(new BufferedReader(new InputStreamReader(System.in)),System.out));// Write the new address book back to disk.FileOutputStream output = new FileOutputStream(args[0]);addressBook.build().writeTo(output);output.close();}
}

Reading A Message

Of course, an address book wouldn’t be much use if you couldn’t get any information out of it! This example reads the file created by the above example and prints all the information in it.

import com.example.tutorial.AddressBookProtos.AddressBook;
import com.example.tutorial.AddressBookProtos.Person;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;class ListPeople {// Iterates though all people in the AddressBook and prints info about them.static void Print(AddressBook addressBook) {for (Person person: addressBook.getPeopleList()) {System.out.println("Person ID: " + person.getId());System.out.println("  Name: " + person.getName());if (person.hasEmail()) {System.out.println("  E-mail address: " + person.getEmail());}for (Person.PhoneNumber phoneNumber : person.getPhonesList()) {switch (phoneNumber.getType()) {case MOBILE:System.out.print("  Mobile phone #: ");break;case HOME:System.out.print("  Home phone #: ");break;case WORK:System.out.print("  Work phone #: ");break;}System.out.println(phoneNumber.getNumber());}}}// Main function:  Reads the entire address book from a file and prints all//   the information inside.public static void main(String[] args) throws Exception {if (args.length != 1) {System.err.println("Usage:  ListPeople ADDRESS_BOOK_FILE");System.exit(-1);}// Read the existing address book.AddressBook addressBook =AddressBook.parseFrom(new FileInputStream(args[0]));Print(addressBook);}
}

Extending a Protocol Buffer

Sooner or later after you release the code that uses your protocol buffer, you will undoubtedly want to “improve” the protocol buffer’s definition. If you want your new buffers to be backwards-compatible, and your old buffers to be forward-compatible – and you almost certainly do want this – then there are some rules you need to follow. In the new version of the protocol buffer:

  • you must not change the tag numbers of any existing fields.
  • you must not add or delete any required fields.
  • you may delete optional or repeated fields.
  • you may add new optional or repeated fields but you must use fresh tag numbers (i.e. tag numbers that were never used in this protocol buffer, not even by deleted fields).
    (There are some exceptions to these rules, but they are rarely used.)

If you follow these rules, old code will happily read new messages and simply ignore any new fields. To the old code, optional fields that were deleted will simply have their default value, and deleted repeated fields will be empty. New code will also transparently read old messages. However, keep in mind that new optional fields will not be present in old messages, so you will need to either check explicitly whether they’re set with has_, or provide a reasonable default value in your .proto file with [default = value] after the tag number. If the default value is not specified for an optional element, a type-specific default value is used instead: for strings, the default value is the empty string. For booleans, the default value is false. For numeric types, the default value is zero. Note also that if you added a new repeated field, your new code will not be able to tell whether it was left empty (by new code) or never set at all (by old code) since there is no has_ flag for it.

proto的是为了序列化以及网络传输而产生的,那个.proto文件我们可以类比为java里的java文件,或者类比为模版文件,这个模版文件告诉proto的编译器,你给我按照这个文件的规则生成对应语言的代码code
最后一节都提到了两个概念Message和其对应的Code,code我们上面讲过,而Message指的不是.proto文件里的message关键字,而是运用protobuf的规范进行的网络传输时,相互传输的那些二进制字符,例如Client A把自己构造的一个ProtoBuf对象进行序列化,再把序列化之后的二进制数组传递给Client B,那么对于Client A和Client B来说,这些二进制字符串就是message

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

相关文章

  1. 内容运营、用户运营、活动运营

    内容运营 内容运营简介 不管是电商、门户、企业、政 府、搜索引擎、社区还是bbs,都有内容。他们的区别只是,内容的类型不一 样,展现的方式不一样,带给受众的感知不一样,可以参与和互动的方法不 一样。 举一个常见的例子: 当我们打开一个电商网站,我们看到了琳琅满目的商品…...

    2024/4/29 4:21:54
  2. 天猫店群:互联网高速发展下的产物,它还能生存多久?

    说起无货源店群,相信电商行业的人都知道,可以说它是一件代发的2.0版本,但也有很多不同之处。一件代发是以阿里巴巴为货源地,自己代为分销来出售。 无货源模式与之不同的就是无需囤货,可以解决积压风险和占用库房的费用;不需要自己发货,我们上架到店铺中,有人下单,我们…...

    2024/4/29 4:21:56
  3. 人工智能的智能悖论

    人工智能技术在深度学习方法和大数据的支持下发展十分迅速。在人工智能方面的研究可以追溯到上世纪五十年代。人工智能的一个最终目标是让机器可以通过图灵测试,即人工智能可以表现的像人一样,以至于与其交互的人无法辩识自己是在和人交互还是和机器交互。 如众多科幻小说和电…...

    2024/4/29 4:21:52
  4. vue.js 基础复习

    vue基础复习 1.vue简介1.JavaScript框架​ 2.用于构建用户界面的**渐进式框架**(自底向上逐层应用)​ 3.简化DOM操作​ 4.响应式数据驱动​ 5.第三方库:网络通信(axios(实现ajax))、页面跳转(router)、状态管理(vuex)Vue.js 的核心是一个允许采用简洁的模板语法来声明式…...

    2024/5/7 0:18:23
  5. ThreadLocal不会难到我们吧?

    大家好,我是方圆 一定要学好多线程!目录1. Thread、ThreadLocal和ThreadLocalMap三者的关系2. get方法3. set方法3.1 createMap方法4. remove方法4.1 重点说一说它的Value值内存泄漏问题4.1.1 先看看Entry中强引用和弱引用4.1.2 OOM问题我们需要注意的点5. ThreadLocal使用的…...

    2024/4/29 4:21:38
  6. MariaDB 修改存储路径后启动失败问题解决

    MariaDB 修改存储路径后启动失败问题解决参考文章: (1)MariaDB 修改存储路径后启动失败问题解决 (2)https://www.cnblogs.com/dizhiyaochang/p/9501991.html 备忘一下。...

    2024/4/29 4:21:40
  7. 链表的顺序存储和链式存储的区别

    顺序存储就是顺序表 链式存储就是链表基于空间的比较 1.存储分配方式 顺序表的存储空间是一次性分配的,且是连续的存储空间 链表的存储空间是多次分配的,不需要是连续的 2.存储密度 存储密度=结点值域所占的存储量/结点结构所占的存储空间的总量 顺序表的存储密度=1,链表的存…...

    2024/4/29 4:21:32
  8. try catch异常处理结构

    try catch练习题详解题目描述: 题目描述: 电脑产生一个零到100之间的随机数字,然后让用户来猜,如果用户猜的数字比这个数字大,提示太大,否则提示太小,当用户正好猜中电脑会提示,“恭喜你猜到了这个数是…”。在用户每次猜测之前程序会输出用户是第几次猜测,如果用户输入…...

    2024/4/29 3:07:30
  9. 数据库的创建与管理

    ...

    2024/4/29 3:07:27
  10. MAC地址泛洪攻击原理与过程

    MAC地址泛洪攻击原理与过程1、MAC地址泛洪攻击原理(1)交换机转发数据原理(2)MAC地址泛洪攻击原理2、MAC地址泛洪攻击过程 1、MAC地址泛洪攻击原理 (1)交换机转发数据原理 1.交换机收到数据帧的时候,先解封装数据链路层,查看源MAC地址,并且关联自己接收数据的这个接口,…...

    2024/4/29 4:21:24
  11. 面向对象程序设计——银行ATM机系统

    文章目录针对于面向对象设计——做一个简单的银行ATM机系统ATM机需求分析用户类ATM机类银行类注册操作的大概流程登录操作的大概流程用户类代码ATM机类代码bank类代码(主类)总结 针对于面向对象设计——做一个简单的银行ATM机系统 ATM机需求分析模拟用户注册,登录,修改密码…...

    2024/5/2 12:05:53
  12. 【记录 撸一个博客系统】 04.jenkins部署-Jenkins简介

    Jenkins简介 参考: https://blog.csdn.net/miss1181248983 http://www.eryajf.net/2415.html CI/CD介绍 互联网软件的开发和发布,已经形成了一套标准流程,假如把开发工作流程分为以下几个阶段: 编码 → 构建 → 集成 → 测试 → 交付 → 部署持续集成 持续集成指的是,频繁…...

    2024/4/29 4:21:15
  13. leetcode 404. 左叶子之和 基础dfs

    计算给定二叉树的所有左叶子之和。 示例:3/ \9 20/ \15 7在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/sum-of-left-leaves 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注…...

    2024/4/29 4:21:11
  14. MyBatis 一对多collection使用实例 :获取父级所有数据以及每个父级的所有子集数据

    数据内容如下表: parent字段数据对应id,如:10-流行 是 1-演唱会 的子类需要获取的data格式如下:如上图所示,获取每个level1的数据都要带有level1所有的子类数据 实现代码: 获取类如下: public class DmItemTypeVo implements Serializable {//主键private Long id;//类型…...

    2024/4/29 4:21:06
  15. 用mybatis根据对象搜索

    用mybatis根据对象查询不到查询出来的记录为0条带尺寸的图片: 居中的图片: 居中并且带尺寸的图片: 当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。 如何插入一段漂亮的代码片 去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片. // An …...

    2024/4/29 4:20:59
  16. PC 护眼模式(凑合用)

    产品经理说PC客户端要做护眼模式,理由是竞品做了!一,思路win10 自带夜间模式,win7通过调整饱和度,色调也可以达到同样的效果,但是多方查找并没有找到系统提供的api。参考其它可以实现此功能的软件,比如“联想护眼管理 v2.6.50.4081.exe”,或者 LightBulb等。有的是自己…...

    2024/4/29 4:20:56
  17. python基础之认识 Python

    认识 Python人生苦短,我用 Python —— Life is short, you need Python目标Python 的起源 为什么要用 Python? Python 的特点 Python 的优缺点01. Python 的起源Python 的创始人为吉多范罗苏姆(Guido van Rossum)1989 年的圣诞节期间,吉多范罗苏姆为了在阿姆斯特丹打发时…...

    2024/4/29 10:51:53
  18. python入门——变量的使用

    一、变量的使用 1.变量定义 在Python中, 每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建 等号(=)用来给变量赋值 左边是一个变量名 右边是存储在变量中的值 变量名 = 值 变量定义之后,后续就可以直接使用了 变量演练1 – iPython #定义qq_number 的变量用来保存q…...

    2024/4/29 4:20:48
  19. JS: 堆和栈、ES5新增属性、字符串概念

    一、堆和栈 基本数据类型和引用数据类型的区别; 01、基本数据类型之间的赋值关系;按值传递 02、引用数据类型之间的赋值关系;按引用传递(按地址传递)运行程序; 1,准备运行程序要用的空间(一旦分配好以后,内存大小没法改变了)2,开始运行程序 【引用】数据类型…...

    2024/4/29 4:20:49
  20. C#医疗保险定点结算

    C#医疗保险定点结算 本篇主要以卫生院端进行介绍,村医端和卫生院端相比,少了卫生院医生保存电子处方的功能,其余功能相同。 效果自己做的一个毕设小系统其中的一个流程:医疗保险定点结算(卫生院)实现 1.首先,病人去找卫生院医生看病,医生根据病人情况登记处方,绘制处方…...

    2024/4/29 4:20:41

最新文章

  1. 【6D位姿估计】数据集汇总 BOP

    前言 BOP是6D位姿估计基准&#xff0c;汇总整理了多个数据集&#xff0c;还举行挑战赛&#xff0c;相关报告被CVPR2024接受和认可。 它提供3D物体模型和RGB-D图像&#xff0c;其中标注信息包括6D位姿、2D边界框和2D蒙版等。 包含数据集&#xff1a;LM 、LM-O 、T-LESS 、IT…...

    2024/5/7 0:55:59
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/6 9:38:23
  3. 深入浅出 -- 系统架构之微服务中Nacos的部署

    前面我们提到过&#xff0c;在微服务架构中&#xff0c;Nacos注册中心属于核心组件&#xff0c;通常我们会采用高性能独立服务器进行部署&#xff0c;下面我们一起来看看Nacos部署过程&#xff1a; 1、环境准备 因为Nacos是支持windows和Linux系统的&#xff0c;且服务器操作…...

    2024/5/5 1:21:32
  4. 在 Visual Studio Code (VSCode) 中隐藏以 . 开头的文件

    打开VSCode。 按下Ctrl ,快捷键打开设置。您也可以点击屏幕左下角的齿轮图标&#xff0c;然后选择“Settings”。 在设置搜索框中&#xff0c;键入files.exclude。 在找到的Files: Exclude项中&#xff0c;点击Add Pattern按钮来添加一个新的模式&#xff0c;或者直接在搜索…...

    2024/5/5 2:03:53
  5. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/5/6 18:23:10
  6. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/5/6 18:40:38
  7. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/5/6 23:37:19
  8. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/5/6 7:24:07
  9. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/5/7 0:32:52
  10. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/5/6 6:01:13
  11. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/5/6 7:24:06
  12. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/5/6 1:08:53
  13. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/5/6 20:04:22
  14. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/5/7 0:32:51
  15. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/5/6 7:24:04
  16. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/5/6 7:24:04
  17. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/5/6 19:38:16
  18. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/5/6 7:24:03
  19. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/5/7 0:32:49
  20. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/5/6 21:25:34
  21. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/5/6 7:24:02
  22. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/5/6 7:24:01
  23. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/5/7 0:32:47
  24. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/5/6 16:50:57
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57