Java I/O流复习(一)—File类、字节流、字节缓冲流

来源:互联网 发布:黑马程序员训练营 编辑:程序博客网 时间:2024/06/05 05:25

Java I/O流复习(一)—File类、字节流、字节缓冲流

1. File类

1.1 File类作用

  1. 文件可认为是相关记录或放在一起的数据的集合。文件一般存放在存储介质上:硬盘、u盘、光盘、软盘、云盘等。
  2. java.io.File 类是专门对文件进行操作的类。(只能对文件本身进行操作,不能对文件内容操作)
  3. File类是“文件和目录路径名的抽象表示”。 而不是指文件的内容(IO)。路径就是字符串
  4. File类定义了一些与平台无关的方法操作,如:创建、删除文件和重命名等。
  5. Java中目录被看成是一个特殊的文件。 File.listFiles()方法可以返回目录中所有的子目录和文件。
  6. 在unix下路径分隔符为(/),而在windos中则是为(\),在java中可以正确的处理不同系统中的分隔符。注意:从1.5开始在java中可以统一使用(/)来作为路径分隔符。

1.2 File类的构造方法

  1. public File(String pathname); 以pathname为路径创建File对象,如果pathname是相对路径,则是相对于Java的系统属性user.dir中的路径。(对eclipse创建的java工程来说,就是该工程的根目录。)

  2. public File(File dir,String name);

    根据f 抽象路径名和 child 路径名字符串创建一个新 File 实例。

1.3 File类文件属性

1.3.1 属性:

  1. public static final String separator 分隔符 存储了当前系统的名称分隔符,在 UNIX 和Mac系统上,此字段的值为 ‘/’;在 Windows 系统上,它为 ‘\’;为了程序的跨平台特性,文件的路径应该用这个属性值来代表。
  2. public static final char pathSeparator 存储了当前系统默认路径分割符号,在 UNIX 和Mac系统上,此字段的值为’:’,Windows系统是’;’。

1.4 使用File类对文件进行访问

方法名 描述 public boolean canRead() 是否可读 public boolean canWrite() 是否可写 public boolean exists() 文件或目录是否存在,先判断 public boolean isDirectory() 是否是目录(文件夹)非目录就是文件 public boolean isFile() 是否是文件(非目录) public boolean isHidden() 是否是隐藏文件 public long lastModified() 最后一次修改的时间,需要转换 public long length() 返回文件大小,以字节为单位 public String getName() 返回文件的名字(不包含路径) public String getPath() 返回创建File时使用指定的路径;[^提示] public String getAbsolutePath() 返回此File对象的绝对路径名 public File getAbsoluteFile() 返回该文件的绝对路径的文件对象。 public String getParent() 返回该文件所在的目录的路径。一般转化为绝对路径对象再使用 public File getParentFile() 返回该文件所在的目录File对象。
[^提示]: 创建文件的时候是相对路径就返回相对路径,是绝对路径就返回绝对路径。
Scanner sc = new Scanner(System.in);        while (true) {            System.out.println("请输入一个路径");            String next = sc.next();            File file = new File(next);            if (file.exists()) {                String name = file.getName();                String absolutePath = file.getAbsolutePath();                File parentFile = file.getParentFile();                parentFile.getParent();                boolean canRead = file.canRead();                boolean canWrite = file.canWrite();                long lastModified = file.lastModified();                Date date = new Date(lastModified);                System.out.println("文件名"+" "+"文件的路径"+" "+"文件目录"+" "+"是否可读"+" "+"最后一次修改时间");                System.out.println(name+" "+absolutePath+" "+parentFile+" "+canRead+" "+date.toString());                break;            }else {                System.out.println("你输入的文件不存在");            }        }

1.5 使用File类对文件进行操作

方法名 描述 public boolean createNewFile() 当文件不存在是,则创建一个空文件(非目录)确保文件所在目录存在,否则会抛IO异常 public boolean delete() 删除文件。如果是目录必须是空目录才能删除,只删除最后一级目录 public boolean mkdir() 文件夹的创建。创建此抽象路径名指定(最后一级)的目录,确保父类目录存在 public boolean mkdirs() 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录 public boolean renameTo(File dest) 重新命名此抽象路径名表示的文件。如果是文件路径是不一样的话,就相当于剪切的功能。如果一样的话,也可以看成是重命名

1.6 使用File类浏览目录中的文件和子目录

方法名 描述 public String[] list() 返回此目录中的文件名和目录名的数组,遍历输出 public File[] listFiles() 返回此目录中的文件和目录的File实例数组,文件路径。如果不是目录就输出为空 public File[] listFiles(FileFilter filter) 返回此目录中满足指定过滤器的文件和目录。new FileFilter 匿名内部类

课堂练习:使用 递归算法 打印出目录(文件夹)中所有文件与目录(包括目录内部的文件和目录)。

``java
private static void listChilds(File f){
if (f==null)
return;
System.out.println(f.getPath());
if (f.isFile())
return;
File[] files = f.listFiles();
for (File file : files)
listChilds(file);
}
public class Main5 {
private static File file = new File(“F:\\java和HTML等”);
public static void findFile(File file) {
if (file.isDirectory()) {
File[] listFiles = file.listFiles();
if (listFiles==null||listFiles.length==0) {
return;
}else {
for (File f : listFiles) {
System.out.println(f);
if (f.isDirectory()) {
findFile(f);//递归
}
}
}
}
}
public static void main(String[] args) {
findFile(file);
}
}

2. IO概念和种类:

2.1 什么是IO流?

IO指的是 Input/Output,IO流:输入输出流。 统称为数据流。(IO Stream)

在Java程序中,对于数据的输入 / 输出操作以流的方式进行;流是从起源到接收的有序数据。JDK提供了各种各样的Stream 类,用以获取不同种类的数据;

IO流的作用就是对文件数据的读(输入)和写(输出)。

2.2 流的作用和原理?

3. IO流的种类:

3.1 输入流、输出流

  1. 输入流:程序可以从中读取数据的流(流入程序的流)
  2. 输出流:程序能向其中写入数据的流 (从程序流出的流)

3.2 字节流、字符流

  1. 字节流:以字节为单位传输数据的流
  2. 字符流:以字符为单位传输数据的流

3.3 节点流、处理流

  1. 节点流:用于直接操作目标设备的流
  2. 处理流:是对一个已存在的流的连接和封装,通过对数据的处理为程序提供更为强大、灵活的读写功能。

3.4 IO流的分类图:

4. 字节输入流:

4.1 InputStream类的常用方法

  1. available() 方法,获取与之关联的文件剩余可读的字节数。
  2. int read() 方法,读取输入流。读取输入流的下一个字节,返回一个0-255之间的int类型整数。如果到达流的末端,返回-1。

  3. int read(byte[] b) 方法,读取输入流。读取多个字节,存入字节数组b,返回实际读入的字节数。如果到达流的末端,返回-1。

  4. int read (byte[] b, int off, int len); 方法,读取输入流。每次读取len个字节,存入字节数组b,从off下标开始存储。如果到达流的末端,返回-1。

  5. close() 方法,关闭当前流,释放与该流相关的资源,防止资源泄露。在带资源的try语句中将被自动调用。关闭流之后还试图读取字节,会出现IOException异常。

4.2 InputStream类的子类:文件输入流FileInputStream

FileInputStream 用于读取本地文件中的字节数据,继承自InputStream类

4.2.1 FileInputStream构造方法和常用方法

4.2.1.1构造方法
  1. FileInputStream(File file); 通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
  2. FileInputStream(String name); 通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的路径名 name 指定。
4.2.1.2 常用方法
  1. read() 方法,读取输入流。读取输入流的下一个字节,返回一个0-255之间的int类型整数。如果到达流的末端,返回-1。

    is = new FileInputStream("test.txt");  int i; while ((i = is.read()) != -1) {   System.out.println("out: " + (char)i);  } 
  2. read(byte[] b) 方法,读取输入流。读取多个字节,存入字节数组b,返回实际读入的字节数。

    InputStream is = null;  byte[] buffer = new byte[4];//每次读取4个字节try {   is = new FileInputStream("test.txt");     is.read(buffer);     System.out.println("available: " + is.available());//观察在读取的过程中,available 值。   for (byte b : buffer) {         System.out.println((char)b);     }}...
  3. read (byte[] b, int off, int len); 方法,读取输入流。每次读取len个字节,存入字节数组b,从off下标开始存储。

    ~~~java

    File file = new File("helloworld.txt");try(InputStream is = new FileInputStream(file);){    byte[] b = new byte[10];    while (true) {        int read = is.read(b, 0, 10);        // 当每次读取的个数刚好是 byte[] 的长度,则可以这么简写:        // int read = is.read(b);        if (read == -1) {            break;        }        String string = new String(b, 0, read);        System.out.print(string);    }} catch (FileNotFoundException e) {    e.printStackTrace();} catch (IOException e) {    e.printStackTrace();}

    ~~~

  4. close() 方法,关闭当前流,释放与该流相关的资源,防止资源泄露。在带资源的try语句中将被自动调用。关闭流之后还试图读取字节,会出现IOException异常。

  5. skip(long n) 方法,跳过(放弃)当前流的n个字节,返回实际跳过的字节数。(了解)

5. 字节输出流:

5.1 OutputStream类的常用方法

  1. write (int b); 将指定的字节写入此输出流。
  2. write(byte[] byte); 将 b.length 个字节从指定的 byte 数组写入此输出流。
  3. write(byte[] byte, int off, int len); 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
  4. flush(); 用于清空缓存里的数据,并通知底层去进行实际的写操作。(强制把缓存区里面的数据写入到文件)
  5. close();关闭当前流,释放与该流相关的资源。

5.2 OuputStream类的子类:文件输出类FileOutputStream

提供了文件的基本写入能力,继承自 OuputStream类

注意:

  1. 如果进行写操作的文件不存在,则自动创建该文件。
  2. 如果文件所在的路径也不存在则报错。

5.2.1 FileOutputStream构造方法和常用方法

课堂练习一:String content = “拉萨扩大解放了as建立地方看见拉萨的肌肤绿卡时间的分绿卡时间的分利咔”;

写一个方法,接收一个字符串。将该字符串写入到File(路径自己指定)中。返回boolean

课堂练习二:编写一个方法,接受第一个FIle fromFile,接受第二参数 File toFile;

将 fromFIle 文件内容复制到 toFile 中。

一边读,一边写

5.2.1.1 构造方法
  1. public FileOutputStream(String name); 通过打开一个到实际文件的连接来创建一个FileOutputStream,该文件通过文件系统中的路径名 name 指定。
  2. public FileOutputStream(String name,boolean append);通过打开一个到实际文件的连接来创建一个FileOutputStream,该文件通过文件系统中的路径名 name 指定。如果第二个参数为true,则将字节写入文件末尾处,而不是写入文件开始处。
  3. public FileOutputStream(File file):通过打开一个到实际文件的连接来创建一个FileOutputStream,该文件通过文件系统中的 File 对象 file 指定。
  4. public FileOutputStream(File file,boolean append);通过打开一个到实际文件的连接来创建一个FileOutputStream,该文件通过文件系统中的 File 对象 file 指定。如果第二个参数为true,则将字节写入文件末尾处,而不是写入文件开始处。
5.2.1.1 常用方法
  1. write (int b); 将指定的字节写入此输出流。

    try {File file = new File("test.txt");OutputStream fos = new FileOutputStream(file);byte b = 'a';fos.write(b);fos.flush();fos.close();}...

    结果:

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

    try {File file = new File("test.txt");OutputStream fos = new FileOutputStream(file);byte b[]= "abcdefg".getBytes();fos.write(b);fos.flush();fos.close();}...

    结果:

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

    try {File file = new File("test.txt");OutputStream fos = new FileOutputStream(file);byte b[]= "abcdefg".getBytes();fos.write(b,1,3);fos.flush();fos.close();}...

    结果:

  4. flush(); 用于清空缓存里的数据,并通知底层去进行实际的写操作。(强制把缓存区里面的数据写入到文件)

  5. close();关闭当前流,释放与该流相关的资源。

6 字节缓冲流

BufferedInputStream与BufferedOutputStream分别是FilterInputStream类和FilterOutputStream类的子类,实现了装饰设计模式。提高了读写性能。

6.1字节输入缓冲流 BufferedInputStream

BufferedInputStream是带缓冲区的输入流,默认缓冲区大小是8Kb,能够减少访问磁盘的次数,提高文件读取性能;

使用方式:

try {    File file = new File("test.txt");    InputStream fos = new FileInputStream(file);    BufferedInputStream bis = new BufferedInputStream(fos,2*1024);//2*1024设置需要的缓冲区大小    byte b[] =new byte[1024];    while (bis.read(b)!=-1) {        for (byte c : b) {            System.out.println((char)c);        }    }    bis.close();}

6.2 字节输出缓冲流 BufferedOutputStream

BufferedOutputStream是带缓冲区的输出流,能够提高文件的写入效率。

使用方式:

try {    File file = new File("test.txt");    OutputStream fos = new FileOutputStream(file);    BufferedOutputStream bos =new BufferedOutputStream(fos,2*1024);//2*1024设置需要的缓冲区大小    byte b = "a";    bos.write(b);    bos.flush();//带有缓冲区,所以必须刷新。    bos.close();}...

6.3 字节缓冲输入流特有的方法(了解)

  1. (了解)mark(int readlimit) 方法(只有BufferedInputStream才支持),在流的当前位置做个标记,参数readLimit指定这个标记的“有效期”,如果从标记处开始往后,已经获取或者跳过了readLimit个字节,那么这个标记失效,不允许再重新回到这个位置(通过reset方法)。也就是你想回头不能走得太远呀,浪子回头不一定是岸了,跳过(获取)了太多字节,标记就不再等你啦。多次调用这个方法,前面的标记会被覆盖。

    如果我们在 M 处做标记,readLimit为绿色部分,当流的指针在 A 处的时候,这个标记依然有效,可是一旦指针跑到 B 处,标记就失效了。

  2. (了解)reset() 方法(只有BufferedInputStream才支持),用于重定位到最近的标记。如果在这之前mark方法从来没被调用,或者标记已经无效,会抛出IOException。如果没有抛出这个异常,将当前位置重新定位到最近的标记位置。

    InputStream is = null;         try {           is = new BufferedInputStream(new FileInputStream("test.txt"));             is.mark(4);             is.skip(2);             is.reset();             System.out.println((char)is.read());         } finally {             if (is != null) {                 is.close();             }         }}

课后练习

  1. 写一个方法,接收一个参数String text,接受第二个参数File saveFile。将text字符串内容写入到saveFile中。返回boolean
public class SaveFile {    public static boolean Read(String text, File saveFile) {        if (text == null || "".equals(text) || saveFile == null) {            return false;        }        byte[] bytes = text.getBytes();        // File file = new File("saveFile");        try (FileOutputStream fileOutputStream = new FileOutputStream(saveFile);) {            fileOutputStream.write(bytes, 0, text.length());            return false;        } catch (FileNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return false;    }    public static void main(String[] args) {        boolean read = Read("abcdefg", new File("a.txt"));        System.out.println(read);    }

2 编写一个方法,接受第一个参数FIle fromFile,接受第二参数 File toFile;将 fromFIle 文件内容复制到 toFile 中。

public class Main {    public static void copyFile(File formFile, File toFile) {        if (formFile.exists()) {            try (FileInputStream fileInputStream = new FileInputStream(formFile);                    FileOutputStream fileOutputStream = new FileOutputStream(toFile);) {                byte[] b = new byte[1024];//以这个大小来读取                while (true) {                    int read = fileInputStream.read(b);//                  fileInputStream.read(b,0,b.length);                    if (read == -1) {                        return;                    }                    fileOutputStream.write(b,0, read);//指定数组b 从0开始到read的长度                }            } catch (FileNotFoundException e) {                // TODO Auto-generated catch block                e.printStackTrace();            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }    public static void main(String[] args) {        copyFile(new File("a.txt"), new File("c.txt"));    }

3.从键盘输入一个关键字,在 D:盘查找文件,如果文件名中包含该关键字,则输出这个文件的绝对路径,如果都没有找到,则输出找不到相关信息。

public class Find {    public static int  findFile(File file,String keyName) {        int i=0;        File[] listFiles = file.listFiles();//      String[] str = file.list();        if (listFiles.length == 0 || listFiles == null) {            return -1 ;        }        for (File f : listFiles) {            if (f.isDirectory()) {                try {                    int findFile = findFile(f,keyName);                    i+=findFile;                } catch (Exception e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }            if (f.getName().contains(keyName)) {//              System.out.println(f.getName());                System.out.println(f.getAbsolutePath());            }         }        return i;    }    public static void main(String[] args) {        File file = new File("D:");        Scanner scanner = new Scanner(System.in);        System.out.println("请输入关键字");        String keyName = scanner.next();        int findFile = findFile(file,keyName);        if (findFile<=0) {            System.out.println("找不到");        }    }

4.将JAVA LOGO 图片 通过鼠标右键保存到 D盘(D:\cat.jpg)中,然后使用java程序 实现:

  1. 剪切该图片到E盘(E:\cat.jpg)中。
  2. 再从E盘把该图片的 “一半” 复制一份到D盘中。

        File file1 = new File("Letter/1.jpg");        File file2 = new File("Love/1.jpg");        try (FileInputStream fis = new FileInputStream(file2); FileOutputStream fos = new FileOutputStream(file1);) {            byte[] b = new byte[1024];            int a = 0;            while (true) {                int read = fis.read(b);                if (read == -1) {                    return;                }                fos.write(b, 0, read);                a += read;                if (a >= file2.length() / 2) {// 只复制一半                    break;                }            }            System.out.println("复制结束");        } catch (FileNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }
  1. 在D盘指定一个目录(要求目录下面有子目录和文件(图片,文档等),子目录里面也放一些目录和文件,以此类推,可以多放几层)。然后,复制该D盘该目录下所有文件(含目录)到 E盘指定目录下 。

    即:将一个目录内的所有文件(含目录) 全部复制到 另一个目录下!

public class copyAll {    public static void copyDirectory(File srcDir,File destDir) {        File[] listFiles = srcDir.listFiles();        if (listFiles==null) {            return;        }        for (File file : listFiles) {            File srcFile = file;            File destFile = new File(destDir, file.getName());//得到目标文件的路径描述            if (file.isDirectory()) {                System.out.println("正在创建目录:" + destFile);                destFile.mkdir();// 在 destDir 创建对应的目标目录                copyDirectory(srcFile, destFile);//递归,得到里面的文件            }else {                //复制文件                System.out.println("正在copy文件:从" + srcFile + "到" + destFile);                Main.copyFile(srcDir, destDir);//复制            }        }    }    public static void main(String[] args) {        File srcDir = new File("");        File destDir = new File("");        copyDirectory(srcDir, destDir);    }
原创粉丝点击