Android流媒体研究<一>,一台手机录制,另一台手机播放

来源:互联网 发布:被淘宝投诉知识产权 编辑:程序博客网 时间:2024/04/30 01:23

最近无聊,做一下android音视频方面的学习和研究。网上有很多案例值得我们去学习。我个人先去大概了解了一下音视频的一些基本概念,然后做了一个小demo,实现了一台手机录制,另一台手机实时播放。视屏录制采用的Camera,预览用的SurfaceView,把采集的视频压缩成bitmap,通过socket进行传输到另外一台手机上。这个demo只是用来学习android Camera,bitmap传输比较耗流量,所以该demo仅供学习。

视频采集客户端:
录制页面activity

package com.fm.camero;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.List;import com.fangming.myframwork.R;import com.fm.qxtapp.MyApp;import android.content.Intent;import android.content.res.Configuration;import android.graphics.ImageFormat;import android.graphics.Rect;import android.graphics.YuvImage;import android.hardware.Camera;import android.hardware.Camera.PreviewCallback;import android.hardware.Camera.Size;import android.os.Bundle;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.SurfaceHolder.Callback;import android.view.View.OnClickListener;import android.view.Window;import android.widget.Button;import android.widget.EditText;import android.widget.ImageView;/** * @describe 视频录制成图片压缩socket传输 * @author fangming * @CreateTime 2016年8月16日下午2:32:41 */public class TestcamoraActivety2 extends ServiceActivity implements Callback, PreviewCallback {    private TestcamoraActivety2 _this;    private String TAG = TestcamoraActivety2.class.getSimpleName();    private Button btn_start;    private SurfaceView sf_surfaceView;    private SurfaceHolder suHolder;    private int width;// 分辨率宽度    private int height;// 分辨率高度    private Camera mCamera;    private boolean isStreaming = false;    private MyApp myApp;    private Button btn_puse;    private ImageView iv_show;    private Boolean isShow = true;    int mwidth, mheight;    private Button btn_switch;    private Button btn_conn;    private Button btn_disconn;    private EditText et_ip;    private EditText et_port;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.activity_testcamora);        _this = this;        initView();        myApp = MyApp.getInstance();    }    private void initSurfaceholder() {        suHolder = sf_surfaceView.getHolder();        suHolder.addCallback(this);        // width = 352;        // height = 288;        width = 320;        height = 480;        mwidth = width;        mheight = height;        System.out.println("*****相机初始化完成*****");    }    private void initView() {        btn_start = (Button) findViewById(R.id.btn_start);        btn_puse = (Button) findViewById(R.id.btn_puse);        iv_show = (ImageView) findViewById(R.id.iv_show);        sf_surfaceView = (SurfaceView) findViewById(R.id.sf_surfaceView);        initSurfaceholder();        btn_start.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                mCamera.startPreview();                // new DumpFrameTask().execute();            }        });        btn_puse.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                mCamera.stopPreview();            }        });        btn_switch = (Button) findViewById(R.id.btn_switch);        btn_switch.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {            }        });        btn_conn = (Button) findViewById(R.id.btn_conn);        btn_disconn = (Button) findViewById(R.id.btn_disconn);        et_ip = (EditText) findViewById(R.id.et_ip);        et_port = (EditText) findViewById(R.id.et_port);        btn_conn.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                ip = et_ip.getText().toString();                port = et_port.getText().toString();                bindMyService();            }        });        btn_disconn.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                unBindMyService();            }        });    }    @Override    public void onPreviewFrame(byte[] data, Camera camera) {        isStreaming = true;        System.out.println("*****相机采集到的数组长度" + data.length + "*****");        if (isShow) {            mwidth = camera.getParameters().getPreviewSize().width;            mheight = camera.getParameters().getPreviewSize().height;            isShow = false;        }        YuvImage image = new YuvImage(data, ImageFormat.NV21, mwidth, height, null);        if (image != null) {            ByteArrayOutputStream outstream = new ByteArrayOutputStream();            image.compressToJpeg(new Rect(0, 0, mwidth, height), 80, outstream);            byte[] arr=outstream.toByteArray();//          Bitmap bitmap =BitmapFactory.decodeByteArray(arr,0, arr.length);//          iv_show.setRotation(90);//          iv_show.setImageBitmap(bitmap);            mService.sendDate(arr);            try {                outstream.flush();            } catch (IOException e) {                e.printStackTrace();            }        }    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        mCamera = Camera.open();        try {            mCamera.setPreviewDisplay(suHolder);        } catch (IOException e1) {            e1.printStackTrace();        }        mCamera.setPreviewCallback(this);        List<Size> previewSizes = mCamera.getParameters().getSupportedPreviewSizes();        width = previewSizes.get(0).width;        height = previewSizes.get(0).height;        Camera.Parameters parameters = mCamera.getParameters();        parameters.setPreviewSize(width, height);        // 横竖屏镜头自动调整        if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {            parameters.set("orientation", "portrait"); //            parameters.set("rotation", 90); // 镜头角度转90度(默认摄像头是横拍)            mCamera.setDisplayOrientation(90); // 在2.2以上可以使用        } else// 如果是横屏        {            parameters.set("orientation", "landscape"); //            mCamera.setDisplayOrientation(0); // 在2.2以上可以使用        }        System.out.println("*****surfaceCreated*****");    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {        System.out.println("*****系统执行surfaceChanged*****");    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        System.out.println("*****surfaceDestroyed*****");        if (mCamera != null) {            mCamera.setPreviewCallback(null);            mCamera.stopPreview();            mCamera.release();            mCamera = null;        }    }    @Override    protected void onDestroy() {        super.onDestroy();        unBindMyService();    };    @Override    public void finish() {        super.finish();        Intent mintent = new Intent();        mintent.setAction(ConnectionService.ACTION);        stopService(mintent);    }}

该activity布局:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <SurfaceView        android:id="@+id/sf_surfaceView"        android:layout_width="match_parent"        android:layout_height="300dp" />    <LinearLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:orientation="horizontal" >        <Button            android:id="@+id/btn_start"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="start" />        <Button            android:id="@+id/btn_puse"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="暂停" />        <Button            android:id="@+id/btn_switch"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="转码" />        <Button            android:id="@+id/btn_conn"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="connect" />        <Button            android:id="@+id/btn_disconn"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="disconnect" />    </LinearLayout>    <LinearLayout        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:orientation="vertical" >        <EditText            android:id="@+id/et_ip"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="192.168.1.108" />        <EditText            android:id="@+id/et_port"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="6001" />    </LinearLayout>    <ImageView        android:id="@+id/iv_show"        android:layout_width="match_parent"        android:layout_height="300dp"        android:src="@drawable/ic_launcher" /></LinearLayout>

在这个录制中,遇到的几个比较坑的地方,第一个是视频的宽和高,没有设置好,播放时会导致黑屏或者花屏。还有就是对于camera采集的视频格式的一些问题。默认是ImageFormat.NV21,也就是YUV420sp。

// yuv420P(YV12)或者yuv420SP(NV21/NV12)
parameters.setPreviewFormat(ImageFormat.NV21);

我们采集的视频最后通过onPreviewFrame这个回调接口获得

    @Override    public void onPreviewFrame(byte[] data, Camera camera) {        isStreaming = true;        System.out.println("*****相机采集到的数组长度" + data.length + "*****");        if (isShow) {            mwidth = camera.getParameters().getPreviewSize().width;            mheight = camera.getParameters().getPreviewSize().height;            isShow = false;        }        YuvImage image = new YuvImage(data, ImageFormat.NV21, mwidth, height, null);        if (image != null) {            ByteArrayOutputStream outstream = new ByteArrayOutputStream();            image.compressToJpeg(new Rect(0, 0, mwidth, height), 80, outstream);            byte[] arr=outstream.toByteArray();//          Bitmap bitmap =BitmapFactory.decodeByteArray(arr,0, arr.length);//          iv_show.setRotation(90);//          iv_show.setImageBitmap(bitmap);            //视频发送            mService.sendDate(arr);            try {                outstream.flush();            } catch (IOException e) {                e.printStackTrace();            }        }    }

采集到的视频通过mService.sendDate(arr);进行发送。mService是我自己定义的一个service用来后台处理数据。

ConnectionService类

package com.fm.camero;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.net.SocketException;import com.fm.constants.Constants;import com.fm.utill.ByteConvertUtils;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.util.Log;public class ConnectionService extends Service {    public final static String ACTION = "com.connectionService";    private final static int PACKATHEADER_SIGN_LENGTH = 2;// 我的包标识    private final static int PACKATHEADER_TYPE_LENGTH = 4;// 包类型 4byte    private final static int PACKATHEADER_DATALEN_LENGTH = 4;// 包长度 4byte    private final static int PACKATHEADER_LENGTH = PACKATHEADER_SIGN_LENGTH + PACKATHEADER_TYPE_LENGTH            + PACKATHEADER_DATALEN_LENGTH;// 包头    private String ipAdd = "192.168.1.109";    private int port = 6001;    private String TAG = "ConnectionService";    private Socket mSocket;    private OutputStream outStream;    private InputStream inStream;    private InitSocketThread initSocketThread;    private Boolean isAccepte = true;    @Override    public void onCreate() {        super.onCreate();        Log.e(TAG, "---->" + "onCreateservice");    }    @Override    public void onDestroy() {        Log.e(TAG, "---->service停止");        super.onDestroy();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.e(TAG, "---->" + "onStartCommand");        return super.onStartCommand(intent, flags, startId);    }    /**     * 初始化socket线程     */    class InitSocketThread extends Thread {        @Override        public void run() {            super.run();            initSocket();        }    }    /**     * 初始化socket     */    private synchronized void initSocket() {        Log.e(TAG, "---->创建socket成功");        try {            mSocket = new Socket(ipAdd, port);            if (mSocket.isConnected()) {                Log.e(TAG, "---->连接成功");                outStream = mSocket.getOutputStream();                inStream = mSocket.getInputStream();            }        } catch (SocketException e) {            Log.d(TAG, "socket conn fail");            e.printStackTrace();        } catch (IOException e) {            Log.d(TAG, "socket conn fail");            e.printStackTrace();        }    }    public class MyBinder extends Binder {        public ConnectionService getService() {            return ConnectionService.this;        }    }    public MyBinder mBinder = new MyBinder();    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }    public void sendDate(byte[] data) {        int datalength = data.length;        byte[] buffer = new byte[PACKATHEADER_LENGTH + datalength];        // 设置包头3000        System.arraycopy(Constants.APPREQUEST_HEAD, 0, buffer, 0, 2);        // 设置type        byte[] type = { 0, 0, 0x26, (byte) 0x48 };        System.arraycopy(type, 0, buffer, 2, 4);        // 设置长度        byte[] len = ByteConvertUtils.intToBytes(datalength);        System.arraycopy(len, 0, buffer, 6, 4);        // 设置内容        System.arraycopy(data, 0, buffer, 10, datalength);        new sendDataThread(buffer).start();    }    public class sendDataThread extends Thread {        byte byteBuffer[] = null;        public sendDataThread(byte[] data) {            this.byteBuffer = data;        }        public void run() {            try {                outStream.write(byteBuffer, 0, byteBuffer.length);                System.out.println("发送的数据长度:" + byteBuffer.length);                outStream.flush();            } catch (IOException e) {                e.printStackTrace();            }        }    }    public void setIpAndPort(String ip, String port) {        if (ip != null && !ip.equals("")) {            ipAdd = ip;        }        if (port != null && !port.equals("")) {            this.port = Integer.valueOf(port);        }        if (initSocketThread == null) {            initSocketThread = new InitSocketThread();            initSocketThread.start();        }    }}

以上就是客户端录制,下面是播放客户端

播放端activity

package com.fm.server;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.ImageView;import android.widget.Toast;public class MainActivity extends Activity {    private MainActivity _this;    private ImageView iv_btmap;    private EditText et_port;    private Button btn_bind;    private Button btn_unbind;    public String mPort;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        _this = this;        initView();    }    private void initView() {        iv_btmap = (ImageView) findViewById(R.id.iv_btmap);        et_port = (EditText) findViewById(R.id.et_port);        btn_bind = (Button) findViewById(R.id.btn_bind);        btn_unbind = (Button) findViewById(R.id.btn_unbind);        btn_bind.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                String port = et_port.getText().toString();                if (port == null || port.equals("")) {                    Toast.makeText(_this, "端口为null", Toast.LENGTH_SHORT).show();                    return;                }                mPort = port;                bindService();            }        });        btn_unbind.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                unBindService();            }        });    }    Handler mHandler = new Handler() {        public void handleMessage(Message msg) {            switch (msg.what) {            case 0:                byte[] data = (byte[]) msg.obj;                if (data == null) {                    return;                }                System.out.println("handle收到的数据:" + data.length);                BitmapFactory.Options options = new BitmapFactory.Options();                options.inSampleSize = 2;                // Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,                // data.length, options);                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);                if (bitmap != null) {                    iv_btmap.setRotation(90);                    iv_btmap.setImageBitmap(bitmap);                }                break;            default:                break;            }        };    };    @Override    public void finish() {        super.finish();        if (mService != null) {            unBindService();        }    }    public void bindService() {        Intent mintent = new Intent();        mintent.setClass(_this, BindService.class);        bindService(mintent, conn, Context.BIND_AUTO_CREATE);    }    public void unBindService() {        if (mService != null) {            unbindService(conn);        }    }    public BindService mService = null;    ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceDisconnected(ComponentName name) {            mService = null;        }        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            mService = ((BindService.MyBinder) service).getService();            mService.startConn(mPort);            mService.setHandler(mHandler);        }    };}

播放端service

package com.fm.server;import java.io.BufferedInputStream;import java.io.DataInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.net.SocketException;import java.util.Arrays;import com.fm.constants.Constants;import com.fm.utill.ByteConvertUtils;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.util.Log;public class BindService extends Service {    private String TAG = "BindService";    public int port = 6001;    public OutputStream outStream;    public InputStream inStream;    public Socket mSocket;    private InitSocketThread initSocketThread;    private ReadThread readThread;    private Boolean isAccepte = true;    ServerSocket server;    private final static int PACKATHEADER_SIGN_LENGTH = 2;// 我的包标识    private final static int PACKATHEADER_TYPE_LENGTH = 4;// 包类型 4byte    private final static int PACKATHEADER_DATALEN_LENGTH = 4;// 包长度 4byte    private final static int PACKATHEADER_LENGTH = PACKATHEADER_SIGN_LENGTH + PACKATHEADER_TYPE_LENGTH            + PACKATHEADER_DATALEN_LENGTH;// 包头    public void setPort(int port) {        this.port = port;    }    private Handler hander;    public void setHandler(Handler hander) {        this.hander = hander;    }    public void startConn(String port) {        if (port != null && !port.equals("")) {            this.port = Integer.valueOf(port);        }        initSocketThread = new InitSocketThread();        initSocketThread.start();    }    /**     * 初始化socket线程     */    class InitSocketThread extends Thread {        @Override        public void run() {            super.run();            initSocket();        }    }    /**     * 初始化socket     */    private void initSocket() {        Log.e(TAG, "---->创建socket成功");        try {            server = new ServerSocket(port);            mSocket = server.accept();            if (mSocket.isConnected()) {                Log.e(TAG, "---->连接成功");                outStream = mSocket.getOutputStream();                inStream = mSocket.getInputStream();                readThread = new ReadThread();                readThread.start();            }        } catch (SocketException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }    }    class ReadThread extends Thread {        @Override        public void run() {            super.run();            while (isAccepte) {                if (mSocket != null && mSocket.isConnected()) {                    devide(new DataInputStream(new BufferedInputStream(inStream)));                }            }        }    }    public synchronized void devide(DataInputStream ds) {        try {            if (ds.available() > 0) {                recv(ds);            }        } catch (IOException e) {            e.printStackTrace();        }    }    public void recv(DataInputStream dis) throws IOException {        byte[] head = new byte[PACKATHEADER_LENGTH];        Log.e(TAG, "---->>接收数据的长度" + dis.available());        try {            dis.readFully(head, 0, PACKATHEADER_LENGTH);        } catch (IOException e) {            return;        }        // 读取前两个字节我的数据包标识head[]        byte[] sign = new byte[2];        sign = Arrays.copyOfRange(head, 0, 2);        if (ByteConvertUtils.bytesToInt2(sign) != Constants.APP_CTL_HEAD) {            return;        }        // 读取4byte包类型        byte[] type = new byte[4];        type = Arrays.copyOfRange(head, 2, 6);        int nType = ByteConvertUtils.bytesToInt(type);        // 读取4byte内容长度        byte[] datalen = new byte[4];        datalen = Arrays.copyOfRange(head, 6, 10);        int nDatalen = ByteConvertUtils.bytesToInt(datalen);        Log.e(TAG, "type:" + nType);        switch (nType) {// App登陆/查询网关        case Constants.VEDIO_STREAM:            byte[] data = null;            if (nDatalen > 0) {                // 接收指定长度的内容                data = new byte[nDatalen];                dis.readFully(data, 0, nDatalen);                Log.e(TAG, "len:" + nDatalen);                sendMessage(data);            }            break;        default:            Log.e(TAG, "---->不识别的命令");            break;        }    };    public void sendMessage(byte[] data) {        Message msg = hander.obtainMessage();        msg.what = 0;        msg.obj = data;        hander.sendMessage(msg);    }    @Override    public void onCreate() {        Log.e(TAG, "---->" + "onCreateservice");        super.onCreate();    }    @Override    public void onDestroy() {        Log.e(TAG, "---->service停止");        super.onDestroy();        isAccepte = false;        if (readThread != null && readThread.isAlive()) {            readThread.interrupt();            readThread = null;        }        initSocketThread.interrupt();        initSocketThread = null;    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.e(TAG, "---->" + "onStartCommand");        return super.onStartCommand(intent, flags, startId);    }    public class MyBinder extends Binder {        public BindService getService() {            return BindService.this;        }    }    public MyBinder mBinder = new MyBinder();    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }}主要用来和视频采集端进行socket通信。另外附上一个简单的静态类package com.fm.constants;public class Constants {    public static final int APP_CTL_HEAD = 3000;// 包头标识    public static final byte[] APPREQUEST_HEAD={0x0b,(byte) 0xB8};//包头标识    public static final int VEDIO_STREAM = 9800;//服务端将要发送播放视频命令}

工具类:

package com.fangming.utill;import java.nio.ByteBuffer;import java.nio.ByteOrder;import android.util.Log;public class ByteConvertUtils {      /**      * 长整形转byte数组      *       * @param n      *            长整形数字      * @return 转换后的数组      */      public static byte[] longToBytes(long n) {          byte[] b = new byte[8];          b[7] = (byte) (n & 0xff);          b[6] = (byte) (n >> 8 & 0xff);          b[5] = (byte) (n >> 16 & 0xff);          b[4] = (byte) (n >> 24 & 0xff);          b[3] = (byte) (n >> 32 & 0xff);          b[2] = (byte) (n >> 40 & 0xff);          b[1] = (byte) (n >> 48 & 0xff);          b[0] = (byte) (n >> 56 & 0xff);          return b;      }      public static short[] ByteToShortArray(byte[] byteArray)    {        short[] shortArray = new short[byteArray.length/2];        ByteBuffer.wrap(byteArray).order(ByteOrder.BIG_ENDIAN).asShortBuffer().get(shortArray);        return shortArray;    }    public static byte[] StringToByteArray(String houseNo)    {        Log.i("houseNo.length","houseNo.length"+houseNo.length());        byte[] byteArray=new byte[houseNo.length()];        for(int i=0;i<houseNo.length();i++)        {            byteArray[i]=Byte.parseByte(""+houseNo.charAt(i));        }        return byteArray;    }    /**      * 长整形转byte数组      *       * @param n      *            长整形数字      * @param array      *            转换后的结果      * @param offset      *            从第offset位开始转换      */      public static void longToBytes(long n, byte[] array, int offset) {          array[7 + offset] = (byte) (n & 0xff);          array[6 + offset] = (byte) (n >> 8 & 0xff);          array[5 + offset] = (byte) (n >> 16 & 0xff);          array[4 + offset] = (byte) (n >> 24 & 0xff);          array[3 + offset] = (byte) (n >> 32 & 0xff);          array[2 + offset] = (byte) (n >> 40 & 0xff);          array[1 + offset] = (byte) (n >> 48 & 0xff);          array[0 + offset] = (byte) (n >> 56 & 0xff);      }      /**     * 将指定byte数组以16进制的形式打印到控制台     * @param hint String     * @param b byte[]     * @return void     */    public static String printHexString( byte[] b) {        StringBuffer returnValue = new StringBuffer();        for (int i = 0; i < b.length; i++) {            String hex = Integer.toHexString(b[i] & 0xFF);            if (hex.length() == 1) {                hex = '0' + hex;            }            System.out.print(hex.toUpperCase() + " ");            returnValue.append(hex.toUpperCase() + " ");        }        return "[" + returnValue.toString() + "]";    }    /**     *     * @param b byte[]     * @return String     */    public static String Bytes2HexString(byte[] b) {        String ret = "";        for (int i = 0; i < b.length; i++) {            String hex = Integer.toHexString(b[i] & 0xFF);            if (hex.length() == 1) {                hex = '0' + hex;            }            ret += hex.toUpperCase();        }        return ret;    }    /*     * 字节数组转换成Int数    读取后四个字节的内容长度     */    public static int byte2Int(byte[] b) {        int intValue = 0;        for (int i = 0; i < b.length; i++) {            intValue += (b[i] & 0xFF) << (8 * (i));        }        return intValue;    }    /**      * bytes 转 Long      *       * @param array      *            要转换的byte      * @return long长整形数字      */      public static long bytesToLong(byte[] array) {          return ((((long) array[0] & 0xff) << 56) | (((long) array[1] & 0xff) << 48) | (((long) array[2] & 0xff) << 40)                  | (((long) array[3] & 0xff) << 32) | (((long) array[4] & 0xff) << 24)                  | (((long) array[5] & 0xff) << 16) | (((long) array[6] & 0xff) << 8) | (((long) array[7] & 0xff) << 0));      }      public static short[] bytesToShorts(byte byteBuffer[]) {        int len = byteBuffer.length/2;        short[] output = new short[len];        int j = 0;        for (int i = 0; i < len; i++) {            output[i] = (short) (byteBuffer[j++] << 8);            output[i] |= (byteBuffer[j++] & 0xff);//            output[i] = (short) (byteBuffer[j++] << 8);//            output[i] += ((0x7f &byteBuffer[j]) + (byteBuffer[j] < 0 ? 128 : 0));//            j++;        }        return output;    }    public static byte[] shortsToBytes(short shortBuffer[]) {        int len = shortBuffer.length;        byte[] output = new byte[len*2];        int j = 0;        for (int i = 0; i < len; i++) {            output[j++] = (byte) (shortBuffer[i] >>> 8);            output[j++] = (byte) (0xff & shortBuffer[i]);        }        return output;    }    /**     * 将指定字符串src,以每两个字符分割转换为16进制形式 如:"2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF,     * 0xD9}     *      * @param src     *            String     * @return byte[]     */    public static byte[] hexString2Bytes(String src) {        if (src == null || "".equals(src)) {            return null;        }        byte[] tmp = src.getBytes();        int len = tmp.length / 2;        if (len <= 0) {            return null;        }        byte[] ret = new byte[len];        for (int i = 0; i < len; i++) {            ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);        }        return ret;    }    /**     * 将两个ASCII字符合成一个字节; 如:"EF"--> 0xEF     *      * @param src0     *            byte     * @param src1     *            byte     * @return byte     */    public static byte uniteBytes(byte src0, byte src1) {        byte _b0 = Byte.decode("0x" + new String(new byte[] { src0 }))                .byteValue();        _b0 = (byte) (_b0 << 4);        byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 }))                .byteValue();        byte ret = (byte) (_b0 ^ _b1);        return ret;    }    /**      * byte数组转长整形数字      *       * @param array      *            要转换的byte数组      * @param offset      *            从第offset开始转换      * @return 转换后的长整形数字      */      public static long bytesToLong(byte[] array, int offset) {          return ((((long) array[offset + 0] & 0xff) << 56) | (((long) array[offset + 1] & 0xff) << 48)                  | (((long) array[offset + 2] & 0xff) << 40) | (((long) array[offset + 3] & 0xff) << 32)                  | (((long) array[offset + 4] & 0xff) << 24) | (((long) array[offset + 5] & 0xff) << 16)                  | (((long) array[offset + 6] & 0xff) << 8) | (((long) array[offset + 7] & 0xff) << 0));      }      public static byte[] intToBytes(int n) {          byte[] b = new byte[4];          b[3] = (byte) (n & 0xff);          b[2] = (byte) (n >> 8 & 0xff);          b[1] = (byte) (n >> 16 & 0xff);          b[0] = (byte) (n >> 24 & 0xff);          return b;      }      public static void intToBytes(int n, byte[] array, int offset) {          array[3 + offset] = (byte) (n & 0xff);          array[2 + offset] = (byte) (n >> 8 & 0xff);          array[1 + offset] = (byte) (n >> 16 & 0xff);          array[offset] = (byte) (n >> 24 & 0xff);      }      /**      * @param b      * @return      */      public static int bytesToInt(byte b[]) {          return b[3] & 0xff | (b[2] & 0xff) << 8 | (b[1] & 0xff) << 16 | (b[0] & 0xff) << 24;      }     /**      * @param b      * @return      */      public static int bytesToInt2(byte b[]) {          return b[1] & 0xff | (b[0] & 0xff) << 8;      }      /**      * byte 数组转 int      *       * @param b      *            byte数组      * @param offset      *            从数组的第几位开始转      * @return 整形      */      public static int bytesToInt(byte b[], int offset) {          return b[offset + 3] & 0xff | (b[offset + 2] & 0xff) << 8 | (b[offset + 1] & 0xff) << 16                  | (b[offset] & 0xff) << 24;      }      /**      * 无符号整形转数组      *       * @param n      *            要转换的整形      * @return byte数组      */      public static byte[] uintToBytes(long n) {          byte[] b = new byte[4];          b[3] = (byte) (n & 0xff);          b[2] = (byte) (n >> 8 & 0xff);          b[1] = (byte) (n >> 16 & 0xff);          b[0] = (byte) (n >> 24 & 0xff);          return b;      }      public static void uintToBytes(long n, byte[] array, int offset) {          array[3 + offset] = (byte) (n);          array[2 + offset] = (byte) (n >> 8 & 0xff);          array[1 + offset] = (byte) (n >> 16 & 0xff);          array[offset] = (byte) (n >> 24 & 0xff);      }      public static long bytesToUint(byte[] array) {          return ((long) (array[3] & 0xff)) | ((long) (array[2] & 0xff)) << 8 | ((long) (array[1] & 0xff)) << 16                  | ((long) (array[0] & 0xff)) << 24;      }      public static long bytesToUint(byte[] array, int offset) {          return ((long) (array[offset + 3] & 0xff)) | ((long) (array[offset + 2] & 0xff)) << 8                  | ((long) (array[offset + 1] & 0xff)) << 16 | ((long) (array[offset] & 0xff)) << 24;      }      public static byte[] shortToBytes(short n) {          byte[] b = new byte[2];          b[1] = (byte) (n & 0xff);          b[0] = (byte) ((n >> 8) & 0xff);          return b;      }      public static void shortToBytes(short n, byte[] array, int offset) {          array[offset + 1] = (byte) (n & 0xff);          array[offset] = (byte) ((n >> 8) & 0xff);      }      public static short bytesToShort(byte[] b) {          return (short) (b[1] & 0xff | (b[0] & 0xff) << 8);      }      public static short bytesToShort(byte[] b, int offset) {          return (short) (b[offset + 1] & 0xff | (b[offset] & 0xff) << 8);      }      public static byte[] ushortToBytes(int n) {          byte[] b = new byte[2];          b[1] = (byte) (n & 0xff);          b[0] = (byte) ((n >> 8) & 0xff);          return b;      }      public static void ushortToBytes(int n, byte[] array, int offset) {          array[offset + 1] = (byte) (n & 0xff);          array[offset] = (byte) ((n >> 8) & 0xff);      }      public static int bytesToUshort(byte b[]) {          return b[1] & 0xff | (b[0] & 0xff) << 8;      }      public static int bytesToUshort(byte b[], int offset) {          return b[offset + 1] & 0xff | (b[offset] & 0xff) << 8;      }      public static byte[] ubyteToBytes(int n) {          byte[] b = new byte[1];          b[0] = (byte) (n & 0xff);          return b;      }      public static void ubyteToBytes(int n, byte[] array, int offset) {          array[0] = (byte) (n & 0xff);      }      public static int bytesToUbyte(byte[] array) {          return array[0] & 0xff;      }      public static int bytesToUbyte(byte[] array, int offset) {          return array[offset] & 0xff;      }      // char 类型、 float、double 类型和 byte[] 数组之间的转换关系还需继续研究实现。  }

就写到这里,欢迎加我的qq和我交流,也可以加入我们的开发交流群。
个人qq:2385313404
开发交流qq群:574424529

0 0
原创粉丝点击