1. 程式人生 > >Java使用Socket進行字串和圖片檔案同時傳輸

Java使用Socket進行字串和圖片檔案同時傳輸

  最近開發中使用到將字串和圖片同時傳輸的功能。我這邊是Android端,要接收伺服器端傳送來的資訊和圖片。由於伺服器端不是一個web servser,所以圖片和字串資訊要混雜著傳送。比較麻煩,花了一些時間解決這個問題。特記錄。

  網路上關於圖片的傳輸一般有兩種方式,一個是通過base64編碼,一個就是通過傳送端先發送圖片大小,在傳送圖片,接收端根據圖片大小讀取規定大小的資料儲存到檔案。由於base64會增加資料量,身為一個Android程式設計師,我並不想這麼實現,所以我實現第二種方式。

  首先說一下通訊協議:我定義的一條完整的資料如下:(text1)(image_start)(image_file_name)(image_file_name_end)(image_file_length)(image)(text2)(message_end)

  (text1)和(text2):圖片檔案可能是在一條完整資料的中部,所以圖片檔案前端和後端都可能存在文字資料

  (image_start):圖片檔案資料開始的標識,在程式中我使用的是(image:)。

  (image_file_name):圖片檔案的名稱,其實增加這個內容,剛開始的時候只要是想獲得檔案的字尾名從而確定圖片檔案的型別,後來乾脆就直接把圖片檔案的名稱接收算了。。。。

  (imge_file_name_end):圖片檔名結束的標識,在windows系統中,檔名中不能存在?,所以在程式中,我使用的是(?);

  (image_file_length):圖片檔案的長度,這部分是8個位元組的內容。在java中,獲取檔案的長度,返回的是一個Long型別的資料,所以傳送的時候,需要將Long型別轉化為一個8位元組的資料,接收時,要根據這8位元組的資料,轉化為Long型別。

  (image):具體的圖片檔案資訊。

  (message_end):一條完整的訊息結束的標識,在程式中我使用的是(over)。

  首先是傳送圖片的類,我在demo中,傳送圖片的是客戶端。類寫的比較簡單。

複製程式碼
  1 package util;
  2 
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.InputStream;
  6 import java.io.OutputStream;
  7 import java.net.Socket;
  8 
  9 public
class SendImage 10 { 11 private Socket socket; 12 private OutputStream os; 13 /** 14 * 圖片開始的標識 15 */ 16 private final String IMAGE_START = "image:"; 17 /** 18 * 一條完整資訊結束的標識 19 */ 20 private final String MESSAGE_END = "over"; 21 /** 22 * 檔名結束的表示 23 */ 24 private final String FILE_NAME_END = "?"; 25 26 public SendImage(String ip, int port) throws Exception 27 { 28 socket = new Socket(ip, port); 29 os = socket.getOutputStream(); 30 } 31 32 public void send() 33 { 34 try 35 { 36 File imageFile = new File("F:/1.jpg"); 37 InputStream is = new FileInputStream(imageFile); 38 39 long fileLength = imageFile.length(); 40 System.out.println("圖片長度:" + fileLength); 41 42 /*傳送第一部分的文字資訊,對應text1*/ 43 os.write("要開始傳送圖片了哦".getBytes()); 44 45 /*傳送圖片開始的標識,對應image_start*/ 46 os.write(IMAGE_START.getBytes()); 47 48 /*傳送圖片檔名稱,對應image_file_name*/ 49 os.write(imageFile.getName().getBytes()); 50 51 /*傳送圖片檔名稱結束的標識,對應image_file_name_end*/ 52 os.write(FILE_NAME_END.getBytes()); 53 54 /*傳送圖片檔案的長度,對應image_file_length*/ 55 byte[] bs = longToBytes(fileLength); 56 os.write(bs); 57 58 /*傳送圖片檔案,對應image*/ 59 int length; 60 byte[] b = new byte[1024]; 61 while ((length = is.read(b)) > 0) 62 { 63 os.write(b, 0, length); 64 } 65 66 /*傳送第二部分文字資訊,對應text2*/ 67 os.write("圖片傳送結束了".getBytes()); 68 69 /*傳送一條完整資訊結束的標識,對應message_end*/ 70 os.write(MESSAGE_END.getBytes()); 71 } 72 catch (Exception e) 73 { 74 e.printStackTrace(); 75 } 76 } 77 78 public void close() 79 { 80 try 81 { 82 os.close(); 83 socket.close(); 84 } 85 catch (Exception e) 86 { 87 88 } 89 } 90 91 /** 92 * 將長整型轉換為byte陣列 93 * @param n 94 * @return 95 */ 96 public static byte[] longToBytes(long n) 97 { 98 byte[] b = new byte[8]; 99 b[7] = (byte) (n & 0xff); 100 b[6] = (byte) (n >> 8 & 0xff); 101 b[5] = (byte) (n >> 16 & 0xff); 102 b[4] = (byte) (n >> 24 & 0xff); 103 b[3] = (byte) (n >> 32 & 0xff); 104 b[2] = (byte) (n >> 40 & 0xff); 105 b[1] = (byte) (n >> 48 & 0xff); 106 b[0] = (byte) (n >> 56 & 0xff); 107 return b; 108 } 109 110 public static void main(String[] args) 111 { 112 try 113 { 114 SendImage send = new SendImage("127.0.0.1", 40123); 115 116 /*測試多次傳送*/ 117 send.send(); 118 send.send(); 119 send.send(); 120 121 send.close(); 122 } 123 catch (Exception e) 124 { 125 e.printStackTrace(); 126 } 127 } 128 }
複製程式碼

  圖片接受端,使用的是伺服器端來接收圖片。類依然寫的很簡單。

複製程式碼
  1 package util;
  2 
  3 import java.io.File;
  4 import java.io.FileOutputStream;
  5 import java.io.IOException;
  6 import java.io.InputStream;
  7 import java.net.ServerSocket;
  8 import java.net.Socket;
  9 
 10 public class ReceiveImage2
 11 {
 12     private ServerSocket ss;
 13     private Thread listenThread;
 14     /**
 15      * 圖片開始的標識
 16      */
 17     private final String IMAGE_START = "image:";
 18     /**
 19      * 一條完整資訊結束的標識
 20      */
 21     private final String MESSAGE_END = "over";
 22     /**
 23      * 檔名結束的表示
 24      */
 25     private final String FILE_NAME_END = "?";
 26     /**
 27      * 預設的編碼,我的是UTF-8,大家可以更改成自己的編碼
 28      */
 29     private final String DEFAULT_ENCODE = "UTF-8";
 30     /**
 31      * ISO編碼
 32      */
 33     private final String ISO_ENCODE = "ISO-8859-1";
 34 
 35     public ReceiveImage2() throws Exception
 36     {
 37         ss = new ServerSocket(40123);
 38 
 39         listenThread = new Thread(new Runnable()
 40         {
 41             @Override
 42             public void run()
 43             {
 44                 listen();
 45             }
 46         });
 47 
 48         listenThread.start();
 49     }
 50 
 51     /**
 52      * 監聽連結
 53      */
 54     private void listen()
 55     {
 56         while (!ss.isClosed())
 57         {
 58             try
 59             {
 60                 final Socket s = ss.accept();
 61                 new Thread(new Runnable()
 62                 {
 63                     @Override
 64                     public void run()
 65                     {
 66                         read(s);
 67                     }
 68                 }).start();
 69             }
 70             catch (IOException e)
 71             {
 72                 e.printStackTrace();
 73             }
 74         }
 75     }
 76 
 77     /**
 78      * 讀取資訊
 79      * 
 80      * @param socket
 81      *            客戶端連結過來的socket
 82      */
 83     private void read(Socket socket)
 84     {
 85         try
 86         {
 87             InputStream is = socket.getInputStream();
 88             StringBuffer sb = new StringBuffer();
 89             int imageName = 0;
 90             while (!socket.isClosed())
 91             {
 92                 int imageStart;
 93                 while ((imageStart = sb.indexOf(IMAGE_START)) < 0)
 94                     readToBuffer(is, sb);
 95 
 96                 System.out.println("開始讀取第一部分文字資訊");
 97                 String text1 = sb.substring(0, imageStart);
 98                 text1 = new String(text1.getBytes(ISO_ENCODE), DEFAULT_ENCODE);
 99                 System.out.println("第一部分文字資訊:" + text1);
100                 sb.delete(0, imageStart + IMAGE_START.length());
101 
102                 System.out.println("開始讀取檔名稱");
103                 int file_name_end;
104                 while ((file_name_end = sb.indexOf(FILE_NAME_END)) < 0)
105                     readToBuffer(is, sb);
106                 String file_name = new String(sb.substring(0, file_name_end).getBytes(ISO_ENCODE), DEFAULT_ENCODE);
107                 System.out.println("檔名稱:" + file_name);
108                 sb.delete(0, file_name_end + FILE_NAME_END.length());
109 
110                 System.out.println("開始讀取檔案長度");
111                 while (sb.length() < 8)
112                     readToBuffer(is, sb);
113                 String imageLengthString = sb.substring(0, 8);
114                 byte[] imageLengthByteArray = imageLengthString.getBytes(ISO_ENCODE);
115                 long imageLength = bytesToLong(imageLengthByteArray);
116                 System.out.println("檔案長度:" + imageLength);
117                 sb.delete(0, 8);
118 
119                 System.out.println("開始讀取檔案");
120                 byte[] image = sb.toString().getBytes(ISO_ENCODE);
121                 FileOutputStream fos = new FileOutputStream(new File("F:/接收檔案" + imageName + file_name));
122                 if (imageLength > image.length)
123                 {
124                     System.out.println("檔案只有部分在陣列中");
125                     fos.write(image);
126                     System.out.println("已經寫了" + image.length + "還需要寫" + (imageLength - image.length));
127                     writeImage(is, fos, imageLength - image.length);
128                     sb.delete(0, sb.length());
129                 }
130                 else
131                 {
132                     System.out.println("檔案已經在陣列中");
133                     fos.write(image, 0, (int) imageLength);
134                     sb.delete(0, (int) imageLength);
135                 }
136                 fos.close();
137                 imageName++;
138                 System.out.println("檔案已經儲存");
139 
140                 int end;
141                 while ((end = sb.indexOf(MESSAGE_END)) < 0)
142                 {
143                     readToBuffer(is, sb);
144                 }
145 
146                 String text2 = new String(sb.substring(0, end).getBytes(ISO_ENCODE), DEFAULT_ENCODE);
147                 System.out.println("第二部分文字資訊:" + text2);
148                 sb.delete(0, end + MESSAGE_END.length());
149             }
150         }
151         catch (Exception e)
152         {
153             e.printStackTrace();
154         }
155         finally
156         {
157             try
158             {
159                 socket.close();
160             }
161             catch (IOException e)
162             {
163                 
164             }
165             System.out.println("執行緒結束");
166         }
167 
168     }
169 
170     /**
171      * 將輸入流中的資料讀取到stringbuffer中,一次最多讀取1024個長度
172      * 
173      * @param is
174      *            輸入流
175      * @param sb
176      *            圖片檔案輸出流
177      * @throws Exception
178      */
179     private void readToBuffer(InputStream is, StringBuffer sb) throws Exception
180     {
181         int readLength;
182         byte[] b = new byte[1024];
183 
184         readLength = is.read(b);
185         if (readLength == -1)
186             throw new RuntimeException("讀取到了-1,說明Socket已經關閉");
187         String s = new String(b, 0, readLength, ISO_ENCODE);
188         sb.append(s);
189     }
190 
191     /**
192      * 從輸入流中讀取圖片資訊到圖片檔案輸出流中
193      * 
194      * @param is
195      *            輸入流
196      * @param fos
197      *            圖片檔案輸出流
198      * @param length
199      *            需要讀取的資料長度
200      * 
            
           

相關推薦

Java使用Socket進行字串圖片檔案同時傳輸

  最近開發中使用到將字串和圖片同時傳輸的功能。我這邊是Android端,要接收伺服器端傳送來的資訊和圖片。由於伺服器端不是一個web servser,所以圖片和字串資訊要混雜著傳送。比較麻煩,花了一些時間解決這個問題。特記錄。   網路上關於圖片的傳輸一般有兩種方式,

require.js載入highcharts.js/exporting.js實現圖表的繪製圖片檔案功能的匯出

第一步:在require.js的做資料檔案中(data-main)對應的檔案中進行require.config配置,程式碼如下: require.config({ paths: { 'highcharts': '../libs/highcharts/Highcha

Handler解析字串圖片

1.許可權 //連網 2.MainActivity public class MainActivity extends AppCompatActivity { String urlString = “http://api.expoon.com/AppNews/getNewsLi

c# 中base64字串圖片的相互轉行

c#base64字串轉圖片用到了bitmap類,封裝 GDI+ 點陣圖,此點陣圖由圖形影象及其特性的畫素資料組成。 Bitmap 是用於處理由畫素資料定義的影象的物件。 具體bitmap類是什麼可以自己百度查詢,這裡就不多介紹了。 #region base64轉圖

base64字串圖片互相轉換

java類想要實現base64字串轉成圖片檔案輸出,或者圖片檔案轉成base64字串輸出,可以參考以下程式碼: package com.ttt; import java.io.FileInputStream; import java.io.FileOutputStream

不用庫函式進行字串整型資料的相互轉換

//  字串轉換成整型資料 double stoi (char* string = NULL){ if (string == NULL) throw 1;  // 空字串判斷  int i = 0; d

JAVA使用Dom4j實現字串xml檔案相互轉換

在文章《JAVA 使用Dom4j 解析XML》中,介紹了使用Dom44j解析XML,比如節點的解析遍歷、節點的增加、刪除、寫入檔案等操作,本文我們繼續使用dom4j實現xml字串與xml檔案之間的轉

利用printfsscanf進行字串數值的轉換

之前有一個筆記是字串和數字之間的轉換,現在想起來,有相同的地方。 Char szData=”12345”; Int I =1234; 在記憶體裡面,一個是ask碼,一個是int,一個是5個位元組一個是4個位元組。轉換的本質是位元組的轉換,前面有很多的方法轉換,就不在多說。這

tornadofx拖拽顯示文字檔案圖片檔案

class DragFile : View("drag and drop") { val dragFileModel = DragFileModel(this) lateinit var ap: FlowPane override val root = vbox {

圖片檔案轉化為位元組陣列字串,並對其進行Base64編碼處理 對位元組陣列字串進行Base64解碼並生成圖片

public static String imageToBase64(String path) { // 將圖片檔案轉化為位元組陣列字串,並對其進行Base64編碼處理 byte[] data = null; // 讀取圖片位元組

Spring + Ajax 同時傳輸文字檔案

需求:上傳docx檔案,輸入待替換的 人名、地名或組織名 ,然後在後端執行替換,再非同步返回給前端下載 直接將檔案和文字拼接賦給data屬性測試失敗 Html: <div id="page2" class="col s12" style="margin-top: 5%;m

android studiogithub進行關聯如何向README.md檔案中新增圖片說明

今天試了一下,在github裡面提交了簡單的工程檔案。挺好用的。 github越來越多的開發者參與,以後會經常參與其中。廢話不多說,幹活來啦! 如何使AS和github關聯 現在android開發基本都是使用android studio.在AS中,可以

檔案字串byte陣列進行MD5加密

        近來藉助網路研究了一下MD5對檔案的加密,順便也總結一下對字串和byte陣列的加密,現貼出程式碼:         import java.io.File;           import java.io.FileInputStream;        

客戶端AndroidWebservice之間的圖片檔案傳輸解決方法

最近在寫webservice介面 給客戶端提供資料和接收客戶端發來的資料。當資料型別為圖片型別的檔案時候,先把檔案轉為流,然後用Base64編碼成位元組流的字串,傳輸的還是字串。 客戶端程式碼:

在Xshell中使用sz、rz進行本機遠端主機(或虛擬機器)之間檔案傳輸

藉助XShell,使用linux命令sz可以很方便的將伺服器上的檔案下載到本地,使用rz命令則是把本地檔案上傳到伺服器。     其中,對於sz和rz的理解與記憶我用瞭如下的方法(很多時候容易搞混):     sz中的s意為send(傳送),告訴客戶端,我(伺服器

基於深度學習的病毒檢測技術無需沙箱環境,直接將樣本文件轉換為二維圖片,進而應用改造後的卷積神經網絡 Inception V4 進行訓練檢測

進制 思科 開發 主題 需求 做的 病毒 無法 大於 話題 3: 基於深度學習的二進制惡意樣本檢測 分享主題:全球正在經歷一場由科技驅動的數字化轉型,傳統技術已經不能適應病毒數量飛速增長的發展態勢。而基於沙箱的檢測方案無法滿足 APT 攻擊的檢測需求,也受到多種反沙箱技術的

在winandroid上同時進行OpenCV程序設計

line abi path width esp rgb888 轉換 最終 his 基於qt進行Android圖像處理項目設計的時候,初期可以首先在windows上進行調試,等到比較成熟後將代碼轉換到adnroid上。這裏僅以widget為例,如果使用qtquick是一樣的。

iOS 刪除專案中未使用的圖片檔案

由於隨著專案不但的版本迭代開發,資源也不斷的替換,執行檔案 + 圖片資源的也跟著不斷的累積, 導致app的”容量“不斷地增加。 為此我們需要給app瘦身,刪除一些沒有用到的類檔案和圖片資源。   1、刪圖 在進行刪除沒有用到的圖片的時候,我想到了兩種方法去實現它。 第一、

圖片檔案以二進位制方式儲存恢復

/** * 將圖片轉換成二進位制 * * @return */ static String getImageBinary() { BASE64Encoder encoder = new sun.misc.BASE64Encoder(); //本地圖片 Fil

http協議是用於從全球資訊網伺服器傳輸超文字到本地瀏覽器的傳送協議。所有www都遵從這個協議。http是一個基於TCP/IP的通訊協議來傳遞html 檔案 查詢結果 圖片檔案

HTTP 工作原理 HTTP協議工作於客戶端-服務端架構上。瀏覽器作為HTTP客戶端通過URL向HTTP服務端即WEB伺服器傳送所有請求。 Web伺服器有:Apache伺服器,IIS伺服器(Internet Information Services)等。 Web伺服器根據接收到的請求後