(一)IO流的概述
-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
1、IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的对象都在IO包中
2、流按操作数据分为两种:字节流与字符流。
3、流按流向分为:输入流和输出流。
4、按功能的不同可分为节点流和处理流。
节点流:直接操作目标设备,例如:磁盘或一块内存区域。
处理流:通过操作节点流,从而间接完成输入或输出功能的流。处理流的存在是建立在 一个已经存在的输入流或输出流的基础之上的。
5、IO流的基本类:
字节流的抽象基类:
InputStream OutputStream
字符流的抽象基类:
Reader Writer
这四个类派生出来的子类名称都是以其父类名作为子类的后缀。
(二)字符流
操作数据最常见的基本体现形式是文件,用Writer和Reader的子类FileWriter 和 FileReader
字符流的缓冲区
缓冲区的出现提高了对数据的读写效率,缓冲区要结合流才可以使用在流的基础上对流的功能增强 ,BufferedWriter BufferedReader
ReadLine原理:
无论是读一行还是读取多个字符,其实最终都是在硬盘上一个个读取,用的还是read方法一次读一个,把数据临时存起来遇到回车符时一次性全部读出来。
实例1
package IO;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferefDemo {
public static void main(String[] args) {
BufferedWriter bfw = null;
BufferedReader bfd = null;
try {
bfw = new BufferedWriter(new FileWriter("E:\\javalianxi\\新建文件夹\\lang\\text1.txt"));
bfd = new BufferedReader(new FileReader("E:\\javalianxi\\新建文件夹\\lang\\Demo.txt"));
String len = null;
while((len = bfd.readLine())!=null){
bfw.write(len);
bfw.newLine();//换行
bfw.flush();//刷新
}
} catch (IOException e) {
throw new RuntimeException("读写异常");
}
finally{
try {
if(bfd!=null)
bfd.close();
} catch (IOException e2) {
throw new RuntimeException("读关闭异常");
}
try {
if(bfw!=null)
bfw.close();
} catch (IOException e2) {
throw new RuntimeException("写关闭异常");
}
}
}
}
装饰设计模式:
当想要对已有的对象进行功能的增强时,可以定义一个类将已有的对象传入,基于已有的功能提供加强功能,然后定义的类也称为装饰类。
装饰通常通过构造方法接收被装饰的对象,装饰模式比继承更灵活避免了继承的臃肿,而且降低了类与类之间的关系
(三)字节流
字节流主要是操作byte(字节)的类型数据:
字节输出流:OutputStream
字节输入流:InputStream
字节流和字符流在使用上的代码结构都是非常类似的,但是其内部本身也是有区别的,因为在进行字符流操作的时候会使用到缓冲区(内存中),而字节流操作的时候是不会使用到缓冲区的。
在输出的时候,OutputStream类即使最后没有关闭内容也可以输出。但是如果是Writer的话,则如果不关闭,最后一条内容是无法输出的,因为所有的内容都是保存在了缓冲区之中,每当调用了close()方法就意味着清空缓冲区了。那么可以证明字符流确实使用了缓冲区:
字节流:程序 → 文件
字符流:程序 → 缓冲区(内存中) → 文件
两者相比,肯定使用字节流更加的方便,而且在程序中像图片、MP3等都是采用字节的方式的保存,那么肯定字节流会比字符流使用的更广泛。如果要是想操作文本的话,字符流肯定是最好使的。
实例2
拷贝图片
思路
1、用字节流读取流对象和图片关联
2、用字节写入流创建一个图片文件,用于存储获取到的图片数据
3、通过循环读写,写完数据的存储
4关闭资源
package com.io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyPicDemo {
public static void main(String args[]){
long start = System.currentTimeMillis();
show();
long end = System.currentTimeMillis();
System.out.println((end-start)+"毫秒");
}
public static void show(){
FileOutputStream fop = null;
FileInputStream fip = null;
try {
fop = new FileOutputStream("Tulipsuu.jpg");
fip = new FileInputStream("Tulips.jpg");
byte[] by = new byte[1024];
int len = 0;
while((len = fip.read(by))!= -1){
fop.write(by , 0 , len);
}
}
catch (IOException e) {
throw new RuntimeException("读写异常");
}
finally{
try {
if(fip!=null)
fip.close();
} catch (IOException e2) {
// TODO: handle exception
}
try {
if(fop!=null)
fop.close();
} catch (IOException e) {
// TODO: handle exception
}
}
}
}
实例3
演示mp3通过缓冲区复制
package IO;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Map3Copy {
public static void main(String[] args)throws IOException {
BufferedInputStream bfs =
new BufferedInputStream(new FileInputStream("c:\\bb.mp3"));
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream("c:\\nn.mp3"));
int lin =0;
while((lin = bfs.read())!=-1){
bos.write(lin);
}
bfs.close();
bos.close();
}
}
(四)转换流
OutputStreamWriter:把字节输出流对象转成字符输出流对象
InputStreamReader:把字节输入流对象转成字符输入流对象
构建一个字节输出流对象
OutputStream out = newFileOutputStream("");
把字节输出流转成字符输出流
Writer w = new OutputStreamWriter(out);
然后的操作和使用字符输出流的操作一样
---------------------------------------------
构建一个字节输入流对象
InputStream is = newFileInputStream("");
把字节输入流转成字符输入流
Reader r = new InputStreamReader(is);
然后的操作和使用字符输入流的操作一样
(五)File类
流在操作的只有数据,而数据最明显的体现形式就是文件,文件又包含了很多的属性和行为信息, 比如说前缀名、扩展名、文件自己的大小时间等,所以文件是一个复杂的事物而这个事物有很多, 所以java就对文件这类的事物进行了描述,也把它封装成了对象,方面了我们对文件或文件夹的 属性进行操作。而File类的对象也主要用来获取文件本身的一些信息,如文件大小权限等,不涉 及对文件的读写操作。
java提供了三种创建方法来生成一个文件对象。 (1)根据参数指定的文件路径创建一个File文件对象,就是把某个文件封装成对象 File file1 = new File("D:\\abc\\123.txt"); (2)根据给定的目录创建一个File实体对象,其中"d:\\abc"为目录,"123.txt"为文件的名称 File file2 = new File("D:\\abc","123.txt"); (3)可以根据已知的目录文件对象File创建一个新的File实体对象 File d = new File("D:\\abc"); File file3 = new File(d,"123.txt");
File类所提供的方法中,有的是针对文件的处理,有的是针对目录的处理,可以通过一些方法来 判断文件是否存在以及文件的相对路径和绝对路径等,File类的常见方法有:
1,创建。 boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。
boolean mkdir():创建目录文件夹。
boolean mkdirs():创建多级文件夹。
2,删除。 boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();在程序退出时删除指定文件。
3,判断。 boolean exists() :文件是否存在.
isFile(): 是否为文件
isDirectory();是否为目录
isHidden(); 是否是隐藏文件
isAbsolute();是否是绝对路径
4,获取信息。
getName()://获取文件名
getPath()://获取相对路径
getParent()://返回的绝对路径的文件父目录
getAbsolutePath() //获取绝对路径
long lastModified()
long length()
文件列表: listRoots() 列出可用的文件系统根
List() 列出制定文件夹下的文件名称
ListFiles()返回当前文件夹下的文件及文件夹的对象
递归:函数自身调用自身的方法
实例
package IO;
import java.io.File;
public class FileDemo {
public static void main(String[] args) {
File dir =new File("D:\\com");
dirShow(dir);
}
private static void dirShow(File dir) {
System.out.println(dir);
File[] ff =dir.listFiles();
for (int x = 0; x < ff.length; x++) {
if(ff[x].isDirectory()){
dirShow(ff[x]);\\调用自己的方法
}
else {
System.out.println(ff[x]);
}
}
}
}
(六)IO包中的其他类类
Properties类
Properties是hashtable的子类。一个可以将键值进行持久化存储的对象。 也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。
是集合中和IO技术相结合的集合容器。 该对象的特点:可以用于键值对形式的配置文件。
那么在加载数据时,需要数据有固定格式:键=值。
特点: 1:可以持久化存储数据。 2:键值都是字符串。 3:一般用于配置文件。 |-- load():将流中的数据加载进集合。 原理:其实就是将读取流和指定文件相关联,并读取一行数据,因为数据是规则的key=value,所以获取一行后,通过 = 对该行数据进行切割,左边就是键,右边就是值,将键、值存储到properties集合中。 |-- store():写入各个项后,刷新输出流。 |-- list():将集合的键值数据列出到指定的目的地。
打印流
PrintWriter与PrintStream 可以直接操作输入流和文件。该流提供了打印方法,可以将各种数据类 型的数据都原样打印。
字节打印流:PrintStream
构造函数可以接收的参数类型: 1,file对象。File 2,字符串路径。String 3,字节输出流。OutputStream
字符打印流:PrintWriter
构造函数可以接收的参数类型: 1,file对象。File 2,字符串路径。String 3,字节输出流。OutputStream 4,字符输出流,Writer。
序列流 SequenceInputStream
对多个流进行合并,它的构造函数接收的是两个输入流,或者是接收一个输入流的枚举。
实例1
对图片的分段切割和合并
package com.io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
public class SequenceSplitDemo {
//切割后再合并
public static void main(String[] args) throws IOException{
show();
show2();
}
public static void show()throws IOException{
FileInputStream fis = new FileInputStream("E:\\javalianxi\\新建文件夹\\lang\\DSC00129.JPG");
FileOutputStream fos = null;
byte[] buf = new byte[1024*1024];
int len = 0;
int count=1;
while((len = fis.read(buf))!=-1){
fos = new FileOutputStream("E:\\javalianxi\\lianxi\\"+(count++)+".part");
fos.write(buf,0,len);
fos.close();
}
fis.close();
}
public static void show2() throws IOException{
ArrayListal = new ArrayList();
for (int x = 1; x <=5; x++) {
al.add(new FileInputStream("E:\\javalianxi\\lianxi\\"+x+".part"));
}
final Iteratorit = al.iterator();
Enumerationen = new Enumeration() {
public boolean hasMoreElements(){
return it.hasNext();
}
public FileInputStream nextElement(){
return it.next();
}
};
SequenceInputStream ss = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("E:\\javalianxi\\lianxi\\pic\\0.JPG");
byte[] buf = new byte[1024*1024];
int len= 0;
while((len = ss.read(buf))!=-1){
fos.write(buf,0,len);
}
ss.close();
fos.close();
}
}
直接操作对象的流bjectInputStream与ObjectOutputStream
管道流 PipedInputStream和PipedOutputStream输入输出可以直接进行连接,通过结合线程使用。
管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据 由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。 不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在 缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在, 则认为该管道已损坏。