通过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 对象 还有一个 BufferedReader对象
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)
throws IOException
将 b.length 个字节从指定 byte 数组写入此文件输出流中。
覆盖:
类 OutputStream 中的 write
参数:
b- 数据。
抛出:
IOException- 如果发生 I/O 错误。
另请参见:
OutputStream.write(byte[], int, int)
下面介绍在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);
}
};
}