Engineer in Tokyo

Protocol Buffers

A few days ago Protocol Buffers was released by Google as an open source project. Protocol Buffers is a way to generate code for objects that can be serialized to and de-serialized from the protocol buffers binary format. An implementation of the protocol buffers compiler which reads a "proto" and can output Java, Python, and C++ code. Because the format is a binary format and the compiler can output in several languages, this would allow for fast message passing between applications that may or may not be implemented in the same language.

I went ahead and created two simple Java and Python applications that test protocol buffers by simply creating a simple User object, prompting the user for a nickname and e-mail and then serializing the result. I also added a command to de-serialize the output and show the contents of the reconstituted object.

Here I ran the Java program to write the protocol buffers data to a file and then I run the python program to read it.

ian@laptop:~/src/protocol-buffers-test$ make javawrite
mkdir -p java
protoc --java_out=java/ prototest.proto
javac -classpath "java/:protobuf-java-2.0.0beta.jar" java/test.java java/prototest/Prototest.java
java -cp ".:java/:protobuf-java-2.0.0beta.jar" test write test.out
Nickname: Ian <- this is input
Email: test@test.com <- this is input
土 7月 12 19:09:28
ian@laptop:~/src/protocol-buffers-test$ make javaread
java -cp ".:java/:protobuf-java-2.0.0beta.jar" test read test.out
User
Nickname: Ian <- this is output
Email: test@test.com <- this is output
土 7月 12 19:09:33
ian@laptop:~/src/protocol-buffers-test$

Code available here. Code listing follows.

proto file: prototest.proto

option java_package = "prototest";

message User {
  required string nickname = 1;
  required string emailaddress = 2;
}

Java program: test.java

</table></div>

Python program: test.py

import prototest.*;
import com.google.protobuf.CodedInputStream;
import java.io.*;
/**
</td></tr>
 * class test
 * Class to test protobuffer
 * @author Ian Lewis <IanLewis@member.fsf.org
 */</span>
public class test {
       
  public static void main(String[] args) {
    if (args.length < 1) {
      System.err.println("Need a command");
    } else if (args.length < 2) {
      System.err.println("Need a file name");
    } else if (args[0].equals("write")) {
      try {
        Prototest.User.Builder userbuilder = Prototest.User.newBuilder();
       
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String nickname = new String();
        String email = new String();
        while (nickname.length() == 0) {
          System.out.print("Nickname: ");
          nickname = in.readLine();
          if (nickname.length() == 0) {
            System.err.println("Nickname is empty!");
          }
        }
        while (email.length() == 0) {
          System.out.print("Email: ");
          email = in.readLine();
          if (email.length() == 0) {
            System.err.println("Email is empty!");
          }
        }
       
        userbuilder.setEmailaddress(email);
        userbuilder.setNickname(nickname);
       
        FileOutputStream out = new FileOutputStream(new File(args[1]));
        userbuilder.build().writeTo(out);
        out.close();
      } catch (IOException ioe) {
        System.err.println(ioe.getMessage());
      }
    } else if (args[0].equals("read")) {
      try {
        FileInputStream filein = new FileInputStream(new File(args[1]));
        CodedInputStream in = CodedInputStream.newInstance(filein);
        Prototest.User user = Prototest.User.parseFrom(in);
        System.out.println("User");
        System.out.println("Nickname: "+user.getNickname());
        System.out.println("Email: "+user.getEmailaddress());
        filein.close();
      } catch (IOException ioe) {
        System.err.println(ioe.getMessage());
      }
    } else {
      System.err.println("Unknown command");
    }
  }
 
}
import sys
import prototest_pb2

def PromptForUser(person):
  user.nickname = raw_input("Nickname: ")
  user.emailaddress = raw_input("Email: ")
 
def PrintUsage():
  print "Usage:", sys.argv[0], "[read/write] file"
  sys.exit(-1)

if len(sys.argv) != 3 or (sys.argv[1] != "read" and sys.argv[1] != "write"):
  PrintUsage()

user = prototest_pb2.User()

# Read
if (sys.argv[1] == "read"):
  try:
    f = open(sys.argv[2], "rb")
    user.ParseFromString(f.read())
    f.close()
   
    print "User"
    print "Nickname: %s" % user.nickname
    print "Email: %s" % user.emailaddress
  except IOError:
    print sys.argv[1] + ": Could not open file."
    sys.exit(-1)
elif (sys.argv[1] == "write"):
  PromptForUser(user)
  # Write
  f = open(sys.argv[2], "wb")
  f.write(user.SerializeToString())
  f.close()
else:
  PrintUsage()
</code></pre>