Java Io 笔记总结

本文深入探讨了Java中的文件操作与流处理,详细介绍了File类的使用方法及特性,包括创建、检查、创建、删除文件和目录,以及过滤文件等功能。同时,文章还阐述了输入流和输出流的概念,字节流与字符流的区别,以及如何使用处理流简化文件读写操作。此外,还介绍了如何使用RandomAccessFile进行文件内容的快速访问和修改。最后,文章还涉及了序列化和反序列化的基本概念和实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.File类

java.io.File类用来操作文件和目录,比如:获取文件和目录路径,属性判断,新建文件或目录,查看子文件等。File类不能访问文件本身的内容,需使用I/O流处理。

通过构造函数(共有6个构造函数),创建一个File实例:

File file = new File(String pathname); // pathname为文件路径字符串
常用的File类方法:
boolean exists(); // 判断file实例所对应的文件和目录是否存在
boolean createNewFile(); // 新建文件
boolean delete(); // 删除文件
static File CreateTempFile(String prefix, String suffix); // 在默认的临时文件目录中创建临时的空文件,用prefix + 系统生成的随机数 + suffix作为文件名
static File CreateTempFile(String prefix, String suffix, File directory); // 同上,只是指定了生成临时文件所在的目录directory
void deleteOnExit(); // 删除钩子,jvm退出时,删除该文件或目录
boolean mkdir(); // 新建目录
String[] list(); // 返回所有的子文件和目录, 返回的是String[]
File[] listFiles(); // 返回所有的子文件和目录, 返回的是File[]
static File[] listRoots(); // 系统所有的根路径
String getPath(); // 路径名
String getAbsolutePath(); // 绝对路径名
boolean renameTo(File newName); //重命名
文件过滤器:

File类提供了3个方法用来文件过滤:

// @param filter A file filter
public File[] listFiles(FileFilter filter);
//  @param  filter: A filename filter
public File[] listFiles(FilenameFilter filter);
// @param  filter: A filename filter
public String[] list(FilenameFilter filter);

根据FileFilter,FilenameFilter接口accept()方法进行过滤,只有文件满足方法体返回true时,才返回该文件。

/**
 * A filter for abstract pathnames.
 *
 * <p> Instances of this interface may be passed to the <code>{@link
 * File#listFiles(java.io.FileFilter) listFiles(FileFilter)}</code> method
 * of the <code>{@link java.io.File}</code> class.
 *
 * @since 1.2
 */
public interface FileFilter {

    /**
     * Tests whether or not the specified abstract pathname should be
     * included in a pathname list.
     *
     * @param  pathname  The abstract pathname to be tested
     * @return  <code>true</code> if and only if <code>pathname</code>
     *          should be included
     */
    boolean accept(File pathname);

}
public interface FilenameFilter {
    /**
     * Tests if a specified file should be included in a file list.
     *
     * @param   dir    the directory in which the file was found.
     * @param   name   the name of the file.
     * @return  <code>true</code> if and only if the name should be
     * included in the file list; <code>false</code> otherwise.
     */
    boolean accept(File dir, String name);
}

实例:只输出指定目录中的文件,不包括子目录中的文件;输出/Users/hugang/Desktop/file目录下所有java文件

import java.io.File;
import java.io.FilenameFilter;

/*
 * <pre>
 *      文件过滤,找出指定目录下的java文件
 * </pre>
 * @author hugang
 */

public class FileFilterTest {
    public static void main(String[] args) {
        String pathName = "/Users/hugang/Desktop/file";
        File file = new File(pathName);

        String[] javaFile = file.list(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".java");
            }
        });

        for (String fileName : javaFile) {
            System.out.println(fileName);
        }

    }
}

实例:遍历目录下所有文件,包括子目录;如果需要找出目录下所有的java文件,包括所有的子目录,可以使用如下方法:

// 找到目录下所有java文件
    // 递归实现
    // 基线条件:是java文件直接添加到listFiles
    // 递归执行体:递归目录
    public List<File> getListJavaFiles(Object pathName) {
        File directory = null;
        if(pathName instanceof File){
            directory = (File) pathName;
        }else{
            directory = new File(pathName.toString());
        }

        List<File> listFiles = new ArrayList<File>();

        if (directory.isFile() && pathName.toString().endsWith(".java")) {
            listFiles.add(directory);
            return listFiles;
        } else if (directory.isDirectory()) {
            File[] subFileList = directory.listFiles();
            for (File subFile : subFileList) {
                listFiles.addAll(getListJavaFiles(subFile));
            }
        }
        return listFiles;
    }
文件路径:
System.getProperty("user.dir") // 项目所在的路径
System.getProperty("file.separator") // 根据系统,自动生成特定的文件分隔符,windows(‘\’),java中反斜线表示转义字符,需使用‘\\’, 比如:C:\\FILE; 直接使用斜线‘/’作为路径分隔符,表示与平台无关的路径分隔符。

2.IO流分类

输入流和输出流

以程序运行的内存为参照物,划分流的流向:

输入流:只能读取数据,InputStream 和 Reader 为抽象基类

输出流:只能写入数据,OutputStream 和 Writer 为抽象基类

字节流和字符流

所操作的数据单元划分:字节流和字符流

InputStream(字节流,8位的字节),OutputStream(字节流)

Reader(字符流,16位的字符),Writer(字符流)

节点流和处理流

节点流:可以直接向特定的IO设备(硬盘,网络)读写数据的流,直接连接到实际的数据源

处理流:对一个已存在的流进行连接或封装,通过封装后的流进行读写数据,装饰器模式

3.IO操作

InputStream 和 Reader

所有输入流的抽象基类

InputStream

int read(); // 从输入流中读取单个字节
int read(byte[] b); // 从输入流中最多读取b.length个字节的数据,将其存储在字节数组b中,返回实际读取的字节数
int read(byte[] b, int off, int len); // 从输入流中最多读取len个字节的数据,将其存储在字节数组b中,存储的起始位置为b[off]

Reader

// 功能如上,只是操作的数据单元是字符
int read();
int read(char[] buf);
int read(char[] buf, int off, int len);
OutputStream 和 Writer

所有输出流的抽象类

OutputStream

void write(int c); // 将指定的字节输出到输出流
void write(byte[] buf); // 将字节数组中的数据输出到指定输出流
void write(byte[] buf, int off, int len); // 将字节数组中从off开始,长度为len的字节输出到输出流中

Writer

void write(int c);
void write(char[] buf);
void write(char[] buf, int off, int len);
void write(String str);
void write(String str, int off, int len)

实例:文件节点流FileInputStream, FileOutputStream直接操作文件

/*
 * A copy to B
 */
public class FileCopyTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // 输入流和输出流, 在try语句中定义IO流,AutoCloseable 程序结束后,自动关闭IO流
        try (FileInputStream fis = new FileInputStream(
                "/Users/hugang/Desktop/a.txt");
                FileOutputStream fos = new FileOutputStream(
                        "/Users/hugang/Desktop/b.txt");) {
            byte[] buff = new byte[1024];

            int hasRead = 0;
            // 从输入流中读, -1表示输入流的结束点, hasRead为实际读到的字节数,如果本次不为-1,下次会从上次读取的结束后(有个指针标记),继续读
            while ((hasRead = fis.read(buff)) != -1) {
                // 从输出流中读
                fos.write(buff, 0, hasRead);
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

4.常用处理流

PrintStream

PrintStream包装OutputStream,使用处理流后的输出流更加方便,方便写入文本内容。

// 将"write to 1.txt" 写入1.txt
 public class PrintStreamTest {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try(PrintStream ps = new PrintStream(new FileOutputStream("/Users/hugang/Desktop/1.txt"))){
            ps.println("write to 1.txt");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
BufferedReader

BufferedReader包装Reader, readLine()一次读入一行内容,方便读取输入流的文本内容。

转换流:

InputStreamReader:将字节输入流转换为字符输入流

OutputStreamWriter:将字节输出流转换成字符输出流


/*
 * 将键盘输入的内容打印出来,直到输入"exit"退出
 */public class BufferedReaderTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try( BufferedReader br = new BufferedReader( new InputStreamReader ( System.in ) ); ){
            String buffer = null;
            while( ( buffer = br.readLine() ) != null ){
                if( "exit".equals(buffer)  ){
                    System.exit(-1);
                }else{
                    System.out.println(buffer);
                }
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
  System.exit(0);  ---> OK
  System.exit(-1); ---> analogues to Exception
  System.exit(1);  ---> analogues to Error

System.in; // 键盘输入,返回InputStream

System.out; // 显示器输出,返回PrintStream

5.重定向标准输入输出

Java中标准输入输出分别用System.in和System.out
在System类中提供:

static void setErr(PrintStream err):重定向标准错误输出流
static void setIn(InputStream in):重定向标准输入流
static void setOut(PrintStream out):重定向标准输出流
/*
 * 重定向标准输出到文件
 */
public class SetOutTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try (PrintStream ps = new PrintStream(new FileOutputStream(
                "/Users/hugang/Desktop/1.txt"));) {
            System.setOut(ps);

            System.out.println("test setOut");

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

6.RandomAccessFile

文件内容访问类,可以调到任意地方读数据,写数据只能追加。
构造函数:


RandomAccessFile(File file, String mode)
Creates a random access file stream to read from, and optionally to write to, the file specified by the File argument.
RandomAccessFile(String name, String mode)
Creates a random access file stream to read from, and optionally to write to, a file with the specified name.

mode:

"r"     Open for reading only. Invoking any of the write methods of the resulting object will cause an IOException to be thrown.
"rw"    Open for reading and writing. If the file does not already exist then an attempt will be made to create it.
"rws"   Open for reading and writing, as with "rw", and also require that every update to the file's content or metadata be written synchronously to the underlying storage device.
"rwd"   Open for reading and writing, as with "rw", and also require that every update to the file's content be written synchronously to the underlying storage device.

rws flushes the contents of the file and the modification date of the file.

rwd flushs the contents of the file, but the modification date might not change until the file is closed.

rw only flushes when you tell it to and doesn’t change the modifcation date until you close the file.

BTW rwd is much slower for writes than rw, and rws is slower again.

常用方法:

long getFilePointer(); // 文件记录指针当前位置
vodi seek(long pos); // 文件记录指针定位到pos位置,单位:字节

wiki:

http://docs.oracle.com/javase/7/docs/api/java/io/RandomAccessFile.html

/*
 * 追加文件内容
 */
public class RandomAccessFileTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try( RandomAccessFile raf = new RandomAccessFile( "/Users/hugang/Desktop/1.txt", "rw" ); ){
            raf.seek(raf.length());
            raf.writeBytes("append file content!\n");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

7.Java序列化和反序列化

序列化(Serialize):java对象转换成二进制流

反序列化(Deserialize):二进制转换成java对象

需要实现序列化的类必须 implements Serializable(Or Externalizable)。

序列化步骤:

1.新建ObjectOutputStream处理流,必须包装个节点流,比如:FileOutputStream

2.ObjectOutputStream对象的writeObject()输出可序列化对象

实例:

public class People implements Serializable {
    private int age;
    private String name;

    public People( int age, String name ){
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}
/**
 * java序列化, 将java对象转换成二进制
 * @author hugang
 *
 */
public class SerializableTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try( ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream( "/Users/hugang/Desktop/2.txt" ) ); ){
            People people = new People(20, "tom");
            oos.writeObject(people);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

反序列化步骤:

1.新建ObjectInputoutStream对象(处理流),需包装节点流,比如:FileInputStream

2.ObjectOutputStream实例的readObject()读取流中的对象

/**
 * 反序列化成java对象
 * @author hugang
 *
 */
public class DeserializableTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try( ObjectInputStream ois = new ObjectInputStream( new FileInputStream( "/Users/hugang/Desktop/2.txt" ) ); ){
            People people = (People)ois.readObject();
            System.out.println(people.getAge() + ":" + people.getName());

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值