流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。
一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是Internet上的某个URL。
流的方向是重要的,根据流的方向,流可分为两类:输入流和输出流。用户可以从输入流中读取信息,但不能写它。相反,对输出流,只能往输入流写,而不能读它。
实际上,流的源端和目的端可简单地看成是字节的生产者和消费者,对输入流,可不必关心它的源端是什么,只要简单地从流中读数据,而对输出流,也可不知道它的目的端,只是简单地往流中写数据。
1.java.io包中的类对应两类流,一类流直接从指定的位置(如磁盘文件或内存区域)读或写,这类流称为结点流(node stream),其它的流则称为过滤器(filters)。过滤器输入流往往是以其它输入流作为它的输入源,经过过滤或处理后再以新的输入流的形式提供给用户,过滤器输出流的原理也类似。
2.java.io包中的stream类根据它们操作对象的类型是字符还是字节可分为两大类: 字符流和字节流。
抽象类:InputStream,OutputStream,Reader,Writer。
其子类分别是:
InputStream
AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream
OutputStream
ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, PipedOutputStream
Reader
BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader
Writer
BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter
其中常用的有:FileInputStream,FileOutputStream,BufferedReader,InputStreamReader,BufferedWriter,OutputStreamWriter
不同之处:BufferedWriter与BufferedReader可以对String进行操作。
DataInputStream和DataOutputStream
这两个类创建的对象分别被称为数据输入流和数据输出流。这是很有用的两个流,它们允许程序按与机器无关的风格读写Java数据。所以比较适合于网络上的数据传输。这两个流也是过滤器流,常以其它流如InputStream或OutputStream作为它们的输入或输出。
BufferedReader和BufferedWriter
这两个类对应的流使用了缓冲,能大大提高输入输出的效率。这两个也是过滤器流,常用来对InputStreamReader和OutputStreamWriter进行处理。
要对Android设备的外部存储设备进行读写操作,需要添加权限:
Environment获取Android设备中的外部存储设备的状态,有一下几种状态:
MEDIA_BAD_REMOVAL 在没有挂载前存储媒体已经被移除。
MEDIA_CHECKING 正在检查存储媒体。
MEDIA_MOUNTED 存储媒体已经挂载,并且挂载点可读/写。
MEDIA_MOUNTED_READ_ONLY 存储媒体已经挂载,挂载点只读。
MEDIA_NOFS 存储媒体是空白或是不支持的文件系统。
MEDIA_REMOVED 存储媒体被移除。
MEDIA_SHARED 存储媒体正在通过USB共享。
MEDIA_UNMOUNTABLE 存储媒体无法挂载。
MEDIA_UNMOUNTED 存储媒体没有挂载。
此外,Environment还提供了一下几种目录的名字:
DIRECTORY_ALARMS 系统提醒铃声存放的标准目录。
DIRECTORY_DCIM 相机拍摄照片和视频的标准目录。
DIRECTORY_DOWNLOADS 下载的标准目录。
DIRECTORY_MOVIES 电影存放的标准目录。
DIRECTORY_MUSIC 音乐存放的标准目录。
DIRECTORY_NOTIFICATIONS 系统通知铃声存放的标准目录。
DIRECTORY_PICTURES 图片存放的标准目录
DIRECTORY_PODCASTS 系统广播存放的标准目录。
DIRECTORY_RINGTONES 系统铃声存放的标准目录。
String externalState = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(externalState)){
File rootFile = Environment.getRootDirectory(); //获取根目录下的目录结构
String rootString = rootFile.getPath();
File storageFile = Environment.getExternalStorageDirectory();//获取外部设备中的目录结构
String storegeString = storageFile.getPath();
boolean mStorageEmulated = Environment.isExternalStorageEmulated();
boolean mStorageRemovable = Environment.isExternalStorageRemovable();
android.util.Log.v(TAG,"rootString:"+rootString);
android.util.Log.v(TAG,"storegeString:"+storegeString);
android.util.Log.v(TAG,"mStorageEmulated:"+mStorageEmulated);
android.util.Log.v(TAG,"mStorageRemovable:"+mStorageRemovable);
File mFile = new File(storegeString);
if(mFile.isDirectory()){
File mFiles[] = mFile.listFiles();
for(int index = 0;index < mFiles.length;index++){
//android.util.Log.v(TAG,"listFiles----name:"+mFiles[index].getName());
if(Environment.DIRECTORY_DOWNLOADS.equals(mFiles[index].getName())){
try {
File newDirectory = new File(mFiles[index].getPath(), "MyFile");
newDirectory.mkdir(); //创建目录文件
File newFile = new File(newDirectory.getPath(),"file.txt");
newFile.createNewFile(); //创建文件,如果文件名相同,覆盖
//字节流,按字节写入和读取
mInputStream = new FileInputStream(newFile);
mOutputStream = new FileOutputStream(newFile);
/**写入**/
String content = "但是这个目录很可能当前不能访问,比如这个目录被用户的PC挂载,"+"\n"
+"或者从设备中移除,或者其他问题发生,你可以通过getExternalStorageState()来获取当前状态。"+"\n"
+" 还有多用户或者多外部存储的情况,此文不再讨论。"+"\n\n\n";
byte []buffer = content.getBytes();
mOutputStream.write(buffer);
mOutputStream.flush();//刷新该流的缓冲
/**读取**/
int date;
byte[]buffer1 = new byte[2048];
while((date = mInputStream.read()) != -1){//读取一个字节,遇到文件末尾则返回-1
mInputStream.read(buffer1);
android.util.Log.v(TAG,"date:"+new String(buffer1));
}
//字符流,按字符写入和读取
writer = new BufferedWriter(new OutputStreamWriter(mOutputStream));
reader = new BufferedReader(new InputStreamReader(mInputStream));
/**写入**/
writer.newLine(); //空白行
writer.write("BufferedWriter");
writer.flush();//刷新该流的缓冲,否则下面的reader有时会读取不出刚写入的字符。
/**读取**/
if(reader.ready()){
String line;
while((line = reader.readLine())!= null){ //读取一行,遇到文件结尾或者空白行,返回null
android.util.Log.v(TAG,"line:"+line);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
//mOutputStream.close();
//mInputStream.close();
reader.close();
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
锁