IO总结

关于流的概念及作用:

 

流是一种有起始点的字节集合,对数据进行传输的总称,流的本质就是数据传输

它的作用就是为了方便进行更为直观的数据传输

 

IO流中的四大基类:

 

 字节流

字符流

   输入流

InputStream

Reader

   输出流

OutputStream

Writer

Io流中的所有类均是继承自这四大基类

 

按照输入输出的方向来分:

输入流:InputStream  Reader; 输出流: OutputStream  Writer

按照操作文件的形式来分:

字节流:InputStream OutputStream; 字符流:Reader  Writer

 

输入与输出指的是硬盘对于内存的方向来说:

内存读取硬盘中的数据 ——>读取的过程,即输入流

从内存中把数据存入硬盘——>写的过程,即输出流

 

字节流与字符流的区别:

字符流的底层也就是字节流, 字符流 = 字节流 + 编码表

如果只是操作文本文件(能用记事本打开的文件),那么就使用字符流操作

否则,就使用字节流进行操作(操作二进制文件)

 

输入流与输出流:

对输入流只能进行读的操作,对输出流只能进行写的操作,输入输出根据需要待传输的

数据的不同特性而使用不同的流


字节输入流(InputStream

InputStream是所有字节输入流的父类,所有的字节输出流均是继承自它,它是一个抽象类

这些都是InputStream的直接子类

AudioInputStreamByteArrayInputStream,FileInputStreamFilterInputStreamInputStreamObjectInputStreamPipedInputStreamSequenceInputStreamStringBufferInputStream

 

方法(常用)

 

int

available()
返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。

void

close()
关闭此输入流并释放与该流关联的所有系统资源。

int

read()
从输入流中读取数据的下一个字节。

int

read(byte[] b)
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 中。

 

read(byte[] b, int off, int len)
将输入流中最多 len 个数据字节读入 byte 数组。

 

 

方法的详细用法:

 

available():

返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数

应用:传到字节缓冲区中
byte [] buffer = new byte[fileinput.available()];
read()

从输入流中读取数据的下一个字节。如果到达流末尾而没有可用的字节,则返回值 -1。

read(byte [] b):

从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数。(读完数组的长度再进行储存,必须要判断数组的长度不为空,否则会报IO异常

read(byte[] int off,int len):

只读取数组的一部分(读到指定的长度)

close()

关闭流,释放系统资源(避免资源浪费)

字节输出流(OutputStream

字节输出流OutputStream是所有字节输出流的父类,字节输出流都是继承自它,它是一个抽象类

OutputStream的直接子类

ByteArrayOutputStreamFileOutputStreamFilterOutputStreamObjectOutputStreamOutputStreamPipedOutputStream

 

方法:

void

close()
关闭此输出流并释放与此流有关的所有系统资源。

void

flush()
刷新此输出流并强制写出所有缓冲的输出字节。

void

write(byte[] b)
将 b.length 个字节从指定的 byte 数组写入此输出流。

void

write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。

 

write(int b)

将指定的字节写入输出流


close():

关流,释放资源

write(int b):

将指定的字节写入输出流

write(byte [] b):

将b.length个字节从指定的数组中写入输出流

write(byte [] b,int off,inr len):

将数组中的一部分写入输出流

flush():

刷新输出流

 

 

字符输入流(Reader)

字符输入流Reader用于读取字符流的抽象类。

Reader的直接子类:

BufferedReaderCharArrayReaderFilterReaderInputStreamReaderPipedReaderStringReader

 

构造方法(决定了以什么样的方式初始化)

protected

Reader()
创建一个新的字符流 reader,其重要部分将同步其自身的 reader

protected

Reader(Object lock)
创建一个新的字符流 reader,其重要部分将同步给定的对象。



方法(常用):

abstract void

close()
关闭该流并释放与之关联的所有资源。

void

mark(int readAheadLimit)
标记流中的当前位置。

boolean

markSupported()
判断此流是否支持 mark() 操作。

int

read()
读取单个字符。

int

read(char[] cbuf)
将字符读入数组。

abstract int

read(char[] cbuf, int off, int len)
将字符读入数组的某一部分。

int

read(CharBuffer target)
试图将字符读入指定的字符缓冲区。

boolean

ready()
判断是否准备读取此流。



字符输出流(Writer)

字符输出流Writer是所有字符输出流的父类,它是一个抽象类。

 

Writer的直接子类:

BufferedWriterCharArrayWriterFilterWriterOutputStreamWriterPipedWriterPrintWriterStringWriter

 

构造方法(决定了它将以什么样的方式初始化)

protected

Writer()
创建一个新的字符流 writer,其关键部分将同步 writer 自身。

protected

Writer(Object lock)
创建一个新的字符流 writer,其关键部分将同步给定的对象。

 

方法:

 


Writer

append(char c)
将指定字符添加到此 writer

Writer

append(CharSequence csq)
将指定字符序列添加到此 writer

Writer

append(CharSequence csq, int start, int end)
将指定字符序列的子序列添加到此 writer.Appendable

abstract void

close()
关闭此流,但要先刷新它。

abstract void

flush()
刷新该流的缓冲。

void

write(char[] cbuf)
写入字符数组。

abstract void

write(char[] cbuf, int off, int len)
写入字符数组的某一部分。

void

write(int c)
写入单个字符。

void

write(String str)
写入字符串。

void

write(String str, int off, int len)
写入字符串的某一部分。

方法同与字节输出流

 

BufferedReader(高效,自带缓冲区)

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 

可以指定缓冲区的大小

构造方法:

BufferedReader(Reader in) 
创建一个使用默认大小输入缓冲区的缓冲字符输入流。

BufferedReader(Reader in, int sz)   sz - 输入缓冲区的大小 


创建一个使用指定大小输入缓冲区的缓冲字符输入流。

 

独有的方法:

readLine

一次读一行

 

 

 

BufferedWriter(高效自带缓冲)

构造方法:

BufferedWriter(Writer out) 
创建一个使用默认大小输出缓冲区的缓冲字符输出流。

BufferedWriter(Writer out, int sz) 
创建一个使用给定大小输出缓冲区的新缓冲字符输出流。

主要方法:

newline:

写入一个行分隔符(换行)—>Windows中的换行符为‘ \ r \ n

/*

 * 拷贝二进制文件的几种方式和时间比较

 */

long start = System.currentTimeMillis(); //系统时间毫秒值

1.available返回文件从输入流读取的剩余字节数  44ms

2.使用Buffered+字节数组缓冲区  34ms /  Buffered +字节  515ms

3.使用字节数组做为缓冲区    57ms/  按字节读写 95103 ms

 

由此可见:使用高效buffered+缓冲性能是最高的

 

 

 

 

 

 

 

 

 

 

转换流(InputStreamReader OutputStreamWriter

这两个流对象本质上属于字符流(具有转换功能的字符流),所以在构造的时候需要传入字节流对象进来。

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。直接已知子类是FileReader

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。 直接已知子类是FileWriter

 

 

装饰设计模式

就是对原有类的包装,增强其功能

与继承的区别:比继承更简单高效(代码量更少,使用更方便)

把需要增强的功能封装起来,需要调用时直接调用即可

装饰类和被装饰的特点:

1,装饰类中的构造函数需要接受被装饰类。

         2,装饰类和被装饰类应该所属于同一个体系。

如:对流对象的功能增强,增强写的效率

自定义一个实现缓冲的类,继承此类的功能再进行增强

 

File

文件和目录路径名的抽象表示形式。

File类是对硬盘中文件以及文件夹进行封装的对象,File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。

File 类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变。

 

pathSeparator:与系统有关的路径分隔符(带“;”)

separator:与系统有关的默认名称分隔符(“File.separator”)

在不同的操作系统上的路径分隔符与名称分隔符的写法都是不同的,使用separator来通配路径分隔符(在Windows上的路径分隔符是“\\,Linux操作系统上则是“//”)

 

构造方法:

File(File parent, String child)
根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。

File(String pathname)
通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。

File(String parent, String child)
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。

File(URI uri)
通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。

 

 

 

常用的构造方法:
File(String pathname):

通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。

(pathname —路径名字符串

 

boolean

delete()
删除此抽象路径名表示的文件或目录。

boolean

exists()
测试此抽象路径名表示的文件或目录是否存在。

String

getAbsolutePath()
返回此抽象路径名的绝对路径名字符串。

String

getName()
返回由此抽象路径名表示的文件或目录的名称。

boolean

isDirectory()
测试此抽象路径名表示的文件是否是一个目录。

boolean

isHidden()
测试此抽象路径名指定的文件是否是一个隐藏文件。

String[]

list()
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。

String[]

list(FilenameFilter filter)
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。

File[]

listFiles()
返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。

File[]

listFiles(FileFilter filter)
返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。

File[]

listFiles(FilenameFilter filter)
返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。

boolean

mkdir()
创建此抽象路径名指定的目录。

String

toString()
返回此抽象路径名的路径名字符串。



File常用的方法:

createNewFile 创建新文件

mkdir 创建新目录

mkdirs 创建多级目录

delete()  删除

exists()   判断是否存在

isDirectory() 是否为目录

isFile() 是否为文件

list:返回目录名称

listFiles:返回目录的路径及名称

 

 

文件过滤器

FilenameFilter——>文件名过滤器

FileFilter ——文件过滤器

文件过滤器(FilenameFilter/FileFilter)为接口,能够过滤得到指定类型的文件或者目录,但必须重写accept(File file,String path)方法,需要实现FilenameFilter接口

 

步骤:

1.先判断File是否目录(isDirectory)

2.通过list()方法得到这个目录下所有的文件和目录的名称数组,

3.“超级过滤器”:创建一个私有有参构造,然后使用list()的带参构造,返回以此私有方法为后缀的文件

class XFiltx implements FilenameFilter{

private String suffix;

public XFiltx(String suffix) {

super();

this.suffix = suffix;

}

@Override

public boolean accept(File dir, String name) {

return name.endsWith(suffix);

}

}

 

ByteArray

FileInputStream : 输入流,内容是从文件里读出来的

 ByteArrayInputStream: 内容是存在这个流内部的缓冲区里的

 

 FileOutputStream 是写入到了文件里,来存放写入的数据, 数据在磁盘上

 ByteArrayOutputStream  里边有个byte类型的数组,用来缓存你所写入的数据,数据在内存里,他就相当于一个长度可变的byte数组

数组流使用完后可不必关

 

Properties类

Properties直接继承自hashtable(是hashmap的老哥)

Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。即:hashtable<K,V>,k v都是字符串类型

 

Properties类 是集合与IO相关的方法

 

构造方法:

Properties()
创建一个无默认值的空属性列表。

Properties(Properties defaults)
创建一个带有指定默认值的空属性列表。

常用方法是使用空参构造来初始化对象。

 

常用方法:

String

getProperty(String key)
用指定的键在此属性列表中搜索属性。

String

getProperty(String key, String defaultValue)
用指定的键在属性列表中搜索属性。

void

list(PrintStream out)
将属性列表输出到指定的输出流。

void

list(PrintWriter out)
将属性列表输出到指定的输出流。

void

load(InputStream inStream)
从输入流中读取属性列表(键和元素对)。

void

load(Reader reader)
按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。


load

按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 

getPeoperties:

用指定的键在此属性列表中搜索属性。如果在此属性列表中未找到该键,则接着递归检 查默认属性列表及其默认值。如果未找到属性,则此方法返回 null。
list:(此list非彼list,这个list是在Properties类中重写,属于Properties的特有方法)

将属性列表输出到指定的输出流。此方法对调试很有用。

打印流

字节打印流 ——>PrintStream

字符打印流 ——>printWriter

打印流可以打印所有数据类型:小数,整数,字符/串,以及乱码;

 

构造方法:

PrintStream(File file)
创建具有指定文件且不带自动行刷新的新打印流。

PrintStream(File file, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新打印流。

PrintStream(OutputStream out)
创建新的打印流。

PrintStream(OutputStream out, boolean autoFlush)
创建新的打印流。

PrintStream(String fileName)
创建具有指定文件名称且不带自动行刷新的新打印流。

 

PrintWriter(String fileName, String csn)(最实用)
创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter

常用的构造:

PrintStream(String fileName) :

PrintStream ps = new PrintStream(

new FileOutputStream(new File("f:"+File.separator+"a.txt")));
方法:

PrintStream

append(char c)
将指定字符添加到此输出流。

PrintStream

append(CharSequence csq)
将指定字符序列添加到此输出流。

PrintStream

append(CharSequence csq, int start, int end)
将指定字符序列的子序列添加到此输出流。

void

close()
关闭流。

void

flush()
刷新该流的缓冲。

void

print(boolean b)
打印 boolean 值。

void

print(char c)
打印字符。

void

print(char[] s)
打印字符数组。

void

print(double d)
打印双精度浮点数。

void

print(float f)
打印浮点数。

void

print(int i)
打印整数。

void

print(long l)
打印 long 整数。

void

print(Object obj)
打印对象。

void

print(String s)
打印字符串。

void

println()
通过写入行分隔符字符串终止当前行。

void

println(boolean x)
打印 boolean 值,然后终止行。

void

println(char x)
打印字符,然后终止该行。

void

println(char[] x)
打印字符数组,然后终止该行。

void

println(double x)
打印 double,然后终止该行。

void

println(float x)
打印 float,然后终止该行。

void

println(int x)
打印整数,然后终止该行。

void

println(long x)
打印 long,然后终止该行。

void

println(Object x)
打印 Object,然后终止该行。

void

println(String x)
打印 String,然后终止该行。

void

write(byte[] buf, int off, int len)
将 len 字节从指定的初始偏移量为 off 的 byte 数组写入此流。

void

write(int b)
将指定的字节写入此流。

 

常用方法:

printprintln:直接打印(区别换行与不换行)

方法2

1)使用键盘录入

2)初始化pintWriter(使用匿名对象,true

3)缓冲—>String line = null;

4)输出—>pw.println(line);

 

 

 

序列化与反序列化

把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。

 

对象的序列化主要有两种用途:
  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
  2) 在网络上传送对象的字节序列。

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象(就是把对象转换成字节序列化存储到硬盘,然后反序列化把硬盘上的字节序列再读取到硬盘中)

 

ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

 

构造方法:

protected

ObjectOutputStream()
为完全重新实现 ObjectOutputStream 的子类提供一种方法,让它不必分配仅由 ObjectOutputStream 的实现使用的私有数据。

 

ObjectOutputStream(OutputStream out)
创建写入指定 OutputStream 的 ObjectOutputStream

 

方法:

writeObject将指定的对象写入 ObjectOutputStream

接口:

Serializable(表示对象可序列化,用到了标记设计模式)


要写入可通过 ObjectOutputStream 中的示例读取的对象,需执行以下操作:

        FileOutputStream fos = new FileOutputStream("t.tmp");

        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeInt(12345);

        oos.writeObject("Today");

        oos.writeObject(new Date());

        oos.close();

ObjectInputStreamInputStream的子类,继承了它的方法

 

序列版本号(两种方式):

private static final long serialVersionUID = 1L;

private static final long serialVersionUID = -1308681642922066213L;

 

步骤:

1)创建一个文件输出流对象

2)用ObjectOutputStream来初始化这个fileoutputstream

3)写入要序列化的内容:

oos.writeObject(new Person("Jack",22));

4)关流

 

反序列化:

ObjectInputStream将字节序列化恢复成对象

方法:

ReaderObject:从 ObjectInputStream 读取对象

 

步骤:

1)创建一个文件输入流来读取之前存储序列化的文件

2)用ObjectOutputStream来初始化这个fileinputstream

3)使用自定义类来定义对象接收读取到的序列化数据

Person p = (Person)ois.readObject();

4)在输出中转换成字符串类型

System.out.println(p.getName() + "," +p.getAge());

5)关流

 

Transient关键字

在序列化时自定义的类必须要实现seializable接口,但方法被transient关键字修饰后将不会再被序列化

private transient String name;

但是

如果实现 Externalizable接口,则不论是否被transient修饰都会被序列化

 

切割文件

SplitFile

步骤:

1)读取文件(InputStream

2)创建空的文件输出流(用于输出切割后的文件)

3)建立一个字节缓冲区(存满就切,这个缓冲的数组多大的切割的文件就多大)

4)定义数组长度,一个计数器

5)创建一个新的目录来存储切割后的文件(判断有无,否则创建)

6)在循环内输出,将它们存储在指定文件中

7)关流

合并流(SequenceInputStream

把两个文件合并成一个文件

一.将要合并的多个文件的输入流存入集合

二.用集合返回Enumeration接口

步骤:

1)把输出流给存入到定义的集合中

2)把集合返回Enumeeration接口(使用了工具类Collections中的enumeration方法)

3)用SequenInputStream来初始化Enumertion接口

4)输出流输出到文件中(创建文件及路径)

5)建立一个字节缓冲区

6)在循环中输出

7)关流