Java IO流总结

说在前面的话:IO流是用来操作File的,因此先说一下File

一、File类:文件和目录路径名的抽象表示。

File 类只能操作文件的属性,文件的内容是不能操作的。

1.作用:用于对磁盘文件操作。删除、创建等。

2.三种构造函数:

①直接传入一个路径,拿到一个文件或者文件夹

File file1 = new File("F:\\test");

②第一个参数传入父路径、第二个参数传入子路径或者文件

File file2 = new File("F:\\test", "test.txt");

③第一个参数传入file文件、第二个参数传入子路径或者文件

File file3 = new File(file1, "test.txt");

3.路径的表示:

文件夹的分割可以使用"/",通常用在Linux系统,windows也可以用

"\\"通常用在Windows系统,注意'\'需要进行转义

4.需要注意的几个常用方法

①:.delete()  删除文件 删除成功true 删除失败false;若删除文件夹,此文件夹不能有子内容

②:createNewFile() 创建一个新文件创建失败返回false 需要指定的新文件名由调用他的文件对象来决定,而不是传参数,没有才能创建成功需要捕获异常

③:mkdir:只能创建一层目录,如果倒数第二层目录也不存在,创建失败;mkdirs:可以创建多层目录,无论有几层不存在都可以依次创建

④:list()返回当前目录中的所有文件和文件夹的名字,返回值类型为String[]

String[] list = file1.list();
for (String string : list) {
    System.out.println(string);
}

可以再参数中传入FilenameFilter接口的实现类对象,表示对列表中的所有文件进行遍历过滤
需要重写accept方法,如果保留当前文件return true,如果不要当前文件return false

String[] list1 = file1.list(new FilenameFilter()) {
    @Override
    public boolean accept(File dir, String name) {
    // dir:表示包含当前文件夹的父路径
    // name:表示当前文件名
          if (name.endsWith(".txt")) {
              return true;
          }else {
              return false;
          }
    }
});
for (String string1 : list1) {
    System.out.println(string1);
}            

⑤:返回当前目录中的所有文件和文件夹的路径,返回值类型为File[]

File[] files = file1.listFiles();
for (File file : files) {
    System.out.println(file+"----"+file.getName());
}

同样可以对文件进行过滤
①与list()一样使用 FilenameFilter()进行过滤
②使用FileFilter接口的实现类进行过滤

File[] files1 = file1.listFiles(new FileFilter() {
        @Override
        public boolean accept(File pathname) {
        // TODO Auto-generated method stub
                if (pathname.getName().endsWith(".txt")) {
            return true;
          }else {
            return false;
          }
    }
});
for (File fileN : files1) {
    System.out.println(fileN+"----"+fileN.getName());
}    

 

二、IO流的分类:

1.根据流的方向:输入流和输出流

2.根据读取文字的大小:字节流和字符流(字节流按照字节读取,读取中文时容易乱码;字符流按照字符读取,通常用于读取中文

3.根据读取的方式:节点流和缓存流

三、字节流java.io.InputStream java,io,OutputStream

1.FileInputStream类

①该流继承于InputStream用于从文件读取数据,它的对象可以用关键字 new 来创建。
②构造方法
可以使用字符串类型的文件名来创建一个输入流对象来读取文件:
FileInputStream f = new FileInputStream("C:/java/hello");
也可以使用一个文件对象来创建一个输入流对象来读取文件。我们首先得使用 File() 方法来创建一个文件对象:
File f = new File("C:/java/hello");
FileInputStream out = new FileInputStream(f);
③常用方法
available():返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取的字节数。返回一个整数值。
read(int r):这个方法从 InputStream 对象读取指定字节的数据。返回为整数值。返回下一字节数据,如果已经到结尾则返回-1。
read(byte[] b): 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中
close():关闭此文件输入流并释放与此流有关的所有系统资源。抛出IOException异常

2.FileOutStream

①该类用来创建一个文件并向文件中写数据。
如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。
②构造方法
使用字符串类型的文件名来创建一个输出流对象:
OutputStream f = new FileOutputStream("C:/java/hello");
也可以使用一个文件对象来创建一个输出流来写文件。我们首先得使用File()方法来创建一个文件对象:
File f = new File("C:/java/hello");
OutputStream f = new FileOutputStream(f);
③常用方法
write(int b): 将指定字节写入此文件输出流。
write(byte[] b): 将 b.length 个字节从指定 byte 数组写入此文件输出流中。

3、BufferedInputStream、BufferedOutputStream

继承自FilterInputStream、FilterOutputStream

1.作用:在基本流的基础上进行包装,读取或者写入文件时,将通过缓存进行。
即,先将内容写入到缓存区,缓存区满以后再进行读取或写入操作
可以大大减小文件的操作次数,提高写入效率
2.缓存流的使用:
在基础流的基础上进行包装:
new BufferedInputStream(new FileInputStream("F:\\test\\test.txt"));
这种写法我们称为IO链,IO关闭时需要关闭最外层流,内层流将自动关闭
3.使用BufferedOutStream,在关闭时通常调用flush()方法;
表示关闭前将缓存区刷新,将缓存区剩余未满的内容写入文件;
实际上close()方法自带刷新,这样做是一种习惯。

4.DataInputStream和DataOutputStream

1. 分别继承自FilterInputStream和FilterOutStream
2.特殊:
①采用二进制对文件进行读写操作
②与基本流相比,可以直接读写Java中的基本数据类型

3.另外如果操作的一个文件是一个二进制文件,需要使用DataInputStream替代FileInputStream
不代替也可以读)同样,Data系列的流也有read和write方法与基本流操作相同

4.用Data流写入的文件,只能用Data流读,不能使用基本流读

5.与基本流相比几个特有方法
readUTF():首先读取两个字节,以 String 的形式返回此字符串
readInt():读取四个输入字节并返回一个 int 值
readDouble():读取八个输入字节并返回一个 double 值。
6.上面的方法,如果此流在读取所有字节之前到达末尾,则会抛出
java.io.EOFException异常;EOF:END OF FILE
https://www.cnblogs.com/yiwangzhibujian/p/7107084.html(详细解释了为啥会抛异常)

自己领会的解决方法 :

public class Demo04_DataINOUTStream2 {
    public static void main(String[] args) {
        DataInputStream dis = null;
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("F:\\test\\Demo02_IO.class");
            if (fis.available() != 0) {
                dis = new DataInputStream(fis);
            }else {
                System.out.println("文件已没有可读内容!");
            }
        try {
            while (true) {
                    System.out.println(dis.readInt());
            }} catch (EOFException e) {
                System.out.println("一定会抛出这条异常,表示目标文件已读完,没有可以读的内容了,我们不做任何处理就好了!");
            }
        
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            try {
                dis.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}


第一篇:
https://www.cnblogs.com/ouhaitao/p/7683568.html

 1     ObjectInputStream ois = null;
 2     FileInputStream fis=new FileInputStream(filePath);
 3     //当文件中的有内容时
 4     if(fis.available()!=0)
 5         ois = new ObjectInputStream(fis);
 6     else{
 7         System.out.println("文件为空!");
 8         return ;
 9     }
10     try{
11         while(true)                            
12           System.out.println((Student)ois.readObject());
13     }catch(EOFException e){
14     }

原理就是:先用基本流判断文件是不是还有可读内容,只有在判断有可读内容是才实例化一个
高级流对象,这事再去读,当读完又会报错这时只需手动在read...()方法捕捉一下EOFExceptiion这个异常,不处理就好了。

第二篇:
https://blog.csdn.net/ouyang_peng/article/details/46448877

5.ObjectInputStream/ObjectOutputStream

1.继承java.io.InputStream和java.io.OutputStream
2.与基本流相同,可以直接使用read write 方法
3.可以使用Data流的方法
4.特殊方法:readObject()和writeObject()
对象的序列化和反序列化
1.对象的序列化:将程序中的对象,持久化的保存在文件中的过程ObjectOutStream
2.对象的反序列化:将文件中保存的对象,重新读取到程序中的过程。ObjectInputStream
如果要对实体类对象进行序列化,实体类需要实现Serializable(可序列化)接口,
添加一个序列化版本号private static final long serialVersionUID = 4992258028211704199L;
若果不添加序列化版本号,当序列化一个对象后,如果实体类属性有增删,再进行反序列化时会造成错误
java.io.InvalidClassException,因为系统认为这已经不是同一个类

注意虽然叫对象的序列化,但是使用这readObject()和writeObject()这两个方法可以直接传入一个对象集合

readObject()和writeObject()方法也存在EOFException这个异常,解决办法同
DataInputStream和DataOutputStream中的readInt()等方法
http://note.youdao.com/noteshare?id=506c27323c6b8a0b6cf3d1f7f97639eb&sub=C87F25CC0E7342558556C89380D7E2AF

四、字符流

1.Reader、Writer

1.在处理数据单元时,以一个字符作为单位,而字节流是以一个字节作为单位
2.字符的基类:Reader、Writer(抽象类)
FileReader、FileWrite是直接继承自抽象类的两个字符基本流
3、FileReader、FileWrite在读写文件的时候,只能使用系统默认编码格式;
无法指定编码,如果文件格式与系统默认格式不一致,那使用这两个方法读写将造成中文乱码
4.虽然算不上缓存流,但是不 flush()会导致写不进去,读不出来

2.InputStreamReader、OutputStreamWriter

1.将字节流转为字符流,同时支持自定义读写的编码格式
2.常见的编码格式
ASCLL:美国标准消息码;
ISO8859-1:西欧洲码;
ANSI编码,可以分为很多种:
简体中文:GB2312、GBK
繁体中文:big-5
日文中文...
Unicode编码:国际标准码,兼容绝大多数国家的编码格式
可以分为:UTF-6、UTF-8、UTF-16

下面两行把一个utf-8格式的字符串先分解成一个字符数组b,然后使用new String(b,"GBK")生成一个新的GBK格式的字符串s1
String s = "中国fdhasfdj";
byte[] b = s.getBytes("UTF-8");
String s1 = new String(b,"GBK");

3.BufferedReader、BufferedWriter

BufferedWriter 和 BufferedReader 为带有默认缓冲的字符输出输入流,因为有缓冲区所以效率比没有缓冲区的很高。

1、BufferedWriter 类
构造方法:bufferedWriter bf = new bufferedWriter(Writer out );

主要方法:void write(char ch);//写入单个字符。

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

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

void newLine()//写入一个行分隔符。

void flush();//刷新该流中的缓冲。将缓冲数据写到目的文件中去。

void close();//关闭此流,再关闭前会先刷新他。

2、BufferedReader类。
构造方法:BufferedReader br = new BufferReader(Reader in);

主要方法:int read();//读取单个字符。

int read(char[] cbuf,int off,int len);//将字符读入到数组的某一部分。返回读取的字符数。达到尾部 ,返回-1。

String readLine(); //读取一个文本行。

void close(); //关闭该流。并释放与该流相关的所有资源。

 

posted on 2018-04-22 17:25  ★【金字塔】☆  阅读(215)  评论(0编辑  收藏  举报