package protobuf;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.WireFormat;
import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
String str1 = "0A094A7842726F777365721206372E31322E321A480A4631424E444846534331465A5A3139574C494A573734514D394F4552445631435A324235344E4C514430534D4A56544C46554650354A37385644354750574F454435343836314A2281016A6176612E6C616E672E5468726561640D0A636F6D2E7465616D6465762E6A7862726F777365722E656E67696E652E696E7465726E616C2E456E67696E65496D706C0D0A636F6D2E7465616D6465762E6A7862726F777365722E656E67696E652E456E67696E650D0A636F6D2E6A782E746573742E48656C6C6F576F726C640D0A";
byte[] bb = DatatypeConverter.parseHexBinary(str1);
read(bb, null);
}
public static boolean read(byte[] data, String pre) throws IOException {
if (pre == null) {
System.out.println("[");
pre = "\t";
} else {
pre = pre + "\t";
}
CodedInputStream cism = CodedInputStream.newInstance(data);
while (!cism.isAtEnd()) {
int tag = cism.readTag();
int type = WireFormat.getTagWireType(tag);
int number = WireFormat.getTagFieldNumber(tag);
switch (type) {
//int32, int64, uint32, uint64, sint32, sint64, bool, enum
//對應java(boolean int long enum)
case WireFormat.WIRETYPE_VARINT:
//按最大精確度讀取無符號數值
System.out.print(pre + number + ":");
System.out.println(cism.readUInt64());
break;
//fixed64, sfixed64, double
//對應java(long double)
case WireFormat.WIRETYPE_FIXED64:
//按最大精確度讀取無符號數值,默認不按double讀取,fixed64和sfixed64爲8位,double爲不定長
long fixed = cism.readFixed64();
if (cism.getTotalBytesRead() > 8) {
return false;
}
System.out.print(pre + number + ":");
System.out.println(fixed);
break;
//string, bytes, embedded messages, packed repeated
//對應java(string message bytestring)
case WireFormat.WIRETYPE_LENGTH_DELIMITED://會有個別字符串解析爲protobuf
ByteString bs = cism.readBytes();
if (isProtobuf(bs.toByteArray())) {//是protobuf協議繼續解析
System.out.print(pre + number + "{" + "\n");
if (!read(bs.toByteArray(), pre)) {//遞歸解析失敗時按字符串處理
System.out.println(pre + bs.toStringUtf8());
}
System.out.println(pre + "}");
} else {//不是protobuf協議則打印輸出
if (bs.isValidUtf8()) {//如果爲utf8編碼,按字符串輸出
System.out.println(pre + number + ":" + bs.toStringUtf8().replaceAll(new String("\r\n"), "\r\n" + pre));//有換行的時候對齊一下
} else {//不是輸出16進制字符串
System.out.println(pre + number + ":" + util.buf_to_string(bs.toByteArray()));
}
}
break;
//groups (deprecated)
//對應java(message),類型已經過時,出現有問題
case WireFormat.WIRETYPE_START_GROUP:
return false;
//groups (deprecated)
//對應java(message),類型已經過時,出現有問題
case WireFormat.WIRETYPE_END_GROUP:
return false;
//fixed32, sfixed32, float
//對應java(int float)
case WireFormat.WIRETYPE_FIXED32:
System.out.print(pre + number + ":");
System.out.println(cism.readFixed32());
break;
default:
System.out.println("------" + type + "------");
cism.skipField(tag);
break;
}
}
if (pre.equals("\t")) {
System.out.println("]");
}
return true;
}
/**
* 是否爲protobuf數據
*
* @param data
* @return
*/
public static boolean isProtobuf(byte[] data) {
CodedInputStream cism = CodedInputStream.newInstance(data);
try {
while (!cism.isAtEnd()) {
int tag = cism.readTag();
int type = WireFormat.getTagWireType(tag);
if (tag < 0 || type < 0 || type > 5) {
return false;
}
cism.skipField(tag);
}
} catch (IOException e) {
return false;
}
return true;
}
}