1、流的概念
1.1流
(1)流是一个无结构化的数据组成的序列,流中的数据没有任何格式和含义,只是以字节或字符形式进行流入或流出。
(2)数据流的流入和流出都是以程序本身作为核心,流入是指数据从外部数据源流入到程序内部;流出是指数据从程序内部向外部流出到数据的目的地。
(3)不管是流入还是流出,其数据的流动都是通过一个管道进行的,管道两端分别连接数据源和数据目的地。
(4)流的本质就是进行数据传输,因此Java根据数据传输的特性将流抽象成各种类,以方便进行数据操作。
1.2流的分类
- 根据处理数据类型,可以分为字节流和字符流。
- 根据数据的流向可以分为输入流和输出流。
- 根据处理数据功能,可以分为实体流和装饰流。
- 实体流对数据不做任何处理,只完成基本的读写操作。
- 装饰流是在实体流的基础上,提供更高级的功能。
- 这些流都在java.io包中。
1.2.1字节流
- 在数据传输过程中以字节为单位进行输入和输出。
- 适用于传输各种类型的文件或数据。
- 在字节输入流中,InputStream 类是所有的输入字节流的父类,它是一个抽象类。
- 其子类中的ByteArrayInputStream、FileInputStream 是两种基本的实体流。
- ObjectInputStream 和所有FilterInputStream 的子类都是装饰流。
- 在字节输出流中,OutputStream 是所有的输出字节流的父类,它是一个抽象类。
- ByteArrayOutputStream、FileOutputStream 是两种基本的实体流。
- ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。
1.2.2字符流
- 在数据传输过程中以字符为单位进行输入和输出。
- 根据字符编码表,一个字符占用两个字节,因此字符流只适用于字符类型数据的处理。
- 在字符输入流中,Reader 是所有的输入字符流的父类,它是一个抽象类。
- InputStreamReader 是一个连接字节流和字符流的桥梁,它使用指定的字符集读取字节并转换成字符。
- 其FileReader子类可以更方便地读取字符文件,也是常用的Reader流对象。
- 在字符输出流中,Writer是所有的输出字符流的父类,也是一个抽象类。
- 相对输入流的子类,输出流当中也有相应的输出子类,只是数据传输方向相反。
- 这些类有OutputStreamWriter及其子类FileWriter、 CharArrayWriter、StringWriter 、BufferedWriter 、PipedWriter等。
2、File类
2.1文件对象与文件属性
文件用文件类的对象表示,有了文件对象就可以获取文件属性。
返回类型 | 方法名 | 功能 |
---|---|---|
File(String filename) | 在当前路径下,创建一个名字为filename的文件 | |
File(String path, | ||
String filename) | 在给定的path路径下,创建一个名字为filename的文件 | |
String | getName() | 获取此文件(目录)的名称 |
String | getPath() | 获取路径名字符串 |
long | length() | 获取文件的长度。如果表示目录,则返回值不确定 |
boolean | canRead() | 判断文件是否可读 |
String | getAbsolutePath() | 获取路径名字符串 |
boolean | canWrite() | 判断文件是否可写 |
boolean | canExecute() | 判断文件是否执行 |
boolean | exists() | 判断文件(目录)是否存在 |
boolean | isFile() | 判断文件是否是一个标准文件 |
boolean | isDirectory() | 判断文件是否是一个目录 |
boolean | isHidden() | 判断文件是否是一个隐藏文件 |
long | lastModified() | 判断文件最后一次被修改的时间 |
2.2目录
Java把目录作为一种特殊的文件进行处理,它除了具备文件的基本属性如文件名、所在路径等信息以外,同时也提供了专用于目录的一些操作方法。
返回类型 | 方法名 | 功能 |
---|---|---|
boolean | mkdir() | 创建一个目录,并返回创建结果。成功返回true,失败(目录已存在)返回false |
boolean | mkdirs() | 创建一个包括父目录在内的目录。创建所有目录成功返回true,如果失败返回false,但要注意的是有可能部分目录已创建成功 |
String[] | list() | 获取目录下字符串表示形式的文件名和目录名 |
String[] | list(FilenameFilter filter) | 获取满足指定过滤器条件的字符串表示形式的文件名和目录名 |
File[] | listFiles() | 获取目录下文件类型表示形式的文件名和目录名 |
File[] | listFiles(FileFilter filter) | 获取满足指定过滤器文件条件的文件表示形式的文件名和目录名 |
File[] | listFiles(FilenameFliter fliter) | 获取满足指定过滤器路径和文件条件的文件表示形式的文件名和目录名 |
2.3文件的操作
创建文件File类的方法:
public boolean createNewFile()
File file = new File(“D:\\”,”hello.txt”)
file.createNewFile();
删除文件File类中的方法:
file.delete()
运行可执行文件
首先利用Runtime类的静态方法创建一个Runtime对象:
Runtime ec = Runtime.getRuntime();
然后用ec调用方法:
Process exec(String command);
2.4 Scanner类与文件
利用Scanner类的对象还可以从文件中读取数据:
Scanner input=new Scanner(文件类对象)
创建的Scanner类的对象使用read()方法即可从文件中读数据。
读数据时默认以空格作为数据的分隔标记。
3、字节流和字符流
3.1字节流
抽象类InputStream和抽象类OutputStream是所有字节流类的根类,其他字节流类都继承自这两个类。
3.1.1 字节输入流InputStream
字节输入流的作用是从数据输入源(例如从磁盘、网络等)获取字节数据到应用程序(内存)中。
返回类型 | 方法名 | 功能 |
---|---|---|
int | read() | 从输入流中读取下一个字节,返回读入的字节数据;如果读到末尾,返回-1 |
int | read(byte b[]) | 从输入流中读取一定数量的字节保存到字节数组中,并返回实际读取的字节数 |
int | read(byte b[],int off, | |
int len) | 从输入流中读取最多len个字节,保存到数组b中从off开始的位置,并返回实际读入的字节数;如果off+len 大于b.length,或者off 和len中有一个是负数,那么会抛出IndexOutOfBoundsException异常 | |
long | skip(long n) | 从输入流中跳过并丢弃n个字节,并返回实际跳过的字节数 |
void | close() | 关闭输入流,释放资源。对流的读取完毕后调用该方法以释放资源 |
int | available() | 返回此输入流可以读取(或跳过)的估计字节数 |
void | mark(int readlimit) | 在输入流中标记当前的位置。参数readlimit为标记失效前最多读取的字节数。如果读取的字节数超出此范围则标记失效 |
void | reset() | 将输入流重新定位到最后一次调用 mark 方法时的位置 |
boolean | markSupported() | 测试此输入流是否支持 mark 和 reset 方法。只有带缓存的输入流支持标记功能 |
3.1.2 文件字节输入流类FileInputStream
在进行字节输入流操作时,经常使用的是InputStream类的子类FileInputStream,实现简单的文件数据读取。
FileInputStream类的常用构造方法:
public FileInputStream(File file) throws FileNotFoundException
public FileInputStream(String name) throws FileNotFoundException
通过给定的File对象和文件创建文件字节输入流对象。
在创建输入流时,如果文件不存在或出现其他问题,会抛出FileNotFoundException异常,所以要注意捕获。
字节输入流读数据步骤:
- 设定输入流的数据源
- 创建指向这个数据源的输入流
- 从输入流中读取数据
- 关闭输入流
3.1.3 字节输出流OutputStream
字节输出流的作用是将字节数据从应用程序(内存)中传送到输出目的地,如外部设备、网络等。
字节输出流OutputStream的常用方法。
返回类型 | 方法名 | 功能 |
---|---|---|
void | write(int b) | 将整数b的低8位写到输出流 |
void | write(byte b[]) | 将字节数组中数据写到输出流 |
void | write(byte b[ ], | |
int off,int len) | 从字节数组b的off处写len个字节数据到输出流 | |
void | flush() | 强制将输出流保存在缓冲区中的数据写到输出流 |
void | close() | 关闭输出流,释放资源 |
3.1.4 文件字节输出流类FileOutputStream
在进行字节输出流操作时,经常使用的是OutputStream类的子类FileOutputStream,用于将数据写入File或其他的输出流。
FileOutputStream类的常用构造方法:
public FileOutputStream(File file) throws IOException
public FileOutnputStream(String name) throws IOException
public FileOutputStream(File file, boolean append) throws IOException
public FileOutputStream(String name, boolean append) throws IOException
字节输出流写数据步骤:
- 设定输出流的目的地
- 创建指向这目的地输出
- 向输出流中写入数据
- 关闭输出流
在完成写操作过程中,系统会将数据暂存到缓冲区中,缓冲区存满后再一次性写入到输出流中。
执行close()方法时,不管缓冲区是否已满,都会把其中的数据写到输出流。
3.2 字符流
字符流通常用于文本文件的传输。
抽象类Reader和抽象类Writer是所有字符流类的根类,其他字符流类都继承自这两个类。
其中一些子类还在传输过程中对数据做了进一步处理以方便用户的使用。
3.2.1 字符输入流Reader
字符输入流Reader是所有字符输入流类的父类,实现从数据源读入字符数据。常用方法有:
返回类型 | 方法名 | 功能 |
---|---|---|
int | read() | 从输入流读取单个字符 |
int | read(char[] cbuf) | 从输入流读取字符保存到数组cbuf中,返回读取的字符数,如果已到达流的末尾,则返回 -1 |
int | read(char[] cbuf,int off,int len) | 从输入流读取最多len个字符保存到字符数组cbuf中,存放的起始位置在off处。返回:读取的字符数,如果已到达流的末尾,则返回 -1 |
long | skip(long n) | 跳过n个字符。 |
返回:实际跳过的字符数 | ||
void | mark(int readAheadLimit) | 标记流中的当前位置 |
void | reset() | 重置该流 |
boolean | markSupported() | 判断此流是否支持 mark() 操作 |
void | close() | 关闭该流,释放资源 |
3.2.2 文件字符输入流FileReader
进行字符输入流操作时,经常使用的是Reader类的子类FileReader,用于从输入流读取数据。
FileReader类的常用构造方法:
public FileReader(File file) throws FileNotFoundException
public FileReader(String name) throws FileNotFoundException
通过给定的File对象或文件名创建字符输入流。
在创建输入流时,如果文件不存在或出现其他问题,会抛出FileNotFoundException异常。
3.2.3 字符输出流Writer
返回类型 | 方法名 | 功能 |
---|---|---|
void | write(int c) | 将整数c的低16位写到输出流 |
void | write(char[] cbuf) | 将字符数组中数据写到输出流 |
void | write(cbuf[ ],int off,int len) | 从字符数组cbuf的off处开始取len个字符写到输出流 |
void | write(String str) | 将字符串写到输出流 |
void | write(String str,int off,int len) | 从字符串str的off处开始取len个字符数据写到输出流 |
void | flush() | 强制将输出流保存在缓冲区中的数据写到输出 |
void | close() | 关闭输出流,释放资源 |
3.2.4 文件字符输出流FileWriter类
FileWriter类和字节流FileOutputStream类相对应,实现字符的输出操作,实现方法也基本相同。FileWriter类的常用构造方法:
public FileWriter(File file) throws IOException
public FileWriter(String name) throws IOException
public FileWriter(File file, boolean append) throws IOException
public FileWriter(String name, boolean append) throws IOException
如果第二个参数为 true,则将字符写入文件末尾处,而不是写入文件开始处。
如果文件不存在或出现其他问题,会抛出IOException异常。
4、数据流
数据流是Java提供的一种装饰类流。
建立在实体流基础上,让程序不需考虑数据所占字节个数的情况下就能够正确地完成读写操作。
DataInputStream类和DataOutputStream类分别为数据输入流类和数据输出流类。
4.1 数据输入流
数据输入流DataInputStream类允许程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。
DataInputStream类的常用方法:
返回类型 | 方法名 | 功能 |
---|---|---|
DataInputStream(InputStream in) | 使用指定的实体流 InputStream 创建一个DataInputStream | |
boolean | readBoolean() | 读取一个布尔值 |
byte | readByte() | 读取一个字节 |
char | readChar() | 读取一个字符 |
long | readLong() | 读取一个长整型数 |
int | readInt() | 读取一个整数 |
short | readShort() | 读取一个短整型数 |
float | readFloat() | 读取一个Float数 |
double | readDouble() | 读取一个Double数 |
String | readUTF() | 读取一个UTF字符串 |
int | skipBytes(int n) | 跳过并丢弃n个字节,返回实际跳过的字节数 |
4.2 数据输出流
数据输出流DataOutputStream类允许程序以适当方式将基本Java数据类型写入输出流中。DataOutputStream类的常用方法:
返回类型 | 方法名 | 功能 |
---|---|---|
DataOuputStream | ||
(OutputStream out) | 创建一个新的数据输出流,将数据写入指定基础输出流 | |
void | writeBoolean(Boolean v) | 将一个布尔值写出到输出流 |
void | writeByte(int v) | 将一个字节写出到输出流 |
void | writeBytes(String s) | 将字符串按字节(每个字符的高八位丢弃)顺序写出到输出流中 |
void | writeChar(int c) | 将一个 char 值以2字节值形式写入输出流中,先写入高字节 |
void | writeChars(String s) | 将字符串按字符顺序写出到输出流 |
void | writeLong(long v) | 将一个长整型数写出到输出流 |
void | writeInt(int v) | 将一个整数写出到输出流 |
void | writeShort(int v) | 将一个短整型数写出到输出流 |
void | writeFloat(float v) | 将一个Float数写出到输出流 |
void | writeDouble(double v) | 将一个Double数写出到输出流 |
void | writeUTF(String s) | 将一个字符串用UTF-8编码形式写出到输出流 |
int | size() | 返回写到数据输出流中的字节数 |
void | flush() | 清空输出流,使所有缓冲中的字节被写出到流中 |
5、缓冲流
缓冲流是在实体I/O流基础上增加一个缓冲区,应用程序和I/O设备之间的数据传输都要经过缓冲区来进行。
缓冲流分为缓冲输入流和缓冲输出流。
缓冲输入流是将从输入流读入的字节/字符数据先存在缓冲区中,应用程序从缓冲区而不是从输入流读取数据;
缓冲输出流是在进行数据输出时先把数据存在缓冲区中,当缓冲区满时再一次性地写到输出流中。
使用缓冲流可以减少应用程序与I/O设备之间的访问次数,提高传输效率;
可以对缓冲区中的数据进行按需访问和预处理,增加访问的灵活性。
5.1 缓冲输入流
包括字节缓冲输入流BufferedInputStream类和字符缓冲输入流BufferedReader类。
5.1.1 字节缓冲输入流BufferedInputStream类
先通过实体输入流(例如FileInputStream类)对象逐一读取字节数据并存入缓冲区,应用程序则从缓冲区中读取数据。
构造方法:
public BufferedInputStream(InputStream in)
public BufferedInputStream(InputStream in,int size)
size:指定缓冲区的大小。
BufferedInputStream类继承自InputStream,所以该类的方法与InputStream类的方法相同。
5.1.2 字符缓冲输入流BufferedReader类
与字节缓冲输入流BufferedInputStream类在功能和实现上基本相同。它只适用于字符读入。
构造方法:
public BufferedReader(Reader in)
public BufferedReader(Reader in,int sz)
BufferedReader类继承自Reader,所以该类的方法与Reader类的方法相同。
新增按行读取的方法:String readLine()
该方法返回值为该行不包含结束符的字符串内容,如果已到达流末尾,则返回 null。
5.2 缓冲输出流
缓冲输出流包括字节缓冲输出流BufferedOutputStream类和字符缓冲输出流BufferedWriter类。
5.2.1 字节缓冲输出流BufferedOutputStream类
完成输出操作时,先将字节数据写入缓冲区,当缓冲区满时,再把缓冲区中的所有数据一次性写到底层输出流中。
构造方法:
public BufferedOutputStream(OutputStream out)
public BufferedOutputStream(OutputStream out,int size)
BufferedOutputStream类继承自OutputStream,所以该类的方法与OutputStream类的方法相同。
5.2.2 字符缓冲输出流BufferedWriter类
与字节缓冲输出流BufferedOutputStream类在功能和实现上是相同的。只适用于字符输出。
BufferedWriter类的构造方法:
public BufferedWriter(Writer out)
public BufferedWriterr(Writer out,int sz)
BufferedWriter类继承自Writer,所以该类的方法与Writer类的方法相同。
新增写行分隔符的方法:String newLine()
行分隔符字符串由系统属性 line.separator 定义。
6、 随机流
随机流RandomAccessFile类创建的对象既可以作为输入流,也可以作为输出流,因此建立一个随机流就可以完成读写操作。
RandomAccessFile类是java.lang.Object根类的子类。
RandomAccessFile类的实例对象支持对随机访问文件的读取和写入。
随机流可以用于多线程下载或多个线程同时写数据到文件,为快速完成访问提供了便利。
6.1 RandomAccessFile类
返回类型 | 方法名 | 功能 |
---|---|---|
RandomAccessFile(String name, String mode) | 参数name为待访问的文件名,file待访问的文件。参数mode为读写模式,常用的值有:“r”以只读方式打开文件,如果进行写操作会产生异常;“rw”:以读写方式打开文件,如果文件不存在,则创建 | |
RandomAccessFile(File file, String mode) | 同上 | |
int | read() | 从文件中读取一个数据字节并以整数形式返回此字节 |
int | read(byte[] b) | 从文件中读取最多b.length 个数据字节到b数组中,并返回实际读取的字节数 |
int | read(byte[] b, int off, int len) | 从文件中读取len个字节数据到b数组中。off为字节在数组中存放的地址 |
XXX | readXXX() | 从文件中读取一个XXX类型数据,XXX包括:boolean,byte,char,short,int,lang,float,double |
void | write(int b) | 写入指定的字节 |
void | write(byte[] b) | 写入字节数组内容到文件 |
void | writeXXX | |
(XXX v) | 写入指定类型数据到文件,XXX包括:boolean,byte,char,short,int,lang,float,double | |
void | writeChars(String s) | 写入字符串到文件 |
void | writeUTF(String s) | 按UTF-8编码形式将字符串写入到文件 |
long | getFilePointer() | 获取文件的当前偏移量 |
void | seek(long pos) | 设置文件的指针偏移量 |
long | length() | 获取文件的长度 |
void | setLength(long newLength) | 设置此文件的长度。 如果 length 方法返回的文件的现有长度大于 newLength 参数,则该文件将被截短。超过则加大文件,多出部分没有内容 |
int | skipBytes(int n) | 跳过输入的 n 个字节并丢弃跳过的字节 |
void | close() | 关闭文件流,释放资源 |
由于编码格式不同当进行字符串读取的时候,有时会出现“乱码”的现象。
对字符串重新进行编码可以解决乱码问题:
- 先读字符串:
String str = in.readLine();
- 再将字符串恢复成标准字节数组:
byte [] b=str.getBytes(“iso-8859-1”);
- 最后将字节数组按当前机器的默认编码重新转化为字符串:
String result=new String(b);
- 显式地指明编码类型,可以直接给出编码类型:
String result=new String(b,”GB2312”);
7、对象流
对象流是在实体流基础上,通过对对象数据的处理和变换,实现对象的永久保存和读取。
ObjectInputStream和ObjectOutputStream分别是对象输入流类和对象输出流类,它们也是InputStream和OutputStream类的子类。
通过对象输出流,可以把对象写入到文件或进行网络传输。
对象输入流类可以从文件或网络上,把读取的数据还原成对象。
要想实现对象的传输,待传输的对象要先进行序列化处理,才能保证对象能准确地保存和读取。
7.1 对象的序列化
对象的序列化是指把对象转换成字节序列的过程,而把字节序列恢复为对象的过程称为对象的反序列化。
一个类如果实现了java.io.Serializable接口,这个类的实例(对象)就是一个序列化的对象。
Serializable接口中没有方法。实现了该接口的对象进行输出时,JVM将按照一定的格式(序列化信息)转换成字节进行传输和存储到目的地。
对象输入流从文件或网络上读取对象时,会先读取对象的序列化信息,并根据这一信息创建对象。
7.2 对象输入流与对象输出流
7.2.1 对象输入流ObjectInputStream类
实现对象的输入操作。构造方法:
public ObjectInputStream(InputStream in)
类中的方法:Object readObject()
从ObjectInputStream流中读取对象。
7.2.2 对象输出流ObjectOutputStream类
实现对象的输出操作。构造方法:
public ObjectOutputStream(OutputStream out)
类中的方法:void writeObject(Object o)
将指定对象o写入ObjectOutputStream流中。