protobuf 是什么?

 

Protocol buffers是一种编码方法构造的一种有效而可扩展的格式的数据。 谷歌使用其内部几乎RPC协议和文件格式的所有协议缓冲区。

参考文档

http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/overview.html

 

API的 参考文档

protobuf 适用的语言

正宗(Google 自己内部用的)的protobuf支持三种语言:Java 、c++和Pyton,很遗憾的是并不支持.Net 或者 Lua 等语言,但社区的力量是不容忽视的,由于protobuf确实比Json、XML有速度上的优势和使用的方便,并且可以做到向前兼容、向后兼容等众多特点,所以protobuf社区又弄了个protobuf.net的组件并且还支持众多语言,详细可以看这个链接:http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns,具体某种语言的使用请各自对号入座,本篇只是讲使用android 与c++服务器通讯(测试过)或者与PC 通讯,使用java与C#之间互相通讯方面的DEMO,方面读者做参考。

(1)使用protobuf协议

定义protobuf协议 

定义protobuf协议必须创建一个以.proto为后缀的文件,以本篇为例,本篇创建了一个叫msg.proto的消息文件,内容如下:

  1. package msginfo;
  2.  
  3. message CMsg
  4.  
  5. {
  6.  
  7. required string msghead = ;
  8.  
  9. required string msgbody = ;
  10.  
  11. }
  12.  
  13. message CMsgHead
  14.  
  15. {
  16.  
  17. required int32 msglen = ;
  18.  
  19. required int32 msgtype = ;
  20.  
  21. required int32 msgseq = ;
  22.  
  23. required int32 termversion = ;
  24.  
  25. required int32 msgres = ;
  26.  
  27. required string termid = ;
  28.  
  29. }
  30.  
  31. message CMsgReg
  32.  
  33. {
  34.  
  35. optional int32 area = ;
  36.  
  37. optional int32 region = ;
  38.  
  39. optional int32 shop = ;
  40.  
  41. optional int32 ret = ;
  42.  
  43. optional string termid = [defalut=""];
  44.  
  45. }
  46.  
  47. message CMsgLogin
  48.  
  49. {
  50.  
  51. optional int32 ret = ;
  52.  
  53. }
  54.  
  55. message CMsgLogout
  56.  
  57. {
  58.  
  59. optional int32 ret = ;
  60. }

package在Java里面代表这个文件所在的包名,在c#里面代表该文件的命名空间,message代表一个类,

 

required 代表该字段必填,optional 代表该字段可选,并可以为其设置默认值,默认值格式 :[defalut=字符串就是"123" ,整型就是 123]。

如何编译该proto文件

java或android 使用的编译方法 

正宗的proto可以在Linux下编译也有提供win版编译,由于Linux下编译要配置什么g++呀,之类的有点麻烦,之前做的步骤都忘得差不多,那还是回到win版编译吧,而net 版则是需要在win版下编译。

正宗google 的protobuf 下载列表请参照:http://code.google.com/p/protobuf/downloads/list  ,选择其中的win版本下载。解压后会得到一个protoc.exe 文件,此时就可以开始编译了,先以java 为例,编译的步骤如下:

  • cmd 打开命令工具
  • 以我电脑为例,该exe 文件我放在F:\protoc 目录下,先cd 到该目录 cd F:\protoc
  • 再次进入目录后会发现该目录多了一个文件夹,即以该proto的package命名的的目录,会产生一个Msg.java的文件,这时这个文件就可以使用到我们的java或者 android 工程了。
  • 最后一步下载一个protobuf-java-2.3.0.jar的jar 包引用到你的java和android工程 里面,OK。可以使用你的protobuf了。如下图:
     protobuf-java-2.3.0.jar包的获得方法如下:

  • 下载:http://code.google.com/p/protobuf/downloads/list
  • 安装:
    • unzip protobuf-2.5.0.zip
    • cd protobuf-2.5.0
    • ./configure
    • make
    • make check
    • make install
  • java下编译protobuf:
    • 安装maven
    • cd protobuf-2.5.0/java
    • 按照README.txt编译,在target目录中生成protobuf-java-2.5.0.jar   见:protobuf 协议 windows 下 java 环境搭建
    • 在elipse添加protobuf-java-2.5.0.jar:右键你的工程目录,最后一项属性Properties,第三项Java Build Path,右边选项卡第三项Libraries,然后Add External JARS
  • c++下编译protobuf:
    • g++ -c filename.pb.cc
    • g++ -c filename.cpp
    • g++ filename.pb.o filename.o -lprotobuf
 
 
 
c#或者以后的Windows Phone 7 使用的编译方法:

.net 版的protobuf来源于proto社区,有两个版本。一个版本叫protobuf-net,官方站点:http://code.google.com/p/protobuf-net/  写法上比较符合c#一贯的写法。另一个版本叫protobuf-csharp-sport ,

 

官方站点:http://code.google.com/p/protobuf-csharp-port/ 写法上跟java上的使用极其相似,比较遵循Google 的原生态写法,所以做跨平台还是选择第二版本吧。因为你会发现几乎和java的写法没啥两样,本篇也是使用这个版本。

进入该站点,下载你要的win版。 编译步骤如下:

    • 将刚才你的proto文件放在你解压出来的目录与protoc.exe 、ProtoGen.exe、ProtoGen.exe.config放于一起。其他文件可以删除或者 备份。
    • 还是打开命令行,定位于对应的目录里面,你放proto文件的目录里面。
    • 输入:protoc --descriptor_set_out=msg.protobin --include_imports msg.proto
    • msg.protobin是要生成的prtobobin文件,可以使用这个bin文件生成cs文件
    • 再输入protogen msg.protobin  使用该bin文件生成cs文件,这样你就可以得到该 msg.cs 的CSharp版文件了,同时在VS里面使用要引入Google.ProtocolBuffers.dll。为了方便你可以将其做成一个批处理文件代码如下:
  1. echo on
  2.  
  3. protoc --descriptor_set_out=msg.protobin --include_imports msg.proto
  4.  
  5. protogen msg.protobin

  将其另存为.bat文件即可

(2)使用protobuf编译后的文件来进行socket连接

android 与PC

android 做为客户端向PC的Java服务端发送数据,服务端得到数据进行解析,并打印出来 。

客户端代码:

  1. package net.testSocket;
  2.  
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.net.Socket;
  6. import java.net.UnknownHostException;
  7.  
  8. import socket.exception.SmsClientException;
  9. import socket.exception.SmsObjException;
  10.  
  11. import msginfo.Msg.CMsg;
  12. import msginfo.Msg.CMsgHead;
  13. import msginfo.Msg.CMsgReg;
  14. import android.app.Activity;
  15. import android.os.Bundle;
  16. import android.view.View;
  17. import android.widget.Button;
  18. import android.widget.TextView;
  19.  
  20. import com.google.protobuf.InvalidProtocolBufferException;
  21.  
  22. //客户端的实现
  23. public class TestSocket extends Activity {
  24. private TextView text1;
  25. private Button but1;
  26. Socket socket = null;
  27.  
  28. public void onCreate(Bundle savedInstanceState) {
  29. super.onCreate(savedInstanceState);
  30.  
  31. // Thread desktopServerThread=new Thread(new AndroidServer());
  32. // desktopServerThread.start();
  33.  
  34. setContentView(R.layout.main);
  35.  
  36. text1 = (TextView) findViewById(R.id.text1);
  37. but1 = (Button) findViewById(R.id.but1);
  38.  
  39. but1.setOnClickListener(new Button.OnClickListener() {
  40. @Override
  41. public void onClick(View v) {
  42.  
  43. // edit1.setText("");
  44. // Log.e("dddd", "sent id");
  45. // new Thread() {
  46. // public void run() {
  47. try {
  48. // socket=new Socket("192.168.1.102",54321);
  49. //socket = new Socket("192.168.1.110", 10527);
  50. socket = new Socket("192.168.1.116", 12345);
  51. //得到发送消息的对象
  52. //SmsObj smsobj = new SmsObj(socket);
  53.  
  54. //设置消息头和消息体并存入消息里面
  55. // head
  56. CMsgHead head = CMsgHead.newBuilder().setMsglen(5)
  57. .setMsgtype(1).setMsgseq(3).setTermversion(41)
  58. .setMsgres(5).setTermid("11111111").build();
  59.  
  60. // body
  61. CMsgReg body = CMsgReg.newBuilder().setArea(22)
  62. .setRegion(33).setShop(44).build();
  63.  
  64. // Msg
  65. CMsg msg = CMsg.newBuilder()
  66. .setMsghead(head.toByteString().toStringUtf8())
  67. .setMsgbody(body.toByteString().toStringUtf8())
  68. .build();
  69.  
  70. // PrintWriter out = new PrintWriter(new BufferedWriter(
  71. // new OutputStreamWriter(socket.getOutputStream())),
  72. // true);
  73. // out.println(m.toString());
  74. // out.println(m.toByteString().toStringUtf8());
  75.  
  76. // 向服务器发送信息
  77. msg.writeTo(socket.getOutputStream());
  78. //byte[] b = msg.toByteArray();
  79. //smsobj.sendMsg(b);
  80.  
  81. // System.out.println("====msg==="
  82. // + m.toByteString().toStringUtf8());
  83.  
  84. // byte[] backBytes = smsobj.recvMsg();
  85. //
  86. // 接受服务器的信息
  87. InputStream input = socket.getInputStream();
  88.  
  89. // DataInputStream dataInput=new DataInputStream();
  90. //byte[] by = smsobj.recvMsg(input);
  91. byte[] by=recvMsg(input);
  92. setText(CMsg.parseFrom(by));
  93.  
  94. // BufferedReader br = new BufferedReader(
  95. // new InputStreamReader(socket.getInputStream()));
  96. // String mstr = br.readLine();
  97. // if (!str .equals("")) {
  98. // text1.setText(str);
  99. // } else {
  100. // text1.setText("数据错误");
  101. // }
  102. // out.close();
  103. // br.close();
  104.  
  105. input.close();
  106. //smsobj.close();
  107. socket.close();
  108. } catch (UnknownHostException e) {
  109. e.printStackTrace();
  110. } catch (IOException e) {
  111. e.printStackTrace();
  112. } catch (Exception e) {
  113. System.out.println(e.toString());
  114. }
  115. // };
  116. // }.start();
  117.  
  118. }
  119. });
  120.  
  121. }
  122.  
  123. /**
  124. * 接收server的信息
  125. *
  126. * @return
  127. * @throws SmsClientException
  128. * @author fisher
  129. */
  130. public byte[] recvMsg(InputStream inpustream) throws SmsObjException {
  131. try {
  132.  
  133. byte len[] = new byte[1024];
  134. int count = inpustream.read(len);
  135.  
  136. byte[] temp = new byte[count];
  137. for (int i = 0; i < count; i++) {
  138. temp[i] = len[i];
  139. }
  140. return temp;
  141. } catch (Exception localException) {
  142. throw new SmsObjException("SmapObj.recvMsg() occur exception!"
  143. + localException.toString());
  144. }
  145. }
  146.  
  147. /**
  148. * 得到返回值添加到文本里面
  149. *
  150. * @param g
  151. * @throws InvalidProtocolBufferException
  152. */
  153. public void setText(CMsg g) throws InvalidProtocolBufferException {
  154. CMsgHead h = CMsgHead.parseFrom(g.getMsghead().getBytes());
  155. StringBuffer sb = new StringBuffer();
  156. if (h.hasMsglen())
  157. sb.append("==len===" + h.getMsglen() + "\n");
  158. if (h.hasMsgres())
  159. sb.append("==res===" + h.getMsgres() + "\n");
  160. if (h.hasMsgseq())
  161. sb.append("==seq===" + h.getMsgseq() + "\n");
  162. if (h.hasMsgtype())
  163. sb.append("==type===" + h.getMsgtype() + "\n");
  164. if (h.hasTermid())
  165. sb.append("==Termid===" + h.getTermid() + "\n");
  166. if (h.hasTermversion())
  167. sb.append("==Termversion===" + h.getTermversion() + "\n");
  168.  
  169. CMsgReg bo = CMsgReg.parseFrom(g.getMsgbody().getBytes());
  170. if (bo.hasArea())
  171. sb.append("==area==" + bo.getArea() + "\n");
  172. if (bo.hasRegion())
  173. sb.append("==Region==" + bo.getRegion() + "\n");
  174. if (bo.hasShop())
  175. sb.append("==shop==" + bo.getShop() + "\n");
  176. if (bo.hasRet())
  177. sb.append("==Ret==" + bo.getRet() + "\n");
  178. if (bo.hasTermid())
  179. sb.append("==Termid==" + bo.getTermid() + "\n");
  180.  
  181. text1.setText(sb.toString());
  182. }

服务端代码:

package server;

  1. import java.io.DataInputStream;
  2. import java.io.DataOutputStream;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7.  
  8. import msginfo.Msg.CMsg;
  9. import msginfo.Msg.CMsgHead;
  10. import msginfo.Msg.CMsgReg;
  11.  
  12. public class AndroidServer implements Runnable {
  13.  
  14. public void run() {
  15. try {
  16. System.out.println("beign:");
  17. ServerSocket serverSocket = new ServerSocket(12345);
  18. while (true) {
  19. System.out.println("等待接收用户连接:");
  20. // 接受客户端请求
  21. Socket client = serverSocket.accept();
  22.  
  23. DataOutputStream dataOutputStream;
  24. DataInputStream dataInputStream;
  25.  
  26. try {
  27. // 接受客户端信息
  28. // BufferedReader in = new BufferedReader(
  29. // new InputStreamReader(client.getInputStream()));
  30. // String str = in.readLine();
  31. // System.out.println("read length: " + str.length());
  32. // System.out.println("read: " + str);
  33.  
  34. // InputStream inputstream = client.getInputStream();
  35. // byte[] buffer = new byte[1024 * 4];
  36. // int temp = 0;
  37. // while ((temp = inputstream.read(buffer)) != -1) {
  38. // str = new String(buffer, 0, temp);
  39. // System.out.println("===str===" + str);
  40.  
  41. // File file = new File("user\\log\\login.log");
  42. // appendLog(file, str);
  43.  
  44. InputStream inputstream = client.getInputStream();
  45.  
  46. dataOutputStream = new DataOutputStream(
  47. client.getOutputStream());
  48. //dataInputStream = new DataInputStream(inputstream);
  49.  
  50. // byte[] d = new BufferedReader(new InputStreamReader(
  51. // dataInputStream)).readLine().getBytes();
  52. // byte[] bufHeader = new byte[4];
  53. // dataInputStream.readFully(bufHeader);
  54. // int len = BytesUtil.Bytes4ToInt(bufHeader);
  55. // System.out.println(d.length);
  56. // System.out.println(dataInputStream.readLine().toString());
  57. byte len[] = new byte[1024];
  58. int count = inputstream.read(len);
  59.  
  60. byte[] temp = new byte[count];
  61.  
  62. for (int i = 0; i < count; i++) {
  63.  
  64. temp[i] = len[i];
  65. }
  66.  
  67. // 协议正文
  68. // byte[] sendByte = new byte[30];
  69. //
  70. // dataInputStream.readFully(sendByte);
  71. // for (byte b : sendByte) {
  72. // System.out.println(""+b);
  73. // }
  74. CMsg msg = CMsg.parseFrom(temp);
  75. //
  76. //
  77. CMsgHead head = CMsgHead.parseFrom(msg.getMsghead()
  78. .getBytes());
  79. System.out.println("==len===" + head.getMsglen());
  80. System.out.println("==res===" + head.getMsgres());
  81. System.out.println("==seq===" + head.getMsgseq());
  82. System.out.println("==type===" + head.getMsgtype());
  83. System.out.println("==Termid===" + head.getTermid());
  84. System.out.println("==Termversion==="
  85. + head.getTermversion());
  86.  
  87. CMsgReg body = CMsgReg.parseFrom(msg.getMsgbody()
  88. .getBytes());
  89. System.out.println("==area==" + body.getArea());
  90. System.out.println("==Region==" + body.getRegion());
  91. System.out.println("==shop==" + body.getShop());
  92.  
  93. // PrintWriter out = new PrintWriter(new BufferedWriter(
  94. // new OutputStreamWriter(client.getOutputStream())),
  95. // true);
  96. // out.println("return " +msg.toString());
  97.  
  98. // in.close();
  99. // out.close();
  100.  
  101. sendProtoBufBack(dataOutputStream);
  102.  
  103. inputstream.close();
  104. //dataInputStream.close();
  105. } catch (Exception ex) {
  106. System.out.println(ex.getMessage());
  107. ex.printStackTrace();
  108. } finally {
  109. client.close();
  110. System.out.println("close");
  111. }
  112. }
  113. } catch (IOException e) {
  114. System.out.println(e.getMessage());
  115. }
  116. }
  117.  
  118. public static void main(String[] args) {
  119. Thread desktopServerThread = new Thread(new AndroidServer());
  120. desktopServerThread.start();
  121. }
  122.  
  123. private byte[] getProtoBufBack() {
  124.  
  125. // head
  126. CMsgHead head = CMsgHead.newBuilder().setMsglen(5)
  127. .setMsgtype(1).setMsgseq(3).setTermversion(41)
  128. .setMsgres(5).setTermid("11111111").build();
  129.  
  130. // body
  131. CMsgReg body = CMsgReg.newBuilder().setArea(22)
  132. .setRegion(33).setShop(44).build();
  133.  
  134. // Msg
  135. CMsg msg = CMsg.newBuilder()
  136. .setMsghead(head.toByteString().toStringUtf8())
  137. .setMsgbody(body.toByteString().toStringUtf8())
  138. .build();
  139.  
  140. return msg.toByteArray();
  141. }
  142.  
  143. private void sendProtoBufBack(DataOutputStream dataOutputStream) {
  144.  
  145. byte[] backBytes = getProtoBufBack();
  146. // 协议头部
  147. // Integer len2 = backBytes.length;
  148. // 前四个字节,标示协议正文长度
  149. // byte[] cmdHead2 = BytesUtil.IntToBytes4(len2);
  150.  
  151. try {
  152. //dataOutputStream.write(cmdHead2, 0, cmdHead2.length);
  153. dataOutputStream.write(backBytes, 0, backBytes.length);
  154. dataOutputStream.flush();
  155. } catch (IOException e) {
  156. e.printStackTrace();
  157. }
  158. }
  159.  
  160. }

最后得到的效果:

客户端:

服务端:

protobuf .net版的实现代码如下:

  1. using System;
  2. using System.IO;
  3. using System.Net;
  4. using System.Net.Sockets;
  5. using System.Threading;
  6. using Google.ProtocolBuffers;
  7. using msginfo;
  8. using System.Text;
  9. using System.Collections;
  10. using System.Collections.Generic;
  11.  
  12. namespace protobuf_csharp_sport
  13. {
  14. class Program
  15. {
  16. private static ManualResetEvent allDone = new ManualResetEvent(false);
  17.  
  18. static void Main(string[] args)
  19. {
  20. beginProtocbuf();
  21. }
  22.  
  23. private static void beginProtocbuf()
  24. {
  25. //启动服务端
  26. TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), );
  27. server.Start();
  28. server.BeginAcceptTcpClient(clientConnected, server);
  29. Console.WriteLine("SERVER : 等待数据 ---");
  30.  
  31. //启动客户端
  32. ThreadPool.QueueUserWorkItem(runClient);
  33. allDone.WaitOne();
  34.  
  35. Console.WriteLine("SERVER : 退出 ---");
  36. // server.Stop();
  37. }
  38.  
  39. //服务端处理
  40. private static void clientConnected(IAsyncResult result)
  41. {
  42. try
  43. {
  44. TcpListener server = (TcpListener)result.AsyncState;
  45. using (TcpClient client = server.EndAcceptTcpClient(result))
  46. {
  47. using (NetworkStream stream = client.GetStream())
  48. {
  49. //获取
  50. Console.WriteLine("SERVER : 客户端已连接,数据读取中 --- ");
  51. byte[] myRequestBuffer = new byte[];
  52.  
  53. int myRequestLength = ;
  54. do
  55. {
  56. myRequestLength = stream.Read(myRequestBuffer, , myRequestBuffer.Length);
  57. }
  58. while (stream.DataAvailable);
  59.  
  60. CMsg msg = CMsg.ParseFrom(myRequestBuffer.RemoveEmptyByte(myRequestLength));
  61.  
  62. CMsgHead head = CMsgHead.ParseFrom(Encoding.ASCII.GetBytes(msg.Msghead));
  63. CMsgReg body = CMsgReg.ParseFrom(Encoding.ASCII.GetBytes(msg.Msgbody));
  64.  
  65. IDictionary<Google.ProtocolBuffers.Descriptors.FieldDescriptor, object> d = head.AllFields;
  66. foreach (var item in d)
  67. {
  68. Console.WriteLine(item.Value.ToString());
  69. }
  70.  
  71. d = body.AllFields;
  72. Console.WriteLine("===========================================");
  73. foreach (var item in d)
  74. {
  75. Console.WriteLine(item.Value.ToString());
  76. }
  77.  
  78. Console.WriteLine("SERVER : 响应成功 ---");
  79.  
  80. Console.WriteLine("SERVER: 关闭连接 ---");
  81. stream.Close();
  82. }
  83. client.Close();
  84. }
  85. }
  86. finally
  87. {
  88. allDone.Set();
  89. }
  90. }
  91.  
  92. //客户端请求
  93. private static void runClient(object state)
  94. {
  95. try
  96. {
  97. CMsgHead head = CMsgHead.CreateBuilder()
  98. .SetMsglen()
  99. .SetMsgtype()
  100. .SetMsgseq()
  101. .SetTermversion()
  102. .SetMsgres()
  103. .SetTermid("")
  104. .Build();
  105.  
  106. CMsgReg body = CMsgReg.CreateBuilder().
  107. SetArea()
  108. .SetRegion()
  109. .SetShop()
  110. .Build();
  111.  
  112. CMsg msg = CMsg.CreateBuilder()
  113. .SetMsghead(head.ToByteString().ToStringUtf8())
  114. .SetMsgbody(body.ToByteString().ToStringUtf8())
  115. .Build();
  116.  
  117. Console.WriteLine("CLIENT : 对象构造完毕 ...");
  118.  
  119. using (TcpClient client = new TcpClient())
  120. {
  121. // client.Connect(new IPEndPoint(IPAddress.Parse("192.168.1.116"), 12345));
  122. client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), ));
  123. Console.WriteLine("CLIENT : socket 连接成功 ...");
  124.  
  125. using (NetworkStream stream = client.GetStream())
  126. {
  127. //发送
  128. Console.WriteLine("CLIENT : 发送数据 ...");
  129.  
  130. msg.WriteTo(stream);
  131.  
  132. //关闭
  133. stream.Close();
  134. }
  135. client.Close();
  136. Console.WriteLine("CLIENT : 关闭 ...");
  137. }
  138. }
  139. catch (Exception error)
  140. {
  141. Console.WriteLine("CLIENT ERROR : {0}", error.ToString());
  142. }
  143. }
  144.  
  145. }//end class
  146.  
  147. public static class ExtensionClass {
  148. public static byte[] RemoveEmptyByte(this byte[] by,int length)
  149. {
  150. byte[] returnByte = new byte[length];
  151.  
  152. for (int i = ; i < length; i++)
  153. {
  154. returnByte[i] = by[i];
  155. }
  156. return returnByte;
  157.  
  158. }
  159. }
  160. }

运行的效果:

这样就OK了,之后就可以把java 服务端的IP或端口改成C# IP和服务端的商品一样,或者反过来也是可以的。c++版本经过测试也是可以的。简直是一个爽字。

ProtocolBuffers (二) android与PC,C#与Java 利用protobuf 进行无障碍通讯【Socket】的更多相关文章

  1. Java利用Rxtx进行串口通讯

    最近在做传感器数据采集的工作,底层是基于Zigbee的无线传感网络,所有数据采集到Zigbee协调器上然后通知上位机数据采集完成,上位机通过USB转串口去读取数据就可以了.那么问题来了,如何进行串口通 ...

  2. [z]c++ 和 java 利用protobuf 通讯

    [z]http://andinker.iteye.com/blog/1979428  java端的具体步骤如下: 1.首先下载 下载protobuf 编译工具   http://code.google ...

  3. 062 01 Android 零基础入门 01 Java基础语法 07 Java二维数组 01 二维数组应用

    062 01 Android 零基础入门 01 Java基础语法 07 Java二维数组 01 二维数组应用 本文知识点:二维数组应用 二维数组的声明和创建 ? 出现空指针异常 数组的名字指向数组的第 ...

  4. 010 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 04 变量的三个元素的详细介绍之二——变量类型——即Java中的数据类型

    010 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 04 变量的三个元素的详细介绍之二--变量类型--即Java中的数据类型 Java中变量的三要素 变量名 变 ...

  5. 101 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联——方案二

    101 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联--方案二 本文知识点:通过方法实现学生类与 ...

  6. 二、Android NDK编程预备之Java jni入门Hello World

    转自:  http://www.eoeandroid.com/forum.php?mod=viewthread&tid=264543&fromuid=588695 昨天已经简要介绍了J ...

  7. 四、Android学习第四天——JAVA基础回顾(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 四.Android学习第四天——JAVA基础回顾 这才学习Android的 ...

  8. 转载:微信开放平台开发第三方授权登陆(二):PC网页端

    微信开放平台开发第三方授权登陆(二):PC网页端 2018年07月24日 15:13:32 晋文子上 阅读数 12644更多 分类专栏: 微信开发 第三方授权登录   版权声明:本文为博主原创文章,遵 ...

  9. 学Android开发,入门语言java知识点

    学Android开发,入门语言java知识点 Android是一种以Linux为基础的开源码操作系统,主要使用于便携设备,而linux是用c语言和少量汇编语言写成的,如果你想研究Android,就去学 ...

随机推荐

  1. 蓝桥杯—ALGO-18 单词接龙(DFS)

    问题描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母, 要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次) ,在两个单词相连时,其 ...

  2. HDU 1934 特殊数字

    有两种车牌号.让你判断第二种是不是在第一种之后且在第一种出Kth之前的车牌号. 本解中是把前面的字母看成一位十进制的数.自己是一个26或者21进制的数.如果比较时有两种.那么第一种和第一种的最后一个比 ...

  3. 怎么从sqlserver的存储过程获得返回的数据

    1.返回一个数值 declare @count int exec @count = testReturn \'111\',\'222\' select @count @count就是返回的数值是int ...

  4. MS14-021: Internet Explorer 安全更新: 2014 年 5 月 1 日

    微软推送全平台IE零日漏洞补丁 2014.05.2 3 Comments 207 views今天,微软正式发布IE安全补丁,修复4月底曝光的零日漏洞.用户可通过Windows Update自动更新服务 ...

  5. webpack 性能优化 -- 待续

    文章 这篇文章挺不错的, 各方面优化都提到了, 有空研究下 文章 这个文章提出 , 增量打包用 webpack-watch 会让你打包速度飞快,  react不参与打包, 不require, 而是放在 ...

  6. AVAudioPlayer播放音频文件时没声音

    AVAudioPlayer播放一个mp3文件时,居然没有声音.mp3文件是放在工程里面的,路径没有错误但就是死活没有声音. func playSound() { let notifyUrl = NSB ...

  7. 务实java基础之集合总结

    Java 提供了容纳对象(或者对象的句柄)的多种方式.其中内建的类型是数组,此外, Java 的工具库提供了一些 "集合类",利用这些集合类,我们可以容纳乃至操纵自己的对象. 声明 ...

  8. Binary file to C array(bin2c)

    /******************************************************************************** * Binary file to C ...

  9. Redis的持久化策略

    Redis 持久化: 提供了多种不同级别的持久化方式:一种是RDB,另一种是AOF. RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot). AO ...

  10. jsp页面编写锚点,和html页面编写锚点

    html锚点的编写方式,在jsp中不兼容.因此在写动态网页时,需要注意 一:html页面中的锚点编写方式 HTML锚点 <a href="#abc">goto1< ...