Android中Socket大文件断点上传

原文:http://blog.csdn.net/shimiso/article/details/8529633

什么是Socket?

所谓Socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信连的句柄,应用程序通常通过“套接字”向网络发送请求或者应答网络请求,它就是网络通信过程中端点的抽象表示。它主要包括以下两个协议:

TCP (Transmission Control Protocol 传输控制协议):传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。
      UDP (User Datagram Protocl 用户数据报协议):用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。

详细解说如下:

TCP传输和UDP不一样,TCP传输是流式的,必须先建立连接,然后数据流沿已连接的线路(虚电路)传输。因此TCP的数据流不会像UDP数据报一样,每个数据报都要包含目标地址和端口,因为每个数据报要单独路由。TCP传输则只需要在建立连接时指定目标地址和端口就可以了。

  形象的讲,TCP就像打电话,UDP就像发电报。宏观上来看UDP是不分客户端和服务端的。通信双方是平等的。微观上来讲只相对一个报文,发送端是客户端,监听端是服务端。发送端把数据报发给路由器就像把电报发给了邮局,后面的事情就是发送者无法控制,也无从知晓的了。所以说是不可靠的,可能会出现报文丢失而无从知晓。就像每张电报都要有收件人一样,每个数据报都要有目的地址和端口。

  而TCP每次连接都是分客户端和服务端的。连接的发起者(相当与拨号打电话的人)是客户端,监听者(相当于在电话边等着接电话的人)是服务端。发起者指定要连接的服务器地址和端口(相当于拨号),监听者通过和发起者三次握手建立连接(相当于听到电话响去接电话)。建立连接后双方可以互相发送和接受数据(打电话)。

Java如何操作Socket?

值得一提的是,Java分别为TCP和UDP提供了相应的类,TCP是java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。这是两个封装得非常好的类,使用起来很方便!UDP是java.net.DatagramSocket.

127.0.0.1是回路地址,用于测试,相当于localhost本机地址,没有网卡,不设DNS都可以访问,端口地址在0~65535之间,其中0~1023之间的端口是用于一些知名的网络服务和应用,用户的普通网络应用程序应该使用1024以上的端口.

Socket通信模型如下:

Android中Socket大文件断点上传

如果大家对Java Socket编程还有模糊的地方抓紧温习(http://blog.csdn.net/shimiso/article/details/8529941),本文不在此赘述,下面我们以最常用的TCP协议举例:

服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。
客户端,使用Java socket通信对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

TCP网络连接模型:

Android中Socket大文件断点上传

Android中Socket大文件断点上传

Android客户端程序代分析:

  1. UploadActivity.java
  2. package com.android.upload;
  3. import java.io.File;
  4. import java.io.OutputStream;
  5. import java.io.PushbackInputStream;
  6. import java.io.RandomAccessFile;
  7. import java.net.Socket;
  8. import android.app.Activity;
  9. import android.os.Bundle;
  10. import android.os.Environment;
  11. import android.os.Handler;
  12. import android.os.Message;
  13. import android.view.View;
  14. import android.view.View.OnClickListener;
  15. import android.widget.Button;
  16. import android.widget.EditText;
  17. import android.widget.ProgressBar;
  18. import android.widget.TextView;
  19. import android.widget.Toast;
  20. import com.android.service.UploadLogService;
  21. import com.android.socket.utils.StreamTool;
  22. public class UploadActivity extends Activity {
  23. private EditText filenameText;
  24. private TextView resulView;
  25. private ProgressBar uploadbar;
  26. private UploadLogService logService;
  27. private boolean start=true;
  28. private Handler handler = new Handler(){
  29. @Override
  30. public void handleMessage(Message msg) {
  31. int length = msg.getData().getInt("size");
  32. uploadbar.setProgress(length);
  33. float num = (float)uploadbar.getProgress()/(float)uploadbar.getMax();
  34. int result = (int)(num * 100);
  35. resulView.setText(result+ "%");
  36. if(uploadbar.getProgress()==uploadbar.getMax()){
  37. Toast.makeText(UploadActivity.this, R.string.success, 1).show();
  38. }
  39. }
  40. };
  41. @Override
  42. public void onCreate(Bundle savedInstanceState) {
  43. super.onCreate(savedInstanceState);
  44. setContentView(R.layout.main);
  45. logService = new UploadLogService(this);
  46. filenameText = (EditText)this.findViewById(R.id.filename);
  47. uploadbar = (ProgressBar) this.findViewById(R.id.uploadbar);
  48. resulView = (TextView)this.findViewById(R.id.result);
  49. Button button =(Button)this.findViewById(R.id.button);
  50. Button button1 =(Button)this.findViewById(R.id.stop);
  51. button1 .setOnClickListener(new OnClickListener() {
  52. @Override
  53. public void onClick(View v) {
  54. start=false;
  55. }
  56. });
  57. button.setOnClickListener(new View.OnClickListener() {
  58. @Override
  59. public void onClick(View v) {
  60. start=true;
  61. String filename = filenameText.getText().toString();
  62. if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
  63. File uploadFile = new File(Environment.getExternalStorageDirectory(), filename);
  64. if(uploadFile.exists()){
  65. uploadFile(uploadFile);
  66. }else{
  67. Toast.makeText(UploadActivity.this, R.string.filenotexsit, 1).show();
  68. }
  69. }else{
  70. Toast.makeText(UploadActivity.this, R.string.sdcarderror, 1).show();
  71. }
  72. }
  73. });
  74. }
  75. /**
  76. * 上传文件
  77. * @param uploadFile
  78. */
  79. private void uploadFile(final File uploadFile) {
  80. new Thread(new Runnable() {
  81. @Override
  82. public void run() {
  83. try {
  84. uploadbar.setMax((int)uploadFile.length());
  85. String souceid = logService.getBindId(uploadFile);
  86. String head = "Content-Length="+ uploadFile.length() + ";filename="+ uploadFile.getName() + ";sourceid="+
  87. (souceid==null? "" : souceid)+"\r\n";
  88. Socket socket = new Socket("192.168.1.78",7878);
  89. OutputStream outStream = socket.getOutputStream();
  90. outStream.write(head.getBytes());
  91. PushbackInputStream inStream = new PushbackInputStream(socket.getInputStream());
  92. String response = StreamTool.readLine(inStream);
  93. String[] items = response.split(";");
  94. String responseid = items[0].substring(items[0].indexOf("=")+1);
  95. String position = items[1].substring(items[1].indexOf("=")+1);
  96. if(souceid==null){//代表原来没有上传过此文件,往数据库添加一条绑定记录
  97. logService.save(responseid, uploadFile);
  98. }
  99. RandomAccessFile fileOutStream = new RandomAccessFile(uploadFile, "r");
  100. fileOutStream.seek(Integer.valueOf(position));
  101. byte[] buffer = new byte[1024];
  102. int len = -1;
  103. int length = Integer.valueOf(position);
  104. while(start&&(len = fileOutStream.read(buffer)) != -1){
  105. outStream.write(buffer, 0, len);
  106. length += len;
  107. Message msg = new Message();
  108. msg.getData().putInt("size", length);
  109. handler.sendMessage(msg);
  110. }
  111. fileOutStream.close();
  112. outStream.close();
  113. inStream.close();
  114. socket.close();
  115. if(length==uploadFile.length()) logService.delete(uploadFile);
  116. } catch (Exception e) {
  117. e.printStackTrace();
  118. }
  119. }
  120. }).start();
  121. }
  122. }
  123. StreamTool.java
  124. package com.android.socket.utils;
  125. import java.io.ByteArrayOutputStream;
  126. import java.io.File;
  127. import java.io.FileOutputStream;
  128. import java.io.IOException;
  129. import java.io.InputStream;
  130. import java.io.PushbackInputStream;
  131. public class StreamTool {
  132. public static void save(File file, byte[] data) throws Exception {
  133. FileOutputStream outStream = new FileOutputStream(file);
  134. outStream.write(data);
  135. outStream.close();
  136. }
  137. public static String readLine(PushbackInputStream in) throws IOException {
  138. char buf[] = new char[128];
  139. int room = buf.length;
  140. int offset = 0;
  141. int c;
  142. loop:       while (true) {
  143. switch (c = in.read()) {
  144. case -1:
  145. case '\n':
  146. break loop;
  147. case '\r':
  148. int c2 = in.read();
  149. if ((c2 != '\n') && (c2 != -1)) in.unread(c2);
  150. break loop;
  151. default:
  152. if (--room < 0) {
  153. char[] lineBuffer = buf;
  154. buf = new char[offset + 128];
  155. room = buf.length - offset - 1;
  156. System.arraycopy(lineBuffer, 0, buf, 0, offset);
  157. }
  158. buf[offset++] = (char) c;
  159. break;
  160. }
  161. }
  162. if ((c == -1) && (offset == 0)) return null;
  163. return String.copyValueOf(buf, 0, offset);
  164. }
  165. /**
  166. * 读取流
  167. * @param inStream
  168. * @return 字节数组
  169. * @throws Exception
  170. */
  171. public static byte[] readStream(InputStream inStream) throws Exception{
  172. ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
  173. byte[] buffer = new byte[1024];
  174. int len = -1;
  175. while( (len=inStream.read(buffer)) != -1){
  176. outSteam.write(buffer, 0, len);
  177. }
  178. outSteam.close();
  179. inStream.close();
  180. return outSteam.toByteArray();
  181. }
  182. }
  183. UploadLogService.java
  184. package com.android.service;
  185. import java.io.File;
  186. import android.content.Context;
  187. import android.database.Cursor;
  188. import android.database.sqlite.SQLiteDatabase;
  189. public class UploadLogService {
  190. private DBOpenHelper dbOpenHelper;
  191. public UploadLogService(Context context){
  192. this.dbOpenHelper = new DBOpenHelper(context);
  193. }
  194. public void save(String sourceid, File uploadFile){
  195. SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
  196. db.execSQL("insert into uploadlog(uploadfilepath, sourceid) values(?,?)",
  197. new Object[]{uploadFile.getAbsolutePath(),sourceid});
  198. }
  199. public void delete(File uploadFile){
  200. SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
  201. db.execSQL("delete from uploadlog where uploadfilepath=?", new Object[]{uploadFile.getAbsolutePath()});
  202. }
  203. public String getBindId(File uploadFile){
  204. SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
  205. Cursor cursor = db.rawQuery("select sourceid from uploadlog where uploadfilepath=?",
  206. new String[]{uploadFile.getAbsolutePath()});
  207. if(cursor.moveToFirst()){
  208. return cursor.getString(0);
  209. }
  210. return null;
  211. }
  212. }
  213. DBOpenHelper.java
  214. package com.android.service;
  215. import android.content.Context;
  216. import android.database.sqlite.SQLiteDatabase;
  217. import android.database.sqlite.SQLiteOpenHelper;
  218. public class DBOpenHelper extends SQLiteOpenHelper {
  219. public DBOpenHelper(Context context) {
  220. super(context, "upload.db", null, 1);
  221. }
  222. @Override
  223. public void onCreate(SQLiteDatabase db) {
  224. db.execSQL("CREATE TABLE uploadlog (_id integer primary key autoincrement, uploadfilepath varchar(100), sourceid varchar(10))");
  225. }
  226. @Override
  227. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  228. db.execSQL("DROP TABLE IF EXISTS uploadlog");
  229. onCreate(db);
  230. }
  231. }
  232. main.xml
  233. <?xml version="1.0" encoding="utf-8"?>
  234. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  235. android:orientation="vertical"
  236. android:layout_width="fill_parent"
  237. android:layout_height="fill_parent"
  238. >
  239. <TextView
  240. android:layout_width="fill_parent"
  241. android:layout_height="wrap_content"
  242. android:text="@string/filename"
  243. />
  244. <EditText
  245. android:layout_width="fill_parent"
  246. android:layout_height="wrap_content"
  247. android:text="022.jpg"
  248. android:id="@+id/filename"
  249. />
  250. <Button
  251. android:layout_width="wrap_content"
  252. android:layout_height="wrap_content"
  253. android:text="@string/button"
  254. android:id="@+id/button"
  255. />
  256. <Button
  257. android:layout_width="wrap_content"
  258. android:layout_height="wrap_content"
  259. android:text="暂停"
  260. android:id="@+id/stop"
  261. />
  262. <ProgressBar
  263. android:layout_width="fill_parent"
  264. android:layout_height="20px"
  265. style="?android:attr/progressBarStyleHorizontal"
  266. android:id="@+id/uploadbar"
  267. />
  268. <TextView
  269. android:layout_width="fill_parent"
  270. android:layout_height="wrap_content"
  271. android:gravity="center"
  272. android:id="@+id/result"
  273. />
  274. </LinearLayout>
  275. AndroidManifest.xml
  276. <?xml version="1.0" encoding="utf-8"?>
  277. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  278. package="com.android.upload"
  279. android:versionCode="1"
  280. android:versionName="1.0" >
  281. <uses-sdk android:minSdkVersion="8" />
  282. <application
  283. android:icon="@drawable/ic_launcher"
  284. android:label="@string/app_name" >
  285. <activity
  286. android:name=".UploadActivity"
  287. android:label="@string/app_name" >
  288. <intent-filter>
  289. <action android:name="android.intent.action.MAIN" />
  290. <category android:name="android.intent.category.LAUNCHER" />
  291. </intent-filter>
  292. </activity>
  293. </application>
  294. <!-- 访问网络的权限 -->
  295. <uses-permission android:name="android.permission.INTERNET"/>
  296. <!-- 在SDCard中创建与删除文件权限 -->
  297. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
  298. <!-- 往SDCard写入数据权限 -->
  299. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  300. </manifest>

Java服务端:

  1. SocketServer.javapackage com.android.socket.server;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.OutputStream;
  7. import java.io.PushbackInputStream;
  8. import java.io.RandomAccessFile;
  9. import java.net.ServerSocket;
  10. import java.net.Socket;
  11. import java.text.SimpleDateFormat;
  12. import java.util.Date;
  13. import java.util.HashMap;
  14. import java.util.Map;
  15. import java.util.Properties;
  16. import java.util.concurrent.ExecutorService;
  17. import java.util.concurrent.Executors;
  18. import com.android.socket.utils.StreamTool;
  19. public class SocketServer {
  20. private String uploadPath="D:/uploadFile/";
  21. private ExecutorService executorService;// 线程池
  22. private ServerSocket ss = null;
  23. private int port;// 监听端口
  24. private boolean quit;// 是否退出
  25. private Map<Long, FileLog> datas = new HashMap<Long, FileLog>();// 存放断点数据,最好改为数据库存放
  26. public SocketServer(int port) {
  27. this.port = port;
  28. // 初始化线程池
  29. executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
  30. .availableProcessors() * 50);
  31. }
  32. // 启动服务
  33. public void start() throws Exception {
  34. ss = new ServerSocket(port);
  35. while (!quit) {
  36. Socket socket = ss.accept();// 接受客户端的请求
  37. // 为支持多用户并发访问,采用线程池管理每一个用户的连接请求
  38. executorService.execute(new SocketTask(socket));// 启动一个线程来处理请求
  39. }
  40. }
  41. // 退出
  42. public void quit() {
  43. this.quit = true;
  44. try {
  45. ss.close();
  46. } catch (IOException e) {
  47. e.printStackTrace();
  48. }
  49. }
  50. public static void main(String[] args) throws Exception {
  51. SocketServer server = new SocketServer(7878);
  52. server.start();
  53. }
  54. private class SocketTask implements Runnable {
  55. private Socket socket;
  56. public SocketTask(Socket socket) {
  57. this.socket = socket;
  58. }
  59. @Override
  60. public void run() {
  61. try {
  62. System.out.println("accepted connenction from "
  63. + socket.getInetAddress() + " @ " + socket.getPort());
  64. PushbackInputStream inStream = new PushbackInputStream(
  65. socket.getInputStream());
  66. // 得到客户端发来的第一行协议数据:Content-Length=143253434;filename=xxx.3gp;sourceid=
  67. // 如果用户初次上传文件,sourceid的值为空。
  68. String head = StreamTool.readLine(inStream);
  69. System.out.println(head);
  70. if (head != null) {
  71. // 下面从协议数据中读取各种参数值
  72. String[] items = head.split(";");
  73. String filelength = items[0].substring(items[0].indexOf("=") + 1);
  74. String filename = items[1].substring(items[1].indexOf("=") + 1);
  75. String sourceid = items[2].substring(items[2].indexOf("=") + 1);
  76. Long id = System.currentTimeMillis();
  77. FileLog log = null;
  78. if (null != sourceid && !"".equals(sourceid)) {
  79. id = Long.valueOf(sourceid);
  80. log = find(id);//查找上传的文件是否存在上传记录
  81. }
  82. File file = null;
  83. int position = 0;
  84. if(log==null){//如果上传的文件不存在上传记录,为文件添加跟踪记录
  85. String path = new SimpleDateFormat("yyyy/MM/dd/HH/mm").format(new Date());
  86. File dir = new File(uploadPath+ path);
  87. if(!dir.exists()) dir.mkdirs();
  88. file = new File(dir, filename);
  89. if(file.exists()){//如果上传的文件发生重名,然后进行改名
  90. filename = filename.substring(0, filename.indexOf(".")-1)+ dir.listFiles().length+ filename.substring(filename.indexOf("."));
  91. file = new File(dir, filename);
  92. }
  93. save(id, file);
  94. }else{// 如果上传的文件存在上传记录,读取上次的断点位置
  95. file = new File(log.getPath());//从上传记录中得到文件的路径
  96. if(file.exists()){
  97. File logFile = new File(file.getParentFile(), file.getName()+".log");
  98. if(logFile.exists()){
  99. Properties properties = new Properties();
  100. properties.load(new FileInputStream(logFile));
  101. position = Integer.valueOf(properties.getProperty("length"));//读取断点位置
  102. }
  103. }
  104. }
  105. OutputStream outStream = socket.getOutputStream();
  106. String response = "sourceid="+ id+ ";position="+ position+ "\r\n";
  107. //服务器收到客户端的请求信息后,给客户端返回响应信息:sourceid=1274773833264;position=0
  108. //sourceid由服务生成,唯一标识上传的文件,position指示客户端从文件的什么位置开始上传
  109. outStream.write(response.getBytes());
  110. RandomAccessFile fileOutStream = new RandomAccessFile(file, "rwd");
  111. if(position==0) fileOutStream.setLength(Integer.valueOf(filelength));//设置文件长度
  112. fileOutStream.seek(position);//移动文件指定的位置开始写入数据
  113. byte[] buffer = new byte[1024];
  114. int len = -1;
  115. int length = position;
  116. while( (len=inStream.read(buffer)) != -1){//从输入流中读取数据写入到文件中
  117. fileOutStream.write(buffer, 0, len);
  118. length += len;
  119. Properties properties = new Properties();
  120. properties.put("length", String.valueOf(length));
  121. FileOutputStream logFile = new FileOutputStream(new File(file.getParentFile(), file.getName()+".log"));
  122. properties.store(logFile, null);//实时记录文件的最后保存位置
  123. logFile.close();
  124. }
  125. if(length==fileOutStream.length()) delete(id);
  126. fileOutStream.close();
  127. inStream.close();
  128. outStream.close();
  129. file = null;
  130. }
  131. } catch (Exception e) {
  132. e.printStackTrace();
  133. } finally {
  134. try {
  135. if(socket != null && !socket.isClosed()) socket.close();
  136. } catch (IOException e) {}
  137. }
  138. }
  139. }
  140. public FileLog find(Long sourceid) {
  141. return datas.get(sourceid);
  142. }
  143. // 保存上传记录
  144. public void save(Long id, File saveFile) {
  145. // 日后可以改成通过数据库存放
  146. datas.put(id, new FileLog(id, saveFile.getAbsolutePath()));
  147. }
  148. // 当文件上传完毕,删除记录
  149. public void delete(long sourceid) {
  150. if (datas.containsKey(sourceid))
  151. datas.remove(sourceid);
  152. }
  153. private class FileLog {
  154. private Long id;
  155. private String path;
  156. public FileLog(Long id, String path) {
  157. super();
  158. this.id = id;
  159. this.path = path;
  160. }
  161. public Long getId() {
  162. return id;
  163. }
  164. public void setId(Long id) {
  165. this.id = id;
  166. }
  167. public String getPath() {
  168. return path;
  169. }
  170. public void setPath(String path) {
  171. this.path = path;
  172. }
  173. }
  174. }
  175. ServerWindow.javapackage com.android.socket.server;
  176. import java.awt.BorderLayout;
  177. import java.awt.Frame;
  178. import java.awt.Label;
  179. import java.awt.event.WindowEvent;
  180. import java.awt.event.WindowListener;
  181. public class ServerWindow extends Frame{
  182. private SocketServer server;
  183. private Label label;
  184. public ServerWindow(String title){
  185. super(title);
  186. server = new SocketServer(7878);
  187. label = new Label();
  188. add(label, BorderLayout.PAGE_START);
  189. label.setText("服务器已经启动");
  190. this.addWindowListener(new WindowListener() {
  191. @Override
  192. public void windowOpened(WindowEvent e) {
  193. new Thread(new Runnable() {
  194. @Override
  195. public void run() {
  196. try {
  197. server.start();
  198. } catch (Exception e) {
  199. e.printStackTrace();
  200. }
  201. }
  202. }).start();
  203. }
  204. @Override
  205. public void windowIconified(WindowEvent e) {
  206. }
  207. @Override
  208. public void windowDeiconified(WindowEvent e) {
  209. }
  210. @Override
  211. public void windowDeactivated(WindowEvent e) {
  212. }
  213. @Override
  214. public void windowClosing(WindowEvent e) {
  215. server.quit();
  216. System.exit(0);
  217. }
  218. @Override
  219. public void windowClosed(WindowEvent e) {
  220. }
  221. @Override
  222. public void windowActivated(WindowEvent e) {
  223. }
  224. });
  225. }
  226. /**
  227. * @param args
  228. */
  229. public static void main(String[] args) {
  230. ServerWindow window = new ServerWindow("文件上传服务端");
  231. window.setSize(300, 300);
  232. window.setVisible(true);
  233. }
  234. }
  235. StreamTool.javapackage com.android.socket.utils;
  236. import java.io.ByteArrayOutputStream;
  237. import java.io.File;
  238. import java.io.FileOutputStream;
  239. import java.io.IOException;
  240. import java.io.InputStream;
  241. import java.io.PushbackInputStream;
  242. public class StreamTool {
  243. public static void save(File file, byte[] data) throws Exception {
  244. FileOutputStream outStream = new FileOutputStream(file);
  245. outStream.write(data);
  246. outStream.close();
  247. }
  248. public static String readLine(PushbackInputStream in) throws IOException {
  249. char buf[] = new char[128];
  250. int room = buf.length;
  251. int offset = 0;
  252. int c;
  253. loop:       while (true) {
  254. switch (c = in.read()) {
  255. case -1:
  256. case '\n':
  257. break loop;
  258. case '\r':
  259. int c2 = in.read();
  260. if ((c2 != '\n') && (c2 != -1)) in.unread(c2);
  261. break loop;
  262. default:
  263. if (--room < 0) {
  264. char[] lineBuffer = buf;
  265. buf = new char[offset + 128];
  266. room = buf.length - offset - 1;
  267. System.arraycopy(lineBuffer, 0, buf, 0, offset);
  268. }
  269. buf[offset++] = (char) c;
  270. break;
  271. }
  272. }
  273. if ((c == -1) && (offset == 0)) return null;
  274. return String.copyValueOf(buf, 0, offset);
  275. }
  276. /**
  277. * 读取流
  278. * @param inStream
  279. * @return 字节数组
  280. * @throws Exception
  281. */
  282. public static byte[] readStream(InputStream inStream) throws Exception{
  283. ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
  284. byte[] buffer = new byte[1024];
  285. int len = -1;
  286. while( (len=inStream.read(buffer)) != -1){
  287. outSteam.write(buffer, 0, len);
  288. }
  289. outSteam.close();
  290. inStream.close();
  291. return outSteam.toByteArray();
  292. }
  293. }

运行效果如下:
Android前端控制:
Android中Socket大文件断点上传

后台监控日志:

Android中Socket大文件断点上传

下载后的文件路径:

Android中Socket大文件断点上传

源码下载地址

上一篇:1490 ACM 数学


下一篇:windows中cmd常用命令收集