Android 從網路上下載檔案以及寫入到SDcard裡面
通過FilegetOutputStream(file) 獲取OutputStream 物件
通過HttpURlConnection.getInputStream() 獲取InputStream物件
本節課講述如何使用Android應用程式在網路上下載檔案。
比如說一個背單詞的應用,詞庫更新,還有音樂播放器之類的都需要這個功能。
1.如何使用HTTP協議下載檔案
2.將下載的檔案寫入SDCARD
FTP HTTP 等很多協議都可以實現下載檔案,我們當然也是可以將下載檔案放入主儲存檔案,但是由於儲存空間限制,我們一般放置帶SD卡里。
檔案下載步驟
1.建立一個HttpURLConnection
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
2.獲得一個輸入流InputStream物件
java中牽涉到檔案操作一定逃不開輸入流輸出流,輸入流是向程式讀入檔案,輸出流是向目標寫出檔案。
3.訪問網路的許可權
android.permission.INTERNET
這個需要在manifest當中進行修改
本次課的程式一共有三個類
Download.java
HttpDownloader.java
FileUtils.java
DownLoad.java 是主程式
HttpDownloader.java 是封裝好的下載工具類
FileUtils.java 是為了將資料寫入到SD卡當中所用到的輔助工具類 可以收藏
在HttpDownloader這個類當中有三個方法
有兩個download函式 但是引數 返回值都不同 是過載關係
public String download(String urlStr)
·這個函式的引數是一個可下載文字檔案的連結 返回一個String型別,就是連結所代表的資料。當然這個函式當中牽涉到了很多java的IO流操作知識。
首先宣告一個StringBuffer物件 (StringBuffer 與String 其實是差不多的 不過 有區別)
還有一個String 物件 還有一個
StringBuffer sb = new StringBuffer();
String line = null;
BufferedReader buffer = null; //為了使用它的readLine()方法
/**
* 根據URL下載檔案,前提是這個檔案當中的內容是文字,函式的返回值就是檔案當中的內容
* 1.建立一個URL物件
* 2.通過URL物件,建立一個HttpURLConnection物件
* 3.得到InputStram
* 4.從InputStream當中讀取資料
* @param urlStr
* @return
*/
首先我們要獲取一個URL物件(用於建立下載檔案所需的HttpURLConnection物件)
private URL url = null;
url = new URL(urlStr);
這樣我們就得到了一個代表輸入引數urlStr地址的URL物件
下一步
// 建立一個Http連線
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
我們呼叫URL的openConnection()方法(並且通過向下轉型)來獲取一個HttpURLConnection物件
這個物件就代表了Http的連線
下面進行IO劉操作
// 使用IO流讀取資料
buffer = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
//urlConn.getInputStream() 代表的就是這個地址的檔案
while ((line = buffer.readLine()) != null) {
sb.append(line);
}
使用HttpURLConnection物件的getInputStream() 方法來獲取InputStream物件(代表著目標檔案與應用程式的連線通道,資料通過管道進入手機)
由於直接操作InputStream 不是很方便 所以要在外面套上一層InputStreamReader 再套上 BufferedReader
原因是由於InputStream 是一個位元組流,也就說讀入的資料都是一個個位元組,所以通過InputStreamReader 我們就可以把位元組流轉換為字元流,但是一個個處理字元還是不方便,於是又套上了BufferedReader,他有一個readLine可以一次性讀取一行資料,很方便,讀完之後返回null。
所以通過StringBuffer 的append就可以新增資料回來
這樣就完成了 (前提是文字檔案)
總結一下,我們
第一步要做的事情是構造一個URL物件,利用URL的建構函式,將我們要下載檔案的地址放在建構函式當中,形成了一個我們要下載檔案物件的URL物件。
第二步我們利用這個URL物件建立一個HttpURlConnection物件,這個物件代表著我們的應用程式與目標檔案之間的連線,這是構造了一個http連線(呼叫URL的openConnection方法,然後通過向下轉型就可以了)。
第三步利用HttpURlConnection物件的getInputStream方法 獲得InputStream物件
由於Android把各種類封裝的很好,這樣就很容易實現了,但是現在這個方法只是將文字讀取出來,並沒有寫入到SD卡里面。
/**
* 根據URL下載檔案,前提是這個檔案當中的內容是文字,函式的返回值就是檔案當中的內容
* 1.建立一個URL物件
* 2.通過URL物件,建立一個HttpURLConnection物件
* 3.得到InputStram
* 4.從InputStream當中讀取資料
* @param urlStr
* @return
*/
public String download(String urlStr) {
StringBuffer sb = new StringBuffer();
String line = null;
BufferedReader buffer = null;
private URL url = null;
try {
// 建立一個URL物件,代表這個地址
url = new URL(urlStr);
// 建立一個Http連線
HttpURLConnection urlConn = (HttpURLConnection) url
.openConnection();
// 使用IO流讀取資料
buffer = new BufferedReader(new InputStreamReader(urlConn
.getInputStream()));//urlConn.getInputStream() 代表的就是這個地址的檔案
while ((line = buffer.readLine()) != null) {
sb.append(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
buffer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return sb.toString();
}
下面講述如何將一個MP3檔案寫入到我們的SDcard裡面
訪問SDCARD的話,我們首先要獲得SDCARD在我們手機裡面的地址名,由於每個手機的地址明可能是不同的額,於是我們不能把這個地址寫死,android作業系統當中的Environment類的getExternalStorageDirectory() 方法可以提供這個SDCARD的地址。
一般是/sdcard的形式
訪問SD卡的許可權:
android.permission.WRITE_EXTERNAL_STORAGE
在AndroidManifest.xml 當中進行宣告才行。
需要使用到一個訪問SDCARD的一個工具類 FileUtils.java 這個類封裝的很好,可以利用。
下面是獲取手機SDCARD地址的程式碼
private String SDPATH;
public String getSDPATH() {
return SDPATH;
}
public FileUtils() {
//得到當前外部儲存裝置的目錄
// /SDCARD
SDPATH = Environment.getExternalStorageDirectory() + "/";
//方便增加地址空間
}
在SDCARD上面建立目錄
/**
/**
* 在SD卡上建立目錄
*
* @param dirName
*/
public File creatSDDir(String dirName) {
File dir = new File(SDPATH + dirName);
dir.mkdirs();
return dir;
}
File(String fielAddress) 構造方法建立File物件,
mkdirs() 方法執行建立命令
Creates the directory named by this file,
/**
* 在SD卡上建立檔案
*
* @throws IOException
*/
public File creatSDFile(String fileName) throws IOException {
File file = new File(SDPATH + fileName);
file.createNewFile();
return file;
}
都是java的IO操作
public boolean isFileExist(String fileName){
File file = new File(SDPATH + fileName);
return file.exists();
}
判斷是否存在此檔案
三個引數 路徑名 檔名 輸入流input
public File write2SDFromInput(String path,String fileName,InputStream input){
File file = null;
OutputStream output = null;
try{
//建立目錄
creatSDDir(path);
//建立檔案
file = creatSDFile(path + fileName);
//建立檔案輸出流
output = new FileOutputStream(file);
byte buffer [] = new byte[4 * 1024];
while((input.read(buffer)) != -1){
output.write(buffer);
}
output.flush();
}
catch(Exception e){
e.printStackTrace();
}
finally{
try{
output.close();
}
catch(Exception e){
e.printStackTrace();
}
}
return file;
}
}
FileOutputStream(File file)
建立一個向指定 File 物件表示的檔案中寫入資料的檔案輸出流。
write
public void write(byte[] b)
將 b.length 個位元組從指定 byte 陣列寫入此檔案輸出流中。
覆蓋:
引數:
b- 資料。
丟擲:
另請參見:
下面介紹在HttpDownloader 中的的二個方法
這個函式可以下載任意形式的檔案 並且存放在SDCARD的指定目錄當中
/**
* 該函式返回整形 -1:代表下載檔案出錯 0:代表下載檔案成功 1:代表檔案已經存在
*/
urlStr 下載檔案的連結 path 存放SDCARD的目錄 fileName 以什麼檔名儲存該檔案
public int downFile(String urlStr, String path, String fileName) {
InputStream inputStream = null;
try {
//生成FileUtils輔助類物件
FileUtils fileUtils = new FileUtils();
if (fileUtils.isFileExist(path + fileName)) {
return 1;
} else {
inputStream = getInputStreamFromUrl(urlStr);
File resultFile = fileUtils.write2SDFromInput(path,fileName, inputStream);
if (resultFile == null) {
return -1;
}
}
} catch (Exception e) {
e.printStackTrace();
return -1;
} finally {
try {
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return 0;
}
用到了封裝函式
/**
* 根據URL得到輸入流
*
* @param urlStr
* @return
* @throws MalformedURLException
* @throws IOException
*/
public InputStream getInputStreamFromUrl(String urlStr)
throws MalformedURLException, IOException {
url = new URL(urlStr);
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConn.getInputStream();
return inputStream;
}
StringBuffer sb = new StringBuffer();
String line = null;
BufferedReader buffer = null;
try {
// 建立一個URL物件,代表這個地址
url = new URL(urlStr);
// 建立一個Http連線
HttpURLConnection urlConn = (HttpURLConnection) url
.openConnection();
// 使用IO流讀取資料
buffer = new BufferedReader(new InputStreamReader(urlConn
.getInputStream()));//urlConn.getInputStream() 代表的就是這個地址的檔案
其實跟這一段程式碼功能相同 只是
File resultFile = fileUtils.write2SDFromInput(path,fileName, inputStream);
if (resultFile == null) {
return -1;
}
Download.java
package com.example.download;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Download extends Activity {
/** Called when the activity is first created. */
private Button downloadTxtButton;
private Button downloadMp3Button;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
downloadTxtButton = (Button)findViewById(R.id.downloadTxt);
downloadTxtButton.setOnClickListener(new DownloadTxtListener());
downloadMp3Button = (Button)findViewById(R.id.downloadMp3);
downloadMp3Button.setOnClickListener(new DownloadMp3Listener());
}
class DownloadTxtListener implements OnClickListener{
@Override
public void onClick(View v) {
HttpDownloader httpDownloader = new HttpDownloader();
String lrc = httpDownloader.download("http://192.168.137.1:8080/mywebsite/guoximing.txt");
System.out.println(lrc);
}
}
class DownloadMp3Listener implements OnClickListener{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
HttpDownloader httpDownloader = new HttpDownloader();
int result = httpDownloader.downFile("http://192.168.137.1:8080/mywebsite/guoxiaoming.txt", "guoximing/", "guoxiaoming.txt");
System.out.println(result);
}
}
}
HttpDownloader.java
package com.example.download;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class HttpDownloader {
private URL url = null;
/**
* 根據URL下載檔案,前提是這個檔案當中的內容是文字,函式的返回值就是檔案當中的內容
* 1.建立一個URL物件
* 2.通過URL物件,建立一個HttpURLConnection物件
* 3.得到InputStram
* 4.從InputStream當中讀取資料
* @param urlStr
* @return
*/
public String download(String urlStr) {
StringBuffer sb = new StringBuffer();
String line = null;
BufferedReader buffer = null;
try {
// 建立一個URL物件,代表這個地址
url = new URL(urlStr);
// 建立一個Http連線
HttpURLConnection urlConn = (HttpURLConnection) url
.openConnection();
// 使用IO流讀取資料
buffer = new BufferedReader(new InputStreamReader(urlConn
.getInputStream()));//urlConn.getInputStream() 代表的就是這個地址的檔案
while ((line = buffer.readLine()) != null) {
sb.append(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
buffer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return sb.toString();
}
/**
* 該函式返回整形 -1:代表下載檔案出錯 0:代表下載檔案成功 1:代表檔案已經存在
*/
public int downFile(String urlStr, String path, String fileName) {
InputStream inputStream = null;
try {
FileUtils fileUtils = new FileUtils();
if (fileUtils.isFileExist(path + fileName)) {
return 1;
} else {
inputStream = getInputStreamFromUrl(urlStr);
File resultFile = fileUtils.write2SDFromInput(path,fileName, inputStream);
if (resultFile == null) {
return -1;
}
}
} catch (Exception e) {
e.printStackTrace();
return -1;
} finally {
try {
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return 0;
}
/**
* 根據URL得到輸入流
*
* @param urlStr
* @return
* @throws MalformedURLException
* @throws IOException
*/
public InputStream getInputStreamFromUrl(String urlStr)
throws MalformedURLException, IOException {
url = new URL(urlStr);
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConn.getInputStream();
return inputStream;
}
}
FileUtils.java
package com.example.download;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.os.Environment;
public class FileUtils {
private String SDPATH;
public String getSDPATH() {
return SDPATH;
}
public FileUtils() {
//得到當前外部儲存裝置的目錄
// /SDCARD
SDPATH = Environment.getExternalStorageDirectory() + "/";
}
/**
* 在SD卡上建立檔案
*
* @throws IOException
*/
public File creatSDFile(String fileName) throws IOException {
File file = new File(SDPATH + fileName);
file.createNewFile();
return file;
}
/**
* 在SD卡上建立目錄
*
* @param dirName
*/
public File creatSDDir(String dirName) {
File dir = new File(SDPATH + dirName);
dir.mkdirs();
return dir;
}
/**
* 判斷SD卡上的資料夾是否存在
*/
public boolean isFileExist(String fileName){
File file = new File(SDPATH + fileName);
return file.exists();
}
/**
* 將一個InputStream裡面的資料寫入到SD卡中
*/
public File write2SDFromInput(String path,String fileName,InputStream input){
File file = null;
OutputStream output = null;
try{
//建立目錄
creatSDDir(path);
//建立檔案
file = creatSDFile(path + fileName);
//建立
output = new FileOutputStream(file);
byte buffer [] = new byte[4 * 1024];
while((input.read(buffer)) != -1){
output.write(buffer);
}
output.flush();
}
catch(Exception e){
e.printStackTrace();
}
finally{
try{
output.close();
}
catch(Exception e){
e.printStackTrace();
}
}
return file;
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/downloadTxt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="下載文字檔案"
></Button>
<Button
android:id="@+id/downloadMp3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="下載MP3檔案 "
></Button>
</LinearLayout>
以上程式是在Android2.3環境下開發的,在高版本的情況下不能再UI執行緒當中訪問網路
這樣就可以了
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class Download extends Activity {
private Button downloadTxtButton;
private Button downloadMp3Button;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
downloadTxtButton = (Button)findViewById(R.id.downloadTxt);
downloadMp3Button = (Button)findViewById(R.id.downloadMp3);
downloadTxtButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
new Thread(downloadRun).start();
}
});
downloadMp3Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
new Thread(downloadMp3).start();
}
});
}
Runnable downloadRun = new Runnable(){
@Override
public void run() {
HttpDownloader httpDownloader = new HttpDownloader();
String lrc = httpDownloader.download("http://121.49.87.4:8080/android/11.txt");
System.out.println(lrc);
}
};
Runnable downloadMp3 = new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
HttpDownloader httpDownloader = new HttpDownloader();
int result = httpDownloader.downFile("http://121.49.87.4:8080/android/11.txt","guoximing/", "guoxiaoming.txt");
System.out.println(result);
}
};
}