浏览器和JS并不直接处理数据--尤其是遇到内部服务时。我的观点是,结构化格式,例如谷歌的Protocol Buffers,是一个比JSON在编码方面更好的选择。如果你从来没有使用过Protocol Buffers,你可以参看 这里。不要担心,在说明为什么要选择Protocol Buffers而不是JSON之前,本文会简介如何使用在Ruby上使用它 。
Protocal Buffers的简短介绍。
首先,什么是Protocol Buffers?文档中说:
“Protocol Buffers是一种以有效并可扩展的格式编码结构化数据的方式。”
Google开发了Protocol Buffers使用于内部的服务。 它是一种二进制格式允许你使用规范的语言定义一个模式,例如:
1 message Person { 。
2 required int32 id = 1; 。
3 required string name = 2; 。
4 optional string email = 3; 。
5 }
你能在命名空间中封装他们或者用上面的方式在顶层声明他们。这个片段定义了Person数据类型的模式,有三个字段:id, name和email。除了命名字段,你能提供一个类型决定数据怎样编码和在线上发送,在上面我们看到有int32类型和string类型。还提供了关键字进行验证和结构化(required 和optional )。字段被编号,这有助于向后兼容,我将在以后详细的介绍。
Protocol Buffers规范已被多种语言实现:Java,C,Go等。如果你四处找找最现代的语言都有实现的方式。Ruby也不例外,有几个不同的Gems使用Protocol Buffers编码和解码数据。这就意味着,这个规范可以在不同语言实现的系统间传递数据。
例如,Ruby Gem安装被称为ruby-protoc的二进制可以和主Protocol Buffers库组合使用(在OSX中brew install protobuf),自动的产生桩类文件用于编码和解码数据。正在运行的二进制proto文件产生以下的Ruby类:
view sourceprint?。
01 #!/usr/bin/env ruby 。
02 # Generated by the protocol buffer compiler. DO NOT EDIT! 。
03 require 'protocol_buffers' 。
04
05 # forward declarations 。
06 class Person < ::ProtocolBuffers::Message; end 。
07 。
08 class Person < ::ProtocolBuffers::Message 。
09 set_fully_qualified_name "Person" 。
10 。
11 required :int32, :id, 1 。
12 required :string, :name, 2 。
13 optional :string, :email, 3 。
14 end
正如你所见,通过支持这种模式(Protocol Buffer格式),用来编码和解码信息,我们就能自动得到一个类(查看代码ProtocolBuffers::Message的基类在Gem中有更多细节的介绍)。我们已经看到了一些信息,那么就让我们再来仔细看看这些特征点,让我尝试说服你考虑Protocol Buffers——这里有5个理由。
class LogonReqMessage : public ::google::protobuf::MessageLite {。
public:
LogonReqMessage();。
virtual ~LogonReqMessage();。
// implements Message ----------------------------------------------。
//下面的成员函数均实现自MessageLite中的虚函数。
//创建一个新的LogonReqMessage对象,等同于clone。
LogonReqMessage* New() const;。
//用另外一个LogonReqMessage对象初始化当前对象,等同于赋值操作符重载(operator=)
void CopyFrom(const LogonReqMessage& from);。
//清空当前对象中的所有数据,既将所有成员变量置为未初始化状态。
void Clear();。
//判断当前状态是否已经初始化。
bool IsInitialized() const;。
//在给当前对象的所有变量赋值之后,获取该对象序列化后所需要的字节数。
int ByteSize() const;。
//获取当前对象的类型名称。
::std::string GetTypeName() const;。
// required int64 acctID = 1;。
//下面的成员函数都是因message中定义的acctID字段而生成。
//这个静态成员表示AcctID的标签值。命名规则是k + FieldName(驼峰规则) + FieldNumber。
static const int kAcctIDFieldNumber = 1;。
//如果acctID字段已经被设置返回true,否则false。
inline bool has_acctid() const;。
//执行该函数后has_acctid函数将返回false,而下面的acctid函数则返回acctID的缺省值。
inline void clear_acctid();。
//返回acctid字段的当前值,如果没有设置则返回int64类型的缺省值。
inline ::google::protobuf::int64 acctid() const;。
//为acctid字段设置新值,调用该函数后has_acctid函数将返回true。
inline void set_acctid(::google::protobuf::int64 value);。
// required string passwd = 2;。
//下面的成员函数都是因message中定义的passwd字段而生成。这里生成的函数和上面acctid。
//生成的那组函数基本相似。因此这里只是列出差异部分。
static const int kPasswdFieldNumber = 2;。
inline bool has_passwd() const;。
inline void clear_passwd();。
inline const ::std::string& passwd() const;。
inline void set_passwd(const ::std::string& value);。
//对于字符串类型字段设置const char*类型的变量值。
inline void set_passwd(const char* value);。
inline void set_passwd(const char* value, size_t size);。
//可以通过返回值直接给passwd对象赋值。在调用该函数之后has_passwd将返回true。
inline ::std::string* mutable_passwd();。
//释放当前对象对passwd字段的所有权,同时返回passwd字段对象指针。调用此函数之后,passwd字段对象。
//的所有权将移交给调用者。此后再调用has_passwd函数时将返回false。
inline ::std::string* release_passwd();。
private:
... ... 。
};
PDF全称Portable Document Format,是Adobe公司开发的电子文件格式。
这种文件格式与操作系统平台无关,也就是说,PDF文件不管是在Windows,Unix还是在苹果公司的Mac OS操作系统中都是通用的。
这一特点使它成为在Internet上进行电子文档发行和数字化信息传播的理想文档格式。越来越多的电子图书、产品说明、公司文告、网络资料、电子邮件开始使用PDF格式文件。PDF格式文件目前已成为数字化信息事实上的一个工业标准。
扩展资料:
打开pdf文件的方法:
1、下载个PDF阅读器,可到百度软件中心搜索,在搜索中输入“PDF阅读”,即可搜出PDF阅读的各种软件。
2、安装后会在桌面显示一个图标,双击打开此图标。
3、弹出界面,在菜单栏中选择“文件”,选择“打开”
4、系统显示打开的文件类型的后缀为”*.pdf",找到需打开的文件,选择”打开“。
5、PDF文件打开成功。
参考资料来源:百度百科-pdf。
例子:
package org.protob;。
import org.protob.W.helloworld;。
import com.google.protobuf.InvalidProtocolBufferException;。
import com.googlecode.protobuf.format.JsonFormat;。
import com.googlecode.protobuf.format.JsonFormat.ParseException;。
/**
* 下载 protoc-2.5.0-win32.zip。
* cmd: protoc.exe --java_out=./ w.proto。
* @author liangrui。
*
*/
public class Main {。
public static void main(String[] args) throws Exception {。
main2(null);
main3(null);
main4(null);
}
//序列化 /返序列化
public static void main2(String[] args) throws InvalidProtocolBufferException {。
//序列化
helloworld.Builder builder=helloworld.newBuilder();。
builder.setId(10);。
builder.setStr("fx");。
builder.setOpt(20);。
helloworld info=builder.build(); 。
byte[] result=info.toByteArray() ; 。
//返序列化
helloworld msg = helloworld.parseFrom(result); 。
System.out.println(msg); 。
}
//protobuf转json。
public static void main3(String[] args) throws InvalidProtocolBufferException {。
//序列化
helloworld.Builder builder=helloworld.newBuilder();。
builder.setId(10);。
builder.setStr("fx");。
builder.setOpt(20);。
helloworld info=builder.build(); 。
byte[] result=info.toByteArray() ; 。
//返序列化
helloworld hello = helloworld.parseFrom(result); 。
System.out.println(hello); 。
String jsonFormat =JsonFormat.printToString(hello);。
System.out.println(jsonFormat);。
}
//josn转protobuf。
public static void main4(String[] args) throws ParseException {。
helloworld.Builder builder =helloworld.newBuilder();。
String jsonFormat = "{id:11,str:'xxx',opt:50}";。
JsonFormat.merge(jsonFormat, builder);。
System.out.println(builder.build());。
}
/**
output:
id: 10
str: "fx"
opt: 20
id: 10
str: "fx"
opt: 20
{"id": 10,"str": "fx","opt": 20}。
id: 11
str: "xxx"
opt: 50
*/
proto文件 w.proto。
package org.protob; 。
message helloworld 。
{
required int32 id = 1; // ID 。
required string str = 2; // str 。
optional int32 opt = 3; //optional field 。
}
生成后的java类
// Generated by the protocol buffer compiler. DO NOT EDIT!。
// source: w.proto。
package org.protob;。
public final class W {。
private W() {}。
public static void registerAllExtensions(。
com.google.protobuf.ExtensionRegistry registry) {。
}
public interface helloworldOrBuilder。
extends com.google.protobuf.MessageOrBuilder {。
// required int32 id = 1;。
/**
* <code>required int32 id = 1;</code>。
*
* <pre>。
* ID
* </pre>。
*/
boolean hasId();。
/**
* <code>required int32 id = 1;</code>。
*
* <pre>。
* ID
* </pre>。
*/
int getId();。
// required string str = 2;。
/**
* <code>required string str = 2;</code>。
*
* <pre>。
* str
* </pre>。
*/
boolean hasStr();。
/**
* <code>required string str = 2;</code>。
*
* <pre>。
* str
* </pre>。
*/
java.lang.String getStr();。
/**
* <code>required string str = 2;</code>。
*
* <pre>。
* str
* </pre>。
*/
com.google.protobuf.ByteString。
getStrBytes();。
// optional int32 opt = 3;。
/**
* <code>optional int32 opt = 3;</code>。
*
* <pre>。
*optional field 。
* </pre>。
*/
boolean hasOpt();。
/**
* <code>optional int32 opt = 3;</code>。
*
* <pre>。
*optional field 。
* </pre>。
*/
int getOpt();。
}
/**
* Protobuf type {@code org.protob.helloworld}。
*/
public static final class helloworld extends。
com.google.protobuf.GeneratedMessage。
implements helloworldOrBuilder {。
// Use helloworld.newBuilder() to construct.。
private helloworld(com.google.protobuf.GeneratedMessage.Builder<?> builder) {。
super(builder);。
this.unknownFields = builder.getUnknownFields();。
}
private helloworld(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }。
private static final helloworld defaultInstance;。
public static helloworld getDefaultInstance() {。
return defaultInstance;。
}
public helloworld getDefaultInstanceForType() {。
return defaultInstance;。
}
private final com.google.protobuf.UnknownFieldSet unknownFields;。
@java.lang.Override。
public final com.google.protobuf.UnknownFieldSet。
getUnknownFields() {。
return this.unknownFields;。
}
private helloworld(。
com.google.protobuf.CodedInputStream input,。
com.google.protobuf.ExtensionRegistryLite extensionRegistry)。
throws com.google.protobuf.InvalidProtocolBufferException {。
initFields();。
int mutable_bitField0_ = 0;。
com.google.protobuf.UnknownFieldSet.Builder unknownFields =。
com.google.protobuf.UnknownFieldSet.newBuilder();。
try {
boolean done = false;。
while (!done) {。
int tag = input.readTag();。
switch (tag) {。
case 0:。
done = true;。
break;。
default: {。
if (!parseUnknownField(input, unknownFields,。
extensionRegistry, tag)) {。
done = true;。
}。
break;。
}
case 8: {。
bitField0_ |= 0x00000001;。
id_ = input.readInt32();。
break;。
}
case 18: {。
bitField0_ |= 0x00000002;。
str_ = input.readBytes();。
break;。
}
case 24: {。
bitField0_ |= 0x00000004;。
opt_ = input.readInt32();。
break;。
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {。
throw e.setUnfinishedMessage(this);。
} catch (java.io.IOException e) {。
throw new com.google.protobuf.InvalidProtocolBufferException(。
e.getMessage()).setUnfinishedMessage(this);。
} finally {。
this.unknownFields = unknownFields.build();。
makeExtensionsImmutable();。
}
}
public static final com.google.protobuf.Descriptors.Descriptor。
getDescriptor() {。
return org.protob.W.internal_static_org_protob_helloworld_descriptor;。
}
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable。
internalGetFieldAccessorTable() {。
return org.protob.W.internal_static_org_protob_helloworld_fieldAccessorTable。
.ensureFieldAccessorsInitialized(。
org.protob.W.helloworld.class, org.protob.W.helloworld.Builder.class);。
}
public static com.google.protobuf.Parser<helloworld> PARSER =。
new com.google.protobuf.AbstractParser<helloworld>() {。
public helloworld parsePartialFrom(。
com.google.protobuf.CodedInputStream input,。
com.google.protobuf.ExtensionRegistryLite extensionRegistry)。
throws com.google.protobuf.InvalidProtocolBufferException {。
return new helloworld(input, extensionRegistry);。
}
};
@java.lang.Override。
public com.google.protobuf.Parser<helloworld> getParserForType() {。
return PARSER;。
}