今天学习了Android开发中比較难的一个环节,就是断点续传下载,非常多人看到这个标题就感觉头大。的确,假设没有良好的逻辑思维,这块的确非常难搞明确。以下我就将自己学到的知识和一些见解写下供那些在这个环节还烦恼的人參考。这里我以下载mp3文件为例。

断点续传下载,顾名思义。那就是我们在一次下载未结束时。退出下载,第二次下载时会接着第一次下载的进度继续下载。那么怎么记录第一次下载的数据呢。这里肯定就要用到数据库了。以下就是我创建数据库的一个SQLiteOpenHelper类。用来首次执行时创建数据库。

DBHelper类:

 1 package cn.yj3g.DBHelper;
2
3 import android.content.Context;
4 import android.database.sqlite.SQLiteDatabase;
5 import android.database.sqlite.SQLiteOpenHelper;
6
7 /**
8 * 建立一个数据库帮助类
9 */
10 public class DBHelper extends SQLiteOpenHelper {
11 //download.db-->数据库名
12 public DBHelper(Context context) {
13 super(context, "download.db", null, 1);
14 }
15
16 /**
17 * 在download.db数据库下创建一个download_info表存储下载信息
18 */
19 @Override
20 public void onCreate(SQLiteDatabase db) {
21 db.execSQL("create table download_info(_id integer PRIMARY KEY AUTOINCREMENT, thread_id integer, "
22 + "start_pos integer, end_pos integer, compelete_size integer,url char)");
23 }
24 @Override
25 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
26
27 }
28
29 }

以下来看主界面的布局,在这里。我仅仅设计了一个ListView来显示下载的音乐的名称,和一个開始下载button和一个暂停button。

布局文件例如以下:

main.xml:

 1 <?

xml version="1.0" encoding="utf-8"?

>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent"
6 android:id="@+id/llRoot">
7 <ListView android:id="@android:id/list"
8 android:layout_width="fill_parent"
9 android:layout_height="fill_parent">
10 </ListView>
11 </LinearLayout>

list_item.xml:

 1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="wrap_content">
6 <LinearLayout
7 android:orientation="horizontal"
8 android:layout_width="fill_parent"
9 android:layout_height="wrap_content"
10 android:layout_marginBottom="5dip">
11 <TextView
12 android:layout_width="fill_parent"
13 android:layout_height="wrap_content"
14 android:layout_weight="1"
15 android:id="@+id/tv_resouce_name"/>
16 <Button
17 android:layout_width="fill_parent"
18 android:layout_height="wrap_content"
19 android:layout_weight="1"
20 android:text="下载"
21 android:id="@+id/btn_start"
22 android:onClick="startDownload"/>
23 <Button
24 android:layout_width="fill_parent"
25 android:layout_height="wrap_content"
26 android:layout_weight="1"
27 android:text="暂停"
28 android:id="@+id/btn_pause"
29 android:onClick="pauseDownload"/>
30 </LinearLayout>
31 </LinearLayout>

主界面执行效果例如以下:

以下我们来看详细实现下载的方法。首先。我们要定义一个记录在下载时各个时期的数据的类。这里我创建了一个DownloadInfo类来记录。代码例如以下:

DownloadInfo:

 1 package cn.yj3g.entity;
2 /**
3 *创建一个下载信息的实体类
4 */
5 public class DownloadInfo {
6 private int threadId;//下载器id
7 private int startPos;//開始点
8 private int endPos;//结束点
9 private int compeleteSize;//完毕度
10 private String url;//下载器网络标识
11 public DownloadInfo(int threadId, int startPos, int endPos,
12 int compeleteSize,String url) {
13 this.threadId = threadId;
14 this.startPos = startPos;
15 this.endPos = endPos;
16 this.compeleteSize = compeleteSize;
17 this.url=url;
18 }
19 public DownloadInfo() {
20 }
21 public String getUrl() {
22 return url;
23 }
24 public void setUrl(String url) {
25 this.url = url;
26 }
27 public int getThreadId() {
28 return threadId;
29 }
30 public void setThreadId(int threadId) {
31 this.threadId = threadId;
32 }
33 public int getStartPos() {
34 return startPos;
35 }
36 public void setStartPos(int startPos) {
37 this.startPos = startPos;
38 }
39 public int getEndPos() {
40 return endPos;
41 }
42 public void setEndPos(int endPos) {
43 this.endPos = endPos;
44 }
45 public int getCompeleteSize() {
46 return compeleteSize;
47 }
48 public void setCompeleteSize(int compeleteSize) {
49 this.compeleteSize = compeleteSize;
50 }
51
52 @Override
53 public String toString() {
54 return "DownloadInfo [threadId=" + threadId
55 + ", startPos=" + startPos + ", endPos=" + endPos
56 + ", compeleteSize=" + compeleteSize +"]";
57 }
58 }

在下载时,我们有进度条来显示运行进度,怎么确定进度条的进度,大小和起始位置呢?这里我定义了一个LoadInfo类来记录下载器具体信息。代码例如以下:

LoadInfo:

 1 package cn.yj3g.entity;
2 /**
3 *自己定义的一个记载下载器具体信息的类
4 */
5 public class LoadInfo {
6 public int fileSize;//文件大小
7 private int complete;//完毕度
8 private String urlstring;//下载器标识
9 public LoadInfo(int fileSize, int complete, String urlstring) {
10 this.fileSize = fileSize;
11 this.complete = complete;
12 this.urlstring = urlstring;
13 }
14 public LoadInfo() {
15 }
16 public int getFileSize() {
17 return fileSize;
18 }
19 public void setFileSize(int fileSize) {
20 this.fileSize = fileSize;
21 }
22 public int getComplete() {
23 return complete;
24 }
25 public void setComplete(int complete) {
26 this.complete = complete;
27 }
28 public String getUrlstring() {
29 return urlstring;
30 }
31 public void setUrlstring(String urlstring) {
32 this.urlstring = urlstring;
33 }
34 @Override
35 public String toString() {
36 return "LoadInfo [fileSize=" + fileSize + ", complete=" + complete
37 + ", urlstring=" + urlstring + "]";
38 }
39 }

以下是最最重要的一步,那就是定义一个下载器来进行下载了,这里我就不多说。详细解释在代码中都有注解。我就直接将代码附下。供大家研究參考

Downloader:

  1 package cn.yj3g.service;
2
3 import java.io.File;
4 import java.io.InputStream;
5 import java.io.RandomAccessFile;
6 import java.net.HttpURLConnection;
7 import java.net.URL;
8 import java.util.ArrayList;
9 import java.util.List;
10 import android.content.Context;
11 import android.os.Handler;
12 import android.os.Message;
13 import android.util.Log;
14 import cn.yj3g.Dao.Dao;
15 import cn.yj3g.entity.DownloadInfo;
16 import cn.yj3g.entity.LoadInfo;
17
18 public class Downloader {
19 private String urlstr;// 下载的地址
20 private String localfile;// 保存路径
21 private int threadcount;// 线程数
22 private Handler mHandler;// 消息处理器
23 private Dao dao;// 工具类
24 private int fileSize;// 所要下载的文件的大小
25 private List<DownloadInfo> infos;// 存放下载信息类的集合
26 private static final int INIT = 1;//定义三种下载的状态:初始化状态,正在下载状态。暂停状态
27 private static final int DOWNLOADING = 2;
28 private static final int PAUSE = 3;
29 private int state = INIT;
30
31 public Downloader(String urlstr, String localfile, int threadcount,
32 Context context, Handler mHandler) {
33 this.urlstr = urlstr;
34 this.localfile = localfile;
35 this.threadcount = threadcount;
36 this.mHandler = mHandler;
37 dao = new Dao(context);
38 }
39 /**
40 *推断是否正在下载
41 */
42 public boolean isdownloading() {
43 return state == DOWNLOADING;
44 }
45 /**
46 * 得到downloader里的信息
47 * 首先进行推断是否是第一次下载。假设是第一次就要进行初始化。并将下载器的信息保存到数据库中
48 * 假设不是第一次下载,那就要从数据库中读出之前下载的信息(起始位置,结束为止。文件大小等),并将下载信息返回给下载器
49 */
50 public LoadInfo getDownloaderInfors() {
51 if (isFirst(urlstr)) {
52 Log.v("TAG", "isFirst");
53 init();
54 int range = fileSize / threadcount;
55 infos = new ArrayList<DownloadInfo>();
56 for (int i = 0; i < threadcount - 1; i++) {
57 DownloadInfo info = new DownloadInfo(i, i * range, (i + 1)* range - 1, 0, urlstr);
58 infos.add(info);
59 }
60 DownloadInfo info = new DownloadInfo(threadcount - 1,(threadcount - 1) * range, fileSize - 1, 0, urlstr);
61 infos.add(info);
62 //保存infos中的数据到数据库
63 dao.saveInfos(infos);
64 //创建一个LoadInfo对象记载下载器的详细信息
65 LoadInfo loadInfo = new LoadInfo(fileSize, 0, urlstr);
66 return loadInfo;
67 } else {
68 //得到数据库中已有的urlstr的下载器的详细信息
69 infos = dao.getInfos(urlstr);
70 Log.v("TAG", "not isFirst size=" + infos.size());
71 int size = 0;
72 int compeleteSize = 0;
73 for (DownloadInfo info : infos) {
74 compeleteSize += info.getCompeleteSize();
75 size += info.getEndPos() - info.getStartPos() + 1;
76 }
77 return new LoadInfo(size, compeleteSize, urlstr);
78 }
79 }
80
81 /**
82 * 初始化
83 */
84 private void init() {
85 try {
86 URL url = new URL(urlstr);
87 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
88 connection.setConnectTimeout(5000);
89 connection.setRequestMethod("GET");
90 fileSize = connection.getContentLength();
91
92 File file = new File(localfile);
93 if (!file.exists()) {
94 file.createNewFile();
95 }
96 // 本地訪问文件
97 RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
98 accessFile.setLength(fileSize);
99 accessFile.close();
100 connection.disconnect();
101 } catch (Exception e) {
102 e.printStackTrace();
103 }
104 }
105
106 /**
107 * 推断是否是第一次 下载
108 */
109 private boolean isFirst(String urlstr) {
110 return dao.isHasInfors(urlstr);
111 }
112
113 /**
114 * 利用线程開始下载数据
115 */
116 public void download() {
117 if (infos != null) {
118 if (state == DOWNLOADING)
119 return;
120 state = DOWNLOADING;
121 for (DownloadInfo info : infos) {
122 new MyThread(info.getThreadId(), info.getStartPos(),
123 info.getEndPos(), info.getCompeleteSize(),
124 info.getUrl()).start();
125 }
126 }
127 }
128
129 public class MyThread extends Thread {
130 private int threadId;
131 private int startPos;
132 private int endPos;
133 private int compeleteSize;
134 private String urlstr;
135
136 public MyThread(int threadId, int startPos, int endPos,
137 int compeleteSize, String urlstr) {
138 this.threadId = threadId;
139 this.startPos = startPos;
140 this.endPos = endPos;
141 this.compeleteSize = compeleteSize;
142 this.urlstr = urlstr;
143 }
144 @Override
145 public void run() {
146 HttpURLConnection connection = null;
147 RandomAccessFile randomAccessFile = null;
148 InputStream is = null;
149 try {
150 URL url = new URL(urlstr);
151 connection = (HttpURLConnection) url.openConnection();
152 connection.setConnectTimeout(5000);
153 connection.setRequestMethod("GET");
154 // 设置范围,格式为Range:bytes x-y;
155 connection.setRequestProperty("Range", "bytes="+(startPos + compeleteSize) + "-" + endPos);
156
157 randomAccessFile = new RandomAccessFile(localfile, "rwd");
158 randomAccessFile.seek(startPos + compeleteSize);
159 // 将要下载的文件写到保存在保存路径下的文件里
160 is = connection.getInputStream();
161 byte[] buffer = new byte[4096];
162 int length = -1;
163 while ((length = is.read(buffer)) != -1) {
164 randomAccessFile.write(buffer, 0, length);
165 compeleteSize += length;
166 // 更新数据库中的下载信息
167 dao.updataInfos(threadId, compeleteSize, urlstr);
168 // 用消息将下载信息传给进度条,对进度条进行更新
169 Message message = Message.obtain();
170 message.what = 1;
171 message.obj = urlstr;
172 message.arg1 = length;
173 mHandler.sendMessage(message);
174 if (state == PAUSE) {
175 return;
176 }
177 }
178 } catch (Exception e) {
179 e.printStackTrace();
180 } finally {
181 try {
182 is.close();
183 randomAccessFile.close();
184 connection.disconnect();
185 dao.closeDb();
186 } catch (Exception e) {
187 e.printStackTrace();
188 }
189 }
190
191 }
192 }
193 //删除数据库中urlstr相应的下载器信息
194 public void delete(String urlstr) {
195 dao.delete(urlstr);
196 }
197 //设置暂停
198 public void pause() {
199 state = PAUSE;
200 }
201 //重置下载状态
202 public void reset() {
203 state = INIT;
204 }
205 }

在这边下载器类的定义中,我们用到了很多关于进行数据库操作的方法,这里我定义了一个数据库工具类,来提供这些方法。代码例如以下:

Dao:

 1 package cn.yj3g.Dao;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import android.content.Context;
6 import android.database.Cursor;
7 import android.database.sqlite.SQLiteDatabase;
8 import cn.yj3g.DBHelper.DBHelper;
9 import cn.yj3g.entity.DownloadInfo;
10
11 /**
12 *
13 * 一个业务类
14 */
15 public class Dao {
16 private DBHelper dbHelper;
17
18 public Dao(Context context) {
19 dbHelper = new DBHelper(context);
20 }
21
22 /**
23 * 查看数据库中是否有数据
24 */
25 public boolean isHasInfors(String urlstr) {
26 SQLiteDatabase database = dbHelper.getReadableDatabase();
27 String sql = "select count(*) from download_info where url=? ";
28 Cursor cursor = database.rawQuery(sql, new String[] { urlstr });
29 cursor.moveToFirst();
30 int count = cursor.getInt(0);
31 cursor.close();
32 return count == 0;
33 }
34
35 /**
36 * 保存 下载的详细信息
37 */
38 public void saveInfos(List<DownloadInfo> infos) {
39 SQLiteDatabase database = dbHelper.getWritableDatabase();
40 for (DownloadInfo info : infos) {
41 String sql = "insert into download_info(thread_id,start_pos, end_pos,compelete_size,url) values (?,? ,?,?,?)";
42 Object[] bindArgs = { info.getThreadId(), info.getStartPos(),
43 info.getEndPos(), info.getCompeleteSize(), info.getUrl() };
44 database.execSQL(sql, bindArgs);
45 }
46 }
47
48 /**
49 * 得到下载详细信息
50 */
51 public List<DownloadInfo> getInfos(String urlstr) {
52 List<DownloadInfo> list = new ArrayList<DownloadInfo>();
53 SQLiteDatabase database = dbHelper.getReadableDatabase();
54 String sql = "select thread_id, start_pos, end_pos,compelete_size,url from download_info where url=?";
55 Cursor cursor = database.rawQuery(sql, new String[] { urlstr });
56 while (cursor.moveToNext()) {
57 DownloadInfo info = new DownloadInfo(cursor.getInt(0),
58 cursor.getInt(1), cursor.getInt(2), cursor.getInt(3),
59 cursor.getString(4));
60 list.add(info);
61 }
62 cursor.close();
63 return list;
64 }
65
66 /**
67 * 更新数据库中的下载信息
68 */
69 public void updataInfos(int threadId, int compeleteSize, String urlstr) {
70 SQLiteDatabase database = dbHelper.getReadableDatabase();
71 String sql = "update download_info set compelete_size=? where thread_id=? and url=? ";
72 Object[] bindArgs = { compeleteSize, threadId, urlstr };
73 database.execSQL(sql, bindArgs);
74 }
75 /**
76 * 关闭数据库
77 */
78 public void closeDb() {
79 dbHelper.close();
80 }
81
82 /**
83 * 下载完毕后删除数据库中的数据
84 */
85 public void delete(String url) {
86 SQLiteDatabase database = dbHelper.getReadableDatabase();
87 database.delete("download_info", "url=?", new String[] { url });
88 database.close();
89 }
90 }

下来就是要进行下载和暂停button的响应事件了。

详细代码和解释例如以下。

MainActivity:

  1 package cn.yj3g.AndroidDownload;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7 import android.app.ListActivity;
8 import android.os.Bundle;
9 import android.os.Handler;
10 import android.os.Message;
11 import android.view.View;
12 import android.widget.LinearLayout;
13 import android.widget.LinearLayout.LayoutParams;
14 import android.widget.ProgressBar;
15 import android.widget.SimpleAdapter;
16 import android.widget.TextView;
17 import android.widget.Toast;
18 import cn.yj3g.entity.LoadInfo;
19 import cn.yj3g.service.Downloader;
20
21 public class MainActivity extends ListActivity {
22 // 固定下载的资源路径,这里能够设置网络上的地址
23 private static final String URL = "http://192.168.1.105:8080/struts2_net/";
24 // 固定存放下载的音乐的路径:SD卡文件夹下
25 private static final String SD_PATH = "/mnt/sdcard/";
26 // 存放各个下载器
27 private Map<String, Downloader> downloaders = new HashMap<String, Downloader>();
28 // 存放与下载器相应的进度条
29 private Map<String, ProgressBar> ProgressBars = new HashMap<String, ProgressBar>();
30 /**
31 * 利用消息处理机制适时更新进度条
32 */
33 private Handler mHandler = new Handler() {
34 public void handleMessage(Message msg) {
35 if (msg.what == 1) {
36 String url = (String) msg.obj;
37 int length = msg.arg1;
38 ProgressBar bar = ProgressBars.get(url);
39 if (bar != null) {
40 // 设置进度条按读取的length长度更新
41 bar.incrementProgressBy(length);
42 if (bar.getProgress() == bar.getMax()) {
43 Toast.makeText(MainActivity.this, "下载完毕。", 0).show();
44 // 下载完毕后清除进度条并将map中的数据清空
45 LinearLayout layout = (LinearLayout) bar.getParent();
46 layout.removeView(bar);
47 ProgressBars.remove(url);
48 downloaders.get(url).delete(url);
49 downloaders.get(url).reset();
50 downloaders.remove(url);
51
52 }
53 }
54 }
55 }
56 };
57 @Override
58 public void onCreate(Bundle savedInstanceState) {
59 super.onCreate(savedInstanceState);
60 setContentView(R.layout.main);
61 showListView();
62 }
63 // 显示listView,这里能够随便加入音乐
64 private void showListView() {
65 List<Map<String, String>> data = new ArrayList<Map<String, String>>();
66 Map<String, String> map = new HashMap<String, String>();
67 map.put("name", "mm.mp3");
68 data.add(map);
69 map = new HashMap<String, String>();
70 map.put("name", "pp.mp3");
71 data.add(map);
72 map = new HashMap<String, String>();
73 map.put("name", "tt.mp3");
74 data.add(map);
75 map = new HashMap<String, String>();
76 map.put("name", "You.mp3");
77 data.add(map);
78 SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.list_item, new String[] { "name" },
79 new int[] { R.id.tv_resouce_name });
80 setListAdapter(adapter);
81 }
82 /**
83 * 响应開始下载button的点击事件
84 */
85 public void startDownload(View v) {
86 // 得到textView的内容
87 LinearLayout layout = (LinearLayout) v.getParent();
88 String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();
89 String urlstr = URL + musicName;
90 String localfile = SD_PATH + musicName;
91 //设置下载线程数为4。这里是我为了方便随便固定的
92 int threadcount = 4;
93 // 初始化一个downloader下载器
94 Downloader downloader = downloaders.get(urlstr);
95 if (downloader == null) {
96 downloader = new Downloader(urlstr, localfile, threadcount, this, mHandler);
97 downloaders.put(urlstr, downloader);
98 }
99 if (downloader.isdownloading())
100 return;
101 // 得到下载信息类的个数组成集合
102 LoadInfo loadInfo = downloader.getDownloaderInfors();
103 // 显示运行进度条
104 showProgress(loadInfo, urlstr, v);
105 // 调用方法開始下载
106 downloader.download();
107 }
108
109 /**
110 * 显示运行进度条
111 */
112 private void showProgress(LoadInfo loadInfo, String url, View v) {
113 ProgressBar bar = ProgressBars.get(url);
114 if (bar == null) {
115 bar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
116 bar.setMax(loadInfo.getFileSize());
117 bar.setProgress(loadInfo.getComplete());
118 ProgressBars.put(url, bar);
119 LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, 5);
120 ((LinearLayout) ((LinearLayout) v.getParent()).getParent()).addView(bar, params);
121 }
122 }
123 /**
124 * 响应暂停下载button的点击事件
125 */
126 public void pauseDownload(View v) {
127 LinearLayout layout = (LinearLayout) v.getParent();
128 String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();
129 String urlstr = URL + musicName;
130 downloaders.get(urlstr).pause();
131 }
132 }

最后我们要在清单文件里加入权限。一个是訪问网络的权限,一个是往SD卡写数据的权限。

代码例如以下:

 <uses-permission android:name="android.permission.INTERNET"/>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

这样我们就实现了文件的断点续传下载功能。详细效果图例如以下:

Android该HTTP下载的更多相关文章

  1. Android Studio的下载和安装教程(从ADT到AS)

    之前一直使用的是Android development tools(简称ADT),后来说是google对ADT不再提供支持,然后一直在考虑是否把自己电脑换成Android Studio(简称AS),从 ...

  2. Android利用Http下载文件

    Android利用Http下载文件 一.场景 下载存文本文件和下载如mp3等大容量的文件 界面 二.代码编写 1.AndroidMainfest.xml中配置 主要是解决网络权限和写SDCard的权限 ...

  3. 驾照理论模拟考试系统Android源码下载

    ‍‍‍驾照理论模拟考试系统Android源码下载 <ignore_js_op> 9.png (55.77 KB, 下载次数: 0) <ignore_js_op> 10.png ...

  4. 【Android 应用开发】Android 开发环境下载地址 -- 百度网盘 adt-bundle android-studio sdk adt 下载

    19af543b068bdb7f27787c2bc69aba7f Additional Download (32-, 64-bit) Package r10 STL debug info androi ...

  5. Android版多线程下载器核心代码分享

    首先给大家分享多线程下载核心类: package com.example.urltest; import java.io.IOException; import java.io.InputStream ...

  6. Android中多线程下载列表的封装实现(含进度反馈)

    来源:http://blog.csdn.net/u011638883/article/details/17347015 实现了一下Android中的文件多线程下载模块,支持自定义线程数.断点续传.下载 ...

  7. android网络图片的下载

    android网络图片的下载 /** * Get image from newwork * * @param path * The path of image * @return byte[] * @ ...

  8. Android源码下载方法详解

    转自:http://www.cnblogs.com/anakin/archive/2011/12/20/2295276.html Android源码下载方法详解 相信很多下载过内核的人都对这个很熟悉 ...

  9. android 多线程断点续传下载

    今天跟大家一起分享下Android开发中比较难的一个环节,可能很多人看到这个标题就会感觉头很大,的确如果没有良好的编码能力和逻辑思维,这块是很难搞明白的,前面2次总结中已经为大家分享过有关技术的一些基 ...

  10. Android之断点续传下载

    今天学习了Android开发中比较难的一个环节,就是断点续传下载,很多人看到这个标题就感觉头大,的确,如果没有良好的逻辑思维,这块的确很难搞明白.下面我就将自己学到的知识和一些见解写下供那些在这个环节 ...

随机推荐

  1. Delphi图像处理 -- 最小值

    阅读提示:     <Delphi图像处理>系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM.     <C++图像处理>系列以代码清晰,可读性为主,全部使用C ...

  2. javascript实现图片无缝滚动(scrollLeft的使用方法介绍)

    <!DOCTYPE html > <html> <head> <meta http-equiv="Content-Type" conten ...

  3. 配置虚拟主机并更改Apache默认解析路径

    配置虚拟主机,非常easy 改动以下文件: 加入以下几句话 <VirtualHost *:80> ##ServerAdmin webmaster@dummy-host2.example.c ...

  4. MyBATIS使用CRUD

    MyEclipse不提供自己主动生成,这里提供mybatis文件包和开发文档 http://download.csdn.net/detail/u010026901/7489319 自己建立配置文件, ...

  5. linux 怎么使用一个c/c++库

    linux 怎么使用一个c/c++库 使用一个库,库有动态和静态之分. 静态库只要能够编译通过,运行时就没有提示缺少这个库可能,因为把这个库就是这个使用者的一部分了.动态库.两部分.1 库信息的注册 ...

  6. 通过加载Kernel32来动态判断 当前操作系统32bit还是64bit

    工作原理:通过加载Kernel32来获取IsWow64Process 函数然后通过函数的地址操作,执行函数的操作. 在程序中只要我们获取了一个函数的地址,就可以找到正确的方法执行这个函数. 但是这种方 ...

  7. Spark中的Scheduler

    Spark中的Scheduler scheduler分成两个类型.一个是TaskScheduler与事实上现,一个是DAGScheduler. TaskScheduler:主要负责各stage中传入的 ...

  8. 【总结】在VirtualBox上面安装Mac的注意事项

    看此文之前 http://www.crifan.com/category/work_and_job/virtual_machine/virtualbox-virtual_machine/ 此文仅仅是针 ...

  9. Matlab实现Hough变换检測图像中的直线

    Hough变换的原理: 将图像从图像空间变换至參数空间.变换公式例如以下: 变换以后,图像空间与參数空间存在下面关系: 图像空间中的一点在參数空间是一条曲线,而图像空间共线的各点相应于參数空间交于一点 ...

  10. 飘逸的python - yield简明教程

    发现还有非常多人对yield不理解,云里雾里,于是试着用文字表述. 仅仅要函数含有yield语句,它就返回一个生成器.所以我们与其把其看成函数定义,不如看作是生成器定义.函数用return返回,而生成 ...