流是一组有序的数据序列,根据操作的类型,可以分为输入流和输出流两种。
Java定义的输入输出类被放在java.io包中
所有的输入流类都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类
而所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类
InputStream类是字节输入流的抽象类,它是所有字节输入流的父类。
该类中所有方法遇到错误时都会引发IOException异常,下面是该类方法中的简要说明:
·read():从输入流中读取数据的下一个字节。返回0~255的int字节值。如果因为已经到达流末尾而没有可用的字节,则返回值为1
·read(byte[] b):从输入流中读入一定长度的字节,并以证书的形式返回字节数
·mark(int readlimit):在输入流的当前位置放置一个标记,readlimit参数告知此输入流在标记位置失效前允许读取的字节数
·reset():将输入指针返回到当前所做的标记处
·skip(long n):跳过输入流上的n个字节并返回实际跳过的字节数
·markSupported():如果当前流支持mark()/reset()操作就返回true
·close():关闭此输入流并释放与该留关联所有的系统资源
并不是所有的InputStream类的子类都支持InputStream类中定义的所有方法,如skip(),mark(),reset()等方法只对某些子类有用
InputStream类是用来处理字节的,并不适合处理字符文本。Reader类是可以专门处理字符文本的类,但是Reader类并不是InputStream类的替换者,只是在处理字符串的时候简化了编程。Reader类是字符输入流的抽象类,所有字符输入流的实现都是它的子类。
OutputStream类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类。
OutputStream类中的所有方法均返回void,在遇到错误时会引发IOException异常。下面是对OutputStream类中的一些方法的简要说明:
write(int b):将指定的字节写入此输出流。
write(byte[] b)方法:将b个字节从指定的byte数组写入此输出流。
write(byte[] b,int off,int len)方法:将指定byte数组中从偏移量off开始的len个字节写入此输出流。
flush()方法:彻底完成输出并清空缓存区。
close()方法:关闭输出流。
Writer类是字符输出流的抽象类,所有字符输出类的实现都是它的子类
File类是java.io包中唯一代表磁盘文件本身的类。File类定义了一些与平台无关的方法开操作文件,可以通过调用File类的方法,实现创建、删除、重命名文件等操作。
File类的对象主要用来获取文件本身的一些信息,如文件所在目录,文件的长度、文件读写权限等。数据流可以将数据写入文件中。
通常使用以下三种方法来创建文件对象
1.File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建一个新File实例:
new File(String pathname),
其中 pathname代表包含文件名的路径名。例如:
File file = new File("D:/test.txt");
2.File(String parent,String child):该构造方法根据定义的父路径和子路径字符串(包含文件名)创建一个新的File对象,语法如下:
new File(String parent,String child)
·parent:父路径字符串,如D:/或D:/doc
·child:子路径字符串,如letter.txt
3.File(File f,String child):该构造方法根据f抽象路径名和child路径名字符串创建一个新File实例。语法如下:
new File(File f,String child)
·f:父路径对象,如D:/doc/
·child:子路径字符串,如letter.txt
注意:如果使用File类创建文件对象后,如果该目录中没有此文件,会自动调用creatNewFile()方法创建一个文件,如果存在,可通过文件对象的delete()方法将其删除
file类提供了很多方法获取文件本身的信息
import java.io.File;
public class FileDemo{
public static void main(String[] args){
File file = new File("D:\\word.txt"); //创建文件对象
if(file.exists()){ //如果文件存在
String name = file.getName();//获取文件名称
long length = file.length(); //获取文件长度
boolean hidden = file.isHidder();//判断文件是否是隐藏文件
System.out.println("文件名称是:"+name);
System.out.println("文件长度:"+length);
System.out.println("该文件是隐藏文件吗:"+hidden);
}
else{
System.out.println("文件不存在");
}
}
}
程序运行期间,大部分数据都在内存中进行操作,当程序结束或者关闭时,这些数据将消失。如果需要将数据永久保存,可使用文件输入/输出流与指定的文件建立连接,将需要的数据永久保存到文件中。
FileInputStream类与FileOutputStream类都用来操作磁盘文件。
如果用户的文件读取需求比较简单,则可以使用FileInputStream类,该类继承自InputStream类。
FileOutStream类与FileInputStream类对应,提供了基本的文件写入能力。
FileInputStream类常用的构造方法如下:
FileInputStream(String name):用给定的文件名name创建一个FileInputStream对象
FileInputStream(File file):用File对象创建FileInputStream对象。允许在把文件连接输入流之前对文件做进一步分析。
FileOutputStream类有与FileInputStream类相同的参数构造方法,创建一个FileOutputStream对象时,可以指定不存在的文件名,但此文件不能是一个已被其他程序打开的文件,下面实例就是使用FileInputStream类与FileOutputStream类实现文件的读取与写入功能。
/*向文本文件中写入内容,再读取出来。
使用FileOutputStream类和FileInputStream类,向D盘根目录的word.txt文件中写入一句话,然后再读取出来输出在控制台上*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStreaml
import java.io.IOException;
public class FileStreamDemo{
public static void main(String[] args){
File file = new File("D:\\word.txt");
try{
FileOutputStream out = new FileOutputStream(file); //创建输出流
byte buy[] = "我有一个文件".getBytes(); //写入内容的字节数组
out.wirte(buy);
out.close();
}catch(IOException e){
e.printStackTrace();
}
try{
FileInputStream in = new FileInputStream(file); //创建输入流
byte byt[] = new byte[1024]; //缓存字节数组
int len = in.read(byt); //将文件信息读入缓存数组中
System.out.println("文件中的信息是:"+new String(byt,0,len)); //将字节转为字符串输出
in.close(); //关闭流
}catch(IOException e){
e.printStackTrace();
}
}
}
/*程序运行后会在D盘创建一个word.txt文件并且写入一行文字,并且会在控制台输出“我有一个文件”的信息*/
因为汉字在文件中占两个字节,使用上面的两个字节流类可能会造成乱码,所以使用FileReader和FileWriter。
FileReader类顺序读取文件,只要不关闭流,每次调用read()方法就顺序的读取源中其余的内容,知道源的末尾或流关闭。
/*使用字符流读写文本文件:使用FileWriter类和FileReader类,向D盘根目录的word.txt文件中写一句话,再输出到控制台上*/
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public calss FileReaderDemo{
public static void main(String[] args){
File file = new File("D:\\\word.txt");//创建文件对象
try{
FileWriter fw = new FileWriter(file); //创建字符输出流
String word = "这是另外一个文件"; //写入的字符串
fw.write(word); //将字符串写入文件中
fw.close();
}catch(IOException e){
e.printStackTrace();
}
try{
FileReader fr = new FileReader(file);
char ch[] = new char[1024]; //缓存字符数组
int len = fr.read(ch); //将文件中的字符读入缓存数组中
System.out.println("文件中的信息是:"+new String(ch,0,len)); //将字符转为字符串输出
fr.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
缓存是I/O的一种性能优化。缓存流为I/O流增加了内存缓存区,使得在流上执行skip(),mark(),reset()方法都成为可能
这两个类可以对所有的InputStrea类进行带缓存区的包装以达到性能的优化,其有两个构造方法:
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
第一种形式的构造方法创建了一个有32个字节的缓存区;
第二个构造方法按照指定的大小来创建缓存区。
一个最优的缓存区的大小,取决于它所在的操作系统、可用的内存空间以及机器配置。从构造方法可以看出,BufferedInputStream对象位于InputStream类对象之后
使用BufferedOutputStream类输出信息和仅用OutputStream类输出信息完全一样,只不过BufferedPutputStream有一个flush()方法来将缓存区的数据强制输出完。它有两个构造方法:
BufferedOutputStream(OutputStream in):创建一个有32个字节的缓存区
BufferedPutputStream(OutputStream in,int size):以指定大小来创建缓存区
注意:flush()方法就是用于即使在缓存区没有慢的情况下,也将缓存区的内容强制写入外设,习惯上成这个过程为刷新。flush()方法只对使用缓存区的OutputStream类的子类有效,当调用close()方法时,系统在关闭流之前,也会将缓存区的信息刷新到磁盘文件中。
BufferedReader类与BufferedWriter类分别继承Reader类与Writer类。这两个类同样具有内部缓存机制,并能够以行为单位进行输出/输入、
BufferedReader类常用的方法如下:
read():读取单个字符
readLine():读取一个文本行,并将其返回为字符串。若无数据刻度,则返回null
BufferedWriter类中的方法都返回void,常用的如下:
flush():刷新该流的缓存
newLine():写入一个行分隔符
在使用BufferedWriter类的Writer()方法时,数据并没有立即被写入输出流,而是首先进入缓存区中,如果想立刻将缓存区中的数据写入输出流,一定要调用flush()方法。
/*使用缓冲流读写文本文件、使用BufferedReader和BufferedWriter类,向D盘根目录的word.txt文件中写入多行内容,然后再读取出来输出在控制台上*/
public class BufferedDemo{
public static void main(String[] args){
String content[] = {"你好","佛i啊很多事","时时发啊哈东"};
File file = new File("D:\\word.txt");
try{
FileWriter fw = new FileWriter(file); //文件字符输出流
BufferedWriter bw = new BufferedWriter(fw); //缓冲输出流
for(int k=0;k<content.length;k++){
bw.wirter(content[k]); //写入字符串
bw.newLine(); //写入一个换行符
}
bw.close();
fw.close();
}catch(IOException e){
e.printStackTrace();
}
try{
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String tmp = null;//作为缓冲的临时字符串
int i =1; //行数
while((tmp = br.readLine()!=null)){
System.out.println("第"+i+"行:"+tmp);
i++;
}
br.close();
fr.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
DataInputStream类与DataOutputStream类允许程序以与机器无关的方式从底层输入流中读取基本的Java数据类型。
也就是说,当读取一个数据时,不必再关心这个数值是哪种字节。DataInputStream类与DataOutputStream类的构造方法如下:
DataInputStream(InputStream in):使用指定的基础InputStream对象创建DataInputStream对象。
DataOutputStream(OutputStream out):创建一个新的数据输出流,将数据写入指定基础输出流。
DataOutputStream类提供了将字符串,double数据、int数据、boolean数据写入文件的方法。其中将字符串写入文件的方法有3中,分别是:
writeBytes(String s)、writeChars(String s)、writeUTF(String s)
因为Java中的字符是Unicode编码,是双字节的,wirteBytes()方法之色将字符串中的每一个字符的低字节内容写入目标设备中。
writerChars()方法将字符串中的每一个字符的两个字节的内容都写到目标设备中;
writeUTF()方法将字符串按照UFT编码后的字节长度写入目标设备,然后才是每一个字节的UTF编码。
DataInputStream类只提供了一个readUTF()方法返回字符串。因为要在一个连续的字节流读取一个字符串,如果没有特殊的标记作为一个字符串的结尾,并且不知道字符串的长度,就无法知道读取到什么位置才是这个字符串的结束。DataOutputStream类中只有writeUTF()方法向目标设备中写入字符串的长度,所以也能准确的读回写入字符串
/*使用数据流读写文本文件:分别通过DataOutputStream类的writeUTF()、writeDouble()、writeInt()、writeBoolean()方法向指定的word.txt文件中写入不同类型的数据,并且通过DataInputStream类的相应方法将写入的数据输出到控制台上。*/
import java.io.*;
public class FataSteamDemo{
File file = new File("D:\\word.txt");
try{
//创建FileOutputStream对象,指定要向其中写入数据的文件
FileOutputStream fos = new FileOutputStream();
//创建DataOutputStream对象,用来向文件
DataOutputStream dos = new DataOutputStream(fos);
dos.writeUTF("使用writeUTF方法写入数据");//将字符串写入文件
dos.writeDouble(19.8);
dos.writeInt(192);
dos.writeBoolean(ture);
dos.close();
fos.close();
//创建FileInputStream对象,指定要从中读取数据的文件
FileInputStream fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fis);
System.out.println("readUTF方法读取数据:"+dis.readUTF()); //读取字符串
System.out.println("readDouble方法读取数据:"+dis.readDouble());
System.out.println("readInt方法读取数据:"+dis.readInt());
System.out.println("readBoolean方法读取数据:"+dis.readBoolean());
dis.close();
fis.close();
}catch(IOException e){
e.printStackTrace();
}
}