Skip to content

Commit 185baa7

Browse files
authored
Merge pull request onlyliuxin#32 from conf1102/master
Homework 3rd
2 parents 3139bf5 + 2389735 commit 185baa7

10 files changed

+325
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.coderising.download;
2+
3+
import java.io.File;
4+
import java.io.IOException;
5+
import java.io.RandomAccessFile;
6+
import java.util.concurrent.CountDownLatch;
7+
8+
import com.coderising.download.api.Connection;
9+
10+
public class DownloadThread extends Thread{
11+
12+
Connection conn;
13+
int startPos;
14+
int endPos;
15+
CountDownLatch latch;
16+
17+
File file = new File("C://download.mp3");
18+
19+
public DownloadThread( Connection conn, int startPos, int endPos, CountDownLatch latch){
20+
this.conn = conn;
21+
this.startPos = startPos;
22+
this.endPos = endPos;
23+
this.latch = latch;
24+
}
25+
public void run(){
26+
RandomAccessFile raf = null;
27+
try {
28+
byte[] byteRead = conn.read(startPos, endPos);
29+
raf = new RandomAccessFile(file, "rw");;
30+
raf.seek(startPos);
31+
raf.write(byteRead);
32+
33+
} catch (IOException e) {
34+
e.printStackTrace();
35+
}finally{
36+
latch.countDown();
37+
try {
38+
raf.close();
39+
} catch (IOException e) {
40+
e.printStackTrace();
41+
}
42+
conn.close();
43+
}
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.coderising.download;
2+
3+
import java.io.IOException;
4+
import java.util.concurrent.CountDownLatch;
5+
import java.util.concurrent.CyclicBarrier;
6+
7+
import com.coderising.download.api.Connection;
8+
import com.coderising.download.api.ConnectionException;
9+
import com.coderising.download.api.ConnectionManager;
10+
import com.coderising.download.api.DownloadListener;
11+
import com.coderising.download.impl.ConnectionManagerImpl;
12+
import com.coderising.download.utils.FileDownloadUtil;
13+
14+
public class FileDownloader {
15+
16+
String url = "http://localhost:8080/MyServer/test.exe";
17+
18+
DownloadListener listener;
19+
20+
ConnectionManager cm;
21+
22+
public FileDownloader(String _url) {
23+
this.url = _url;
24+
cm = new ConnectionManagerImpl();
25+
}
26+
27+
public void execute() throws IOException {
28+
// 在这里实现你的代码, 注意: 需要用多线程实现下载
29+
// 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码
30+
// (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos,
31+
// endPos来指定)
32+
// (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有
33+
// 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。
34+
// 具体的实现思路:
35+
// 1. 需要调用ConnectionManager的open方法打开连接,
36+
// 然后通过Connection.getContentLength方法获得文件的长度
37+
// 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法
38+
// 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组
39+
// 3. 把byte数组写入到文件中
40+
// 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法
41+
42+
// 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。
43+
Connection conn = null;
44+
try {
45+
conn = cm.open(url);
46+
int length = conn.getContentLength();
47+
int[] posArr = FileDownloadUtil.generateDownloadPosArr(length);
48+
CountDownLatch latch = new CountDownLatch(3);
49+
for (int i = 0; i < posArr.length; i++) {
50+
if (i == posArr.length - 1) {
51+
new DownloadThread(cm.open(url), posArr[i], length, latch).start();
52+
} else {
53+
new DownloadThread(cm.open(url), posArr[i], posArr[i + 1] - 1, latch).start();
54+
}
55+
}
56+
latch.await();
57+
System.out.println("Download Finished");
58+
} catch (ConnectionException e) {
59+
e.printStackTrace();
60+
} catch (InterruptedException e) {
61+
e.printStackTrace();
62+
} finally {
63+
if (conn != null) {
64+
conn.close();
65+
}
66+
}
67+
}
68+
69+
public void setListener(DownloadListener listener) {
70+
this.listener = listener;
71+
}
72+
73+
public void setConnectionManager(ConnectionManager ucm) {
74+
this.cm = ucm;
75+
}
76+
77+
public DownloadListener getListener() {
78+
return this.listener;
79+
}
80+
81+
public static void main(String[] args) throws IOException {
82+
new FileDownloader("http://localhost:8080/MyServer/Test.mp3").execute();
83+
}
84+
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.coderising.download;
2+
3+
import java.io.IOException;
4+
5+
import org.junit.After;
6+
import org.junit.Before;
7+
import org.junit.Test;
8+
9+
import com.coderising.download.api.ConnectionManager;
10+
import com.coderising.download.api.DownloadListener;
11+
import com.coderising.download.impl.ConnectionManagerImpl;
12+
13+
public class FileDownloaderTest {
14+
boolean downloadFinished = false;
15+
@Before
16+
public void setUp() throws Exception {
17+
}
18+
19+
@After
20+
public void tearDown() throws Exception {
21+
}
22+
23+
@Test
24+
public void testDownload() throws IOException {
25+
26+
String url = "http://localhost:8080/MyServer/Test.mp3";
27+
28+
FileDownloader downloader = new FileDownloader(url);
29+
30+
31+
ConnectionManager cm = new ConnectionManagerImpl();
32+
downloader.setConnectionManager(cm);
33+
34+
downloader.setListener(new DownloadListener() {
35+
@Override
36+
public void notifyFinished() {
37+
downloadFinished = true;
38+
}
39+
40+
});
41+
42+
downloader.execute();
43+
44+
// 等待多线程下载程序执行完毕
45+
while (!downloadFinished) {
46+
try {
47+
System.out.println("还没有下载完成,休眠五秒");
48+
//休眠5秒
49+
Thread.sleep(5000);
50+
} catch (InterruptedException e) {
51+
e.printStackTrace();
52+
}
53+
}
54+
System.out.println("下载完成!");
55+
56+
57+
58+
}
59+
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.coderising.download.api;
2+
3+
import java.io.IOException;
4+
5+
public interface Connection {
6+
/**
7+
* 给定开始和结束位置, 读取数据, 返回值是字节数组
8+
* @param startPos 开始位置, 从0开始
9+
* @param endPos 结束位置
10+
* @return
11+
*/
12+
public byte[] read(int startPos,int endPos) throws IOException;
13+
/**
14+
* 得到数据内容的长度
15+
* @return
16+
*/
17+
public int getContentLength();
18+
19+
/**
20+
* 关闭连接
21+
*/
22+
public void close();
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.coderising.download.api;
2+
3+
public class ConnectionException extends Exception {
4+
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.coderising.download.api;
2+
3+
public interface ConnectionManager {
4+
public Connection open(String url) throws ConnectionException;
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.coderising.download.api;
2+
3+
public interface DownloadListener {
4+
public void notifyFinished();
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.coderising.download.impl;
2+
3+
import java.io.ByteArrayOutputStream;
4+
import java.io.File;
5+
import java.io.IOException;
6+
import java.io.InputStream;
7+
import java.io.RandomAccessFile;
8+
import java.net.HttpURLConnection;
9+
import java.net.URL;
10+
11+
import com.coderising.download.api.Connection;
12+
13+
public class ConnectionImpl implements Connection {
14+
15+
private HttpURLConnection httpConn;
16+
17+
public ConnectionImpl(String urlStr) {
18+
URL url;
19+
try {
20+
url = new URL(urlStr);
21+
httpConn = (HttpURLConnection) url.openConnection();
22+
} catch (IOException e) {
23+
e.printStackTrace();
24+
}
25+
}
26+
27+
@Override
28+
public byte[] read(int startPos, int endPos) throws IOException {
29+
System.out.println("Start Reading");
30+
System.out.println("StartPos: " + startPos);
31+
System.out.println("EndPos: " + endPos);
32+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
33+
InputStream is = httpConn.getInputStream();
34+
is.skip(startPos);
35+
36+
int downloadLengh = endPos - startPos;
37+
38+
byte[] b = new byte[1024];
39+
int total = 0;
40+
int len = -1;
41+
while ((len = is.read(b)) != -1) {
42+
baos.write(b, 0, len);
43+
total = total + len;
44+
if (total == downloadLengh) {
45+
break;
46+
}
47+
}
48+
is.close();
49+
baos.close();
50+
System.out.println("End Reading");
51+
return baos.toByteArray();
52+
}
53+
54+
@Override
55+
public int getContentLength() {
56+
return httpConn.getContentLength();
57+
}
58+
59+
@Override
60+
public void close() {
61+
httpConn.disconnect();
62+
}
63+
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.coderising.download.impl;
2+
3+
import com.coderising.download.api.Connection;
4+
import com.coderising.download.api.ConnectionException;
5+
import com.coderising.download.api.ConnectionManager;
6+
7+
public class ConnectionManagerImpl implements ConnectionManager {
8+
@Override
9+
public Connection open(String urlStr) throws ConnectionException {
10+
Connection conn = new ConnectionImpl(urlStr);
11+
return conn;
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.coderising.download.utils;
2+
3+
public class FileDownloadUtil {
4+
5+
public static int[] generateDownloadPosArr(int length){
6+
int[] posArr = new int[3];
7+
int firstPos = length/3;
8+
int secondPos = length/3 * 2;
9+
10+
posArr[0] = 0;
11+
posArr[1] = firstPos;
12+
posArr[2] = secondPos;
13+
14+
return posArr;
15+
}
16+
public static void main(String[] args) {
17+
FileDownloadUtil.generateDownloadPosArr(1000);
18+
}
19+
20+
}

0 commit comments

Comments
 (0)