[java特性]文件操作File与文件读写IO

IO核心

IO操作主要类和方法位于java.io.*

> File类                             文件操作
> Serializable接口                 对象序列化
> InputStream抽象类                字节输入流
> OutputStream抽象类               字节输出流
> Reader抽象类                     字符读取流
> Writer抽象类                     字符写入流

> 文件读写四步核心
1. 创建File类对象,指明操作路径
2. 输入输出流子类对象实例化
3. 内容以字节形式读写操作
4. 关闭流

[toc]

File类

public class File extends Object
implements Serializable, Comparable<File>               // 可序列化可排序
-----------------------------------------------------------------------------------
public static final String separator                // 系统相关的路径分隔符
-----------------------------------------------------------------------------------
public File (String pathname)                       // 构造操作路径的文件对象
public File (URI uri)                               // 构造操作路径的文件对象
public File (File parent, String child)     // 通过父路径和子路径构造文件对象
public File (String parent, String child)   // 通过父路径和子路径构造文件对象
-----------------------------------------------------------------------------------
public boolean canExecute ()                            // 判断当前文件可执行
public boolean canRead ()                               // 判断当前文件可读
public boolean canWrite ()                              // 判断当前文件可写
public boolean createNewFile () throws IOException          // 创建新文件
public boolean delete ()                                    // 删除文件
public boolean exists ()                                    // 判断文件存在
public File getAbsoluteFile ()                      // 获取绝对路径文件实例
public String getAbsolutePath ()                    // 获取绝对路径字符串
public String getName ()                                // 获取文件或目录名
public String getParent ()                              // 获取父路径字符串
public File getParentFile ()                            // 获取父路径文件实例
public String getPath ()                                // 获取文件路径
public boolean isDirectory ()                       // 判断当前路径是否为目录
public boolean isFile ()                            // 判断当前文件是否为文件
public long lastModified ()                         // 获取最后修改时间(单位ms)
public long length ()                               // 获取文件大小(单位byte)
public String[] list ()                             // 列出所在路径所有文件名称
public File[] listFiles ()                          // 列出所在路径所有文件对象
public boolean mkdir ()                         // 父目录文件对象创建单级目录
public boolean mkdirs ()                        // 父目录文件对象创建多级目录
public boolean renameTo (File dest)                 // 文件重命名和更改路径

创建文件对象

File.separator可实现文件分隔符的跨平台兼容性

    File file = new File("D:/directory/file.txt");
    File file = new File("D://directory//file.txt");
    File file = new File("D:\\directory\\file.txt"); // 分隔符注意转义
    File file = new File("D:" + File.separator + "directory"+ File.separator + "file.txt");
    File file = new File("D:", "subFile.txt");
    File fileDir = new File("D:" + File.separator + "directory");
    File file = new File(fileDir, "subFile.txt");

创建磁盘文件

父目录存在前提下创建磁盘文件,否则报IOException

    File file = new File("D:" + File.separator + "file.txt");    // 指定操作路径
    try { file.createNewFile(); }                   // 需在已存在的目录下创建文件
    catch (IOException e) { e.printStackTrace(); }
    if (file.exists()) { System.out.println(file.delete()); }       // 文件删除

未知父目录情况应加入存在判断和创建,只需判断和创建一次以提升性能

    private static File file = new File(
              "D:"          + File.separator
            + "directory"   + File.separator
            + "directory"   + File.separator
            + "file.txt");

    // 父目录不存在创建父目录
    static {
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
    }

    public static void main(String[] args) throws IOException {
        if (!file.exists()) {
            file.createNewFile();
        }
    }

文件操作涉及磁盘读写,存在一定的延迟

创建文件目录

父目录存在可使用mkdir方法在父目录下创建一级子目录

    File file = new File("D:" + File.separator + "directory");
    if(!file.exists()){ file.mkdir(); }

父目录存在与否均可使用mkdirs方法一次性创建声明的所有目录

    File file = new File("D:" + File.separator
                + "directory" + File.separator
                + "directory");
    if(!file.exists()){ file.mkdirs(); }

文件属性操作

    System.out.print(file.canRead());         // true
    System.out.print(file.canWrite());        // true
    System.out.print(file.canExecute());      // true
    System.out.print(file.getName());         // file.txt
    System.out.print(file.getPath());         // D:\directory\directory\file.txt
    System.out.print(file.getAbsoluteFile()); // D:\directory\directory\file.txt
    System.out.print(file.getAbsolutePath()); // D:\directory\directory\file.txt
    System.out.print(file.isDirectory());     // false
    System.out.print(file.isFile());          // true
    System.out.print(file.isAbsolute());      // true
    System.out.print(file.lastModified());    // 1567736964497
    System.out.print(file.length());          // 950732640
    System.out.print(new SimpleDateFormat("yyyy-mm-dd").format(file.lastModified())); // 2019-09-06
    System.out.print(String.format("%5.2f", (double) file.length() / 1024 / 1024)); // 906.69

列出全部目录

list方法返回子一级路径目录和文件名称字符串数组,无完整路径
listFile方法返回所有子一级路径目录及文件对象,含完整路径

    System.out.println(Arrays.toString(file.list()));
    System.out.println(Arrays.toString(file.listFiles()));
[dir_0, dir_1, dir_2]
[D:\directory\dir_0, D:\directory\dir_1, D:\directory\dir_2]

递归列出全部目录和文件

    public static void listFile(File file) {
        System.out.println(file);
        if (file.isDirectory()) {
            File[] list = file.listFiles();
            if (list != null) { // 防止空指针和空数组
                for (File item : list) {
                    listFile(item);
                }
            }
        }
    }

    public static void main(String[] args) throws IOException {
        File file = new File("D:" + File.separator + "directory");
        listFile(file);
    }
D:\directory
D:\directory\dir_0
D:\directory\dir_0\test[00].txt
D:\directory\dir_0\test[01].txt
D:\directory\dir_0\test[02].txt
D:\directory\dir_1
D:\directory\dir_1\test[10].txt
D:\directory\dir_1\test[11].txt
D:\directory\dir_1\test[12].txt
D:\directory\dir_2
D:\directory\dir_2\test[20].txt
D:\directory\dir_2\test[21].txt
D:\directory\dir_2\test[22].txt

文件删除操作

目录中内容只有为空时才可删除
深度优先删除文件,最终删除目录

    public static void main(String[] args) throws IOException {
        File file = new File("D:" + File.separator + "directory");
        delDir(file);
    }

    public static void delDir(File file) {
        if(file.isDirectory()){
            File[] list = file.listFiles();
            if(list != null){
                for (File item : list){
                    delDir(item);
                }
            }
        }
        file.delete();
    }

路径名称更改

文件重命名并更改路径

    File file0 = new File("D:" + File.separator + "directory" + File.separator +"file0.txt");
    File file1 = new File("D:" + File.separator + "file1.txt");
    file0.renameTo(file1);

文件批量重命名(待续)

指定D:\directory目录下
所有名字为test[XX].txt的文件
将数字长度补齐到5位,后缀名修改为jpg
    public static void main(String[] args){
        File file = new File("D:" + File.separator + "directory");
        renameFile(file);
    }

    public static void renameFile(File file) {
        System.out.println(file);
        if(file.isDirectory()){
            File[] list = file.listFiles();
            if(list != null){
                for (File item : list){
                    renameFile(item);
                }
            }
        }
    }

输入输出流抽象类

子类之间区别

类型 字节流 字符流
适用场景 文件、网络 文本处理
与硬件交互 字节流直接交互 字符流缓冲区中转字节流

写硬盘时设有缓冲区,为防止频繁写硬盘,写满缓冲区才进行真正的写硬盘操作
在流的close方法中,会调用flush方法强制将缓冲区中的所有内容写入硬盘
FileOutputStream未调用close方法可以成功写入文件
FileWriter需要缓冲区,未调用close方法需要使用flush方法才可成功写文件
FileWrite未调用close方法和flush方法而使用了write方法,将清空文件内容

流的自动关闭

一般手动在finally中进行关闭操作,如下所示IO流自动关闭

    构造File类对象;
    try( 实例化输入输出流对象 ){
        IO处理;
    }catch(IOException e){
        异常处理;
    }

OutputStream抽象类

OutputStream子类ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, PipedOutputStream
避免频繁写入需要使用缓冲区

    public abstract class OutputStream extends Object
    implements Closeable, Flushable
    ------------------------------------------------------------------------------------
    public void close () throws IOException                      // 关闭流及相关系统资源
    public void flush () throws IOException                          // 强制输出缓冲数据
    public abstract void write (int b) throws IOException            // 写入单个特定字节
    public void write (byte[] b) throws IOException               // 写入全部字节数组数据
    public void write (byte[] b, int off, int len) throws IOException // 写入选定部分字节

FileOutputStream子类

public class FileOutputStream extends OutputStream
------------------------------------------------------------------------------------------------
public FileOutputStream (File file) throws FileNotFoundException                 // 从首字节写入
public FileOutputStream (File file, boolean append) throws FileNotFoundException // 末尾追加写入
public FileOutputStream (String name) throws FileNotFoundException
public FileOutputStream (String name, boolean append) throws FileNotFoundException

继承结构

写入文件

父目录存在情况下,无需进行文件创建,否则应创建
write单参方法默认从首字节开始写入,覆盖全部已有内容
同一OutputStream实例多次调用write单参方法,第一次覆盖,之后默认尾部追加
write双参方法设定append为true,从文件内容末尾进行数据追加

    File file = new File("D:" + File.separator + "file.txt");
    OutputStream outputStream = new FileOutputStream(file);
    // OutputStream outputStream = new FileOutputStream(file, true);
    outputStream.write(new String("content\r\n").getBytes());
    outputStream.close();

InputStream抽象类

子类ByteArrayInputStream,FileInputStream,FilterInputStream,ObjectInputStream,PipedInputStream,SequenceInputStream,StringBufferInputStream

public abstract class InputStream
extends Object
implements Closeable
------------------------------------------------------------------------------
public InputStream ()
------------------------------------------------------------------------------
public abstract int read () throws IOException                  // 读取下个字节
public int read (byte[] b) throws IOException                   // 读取字节数组
public int read (byte[] b, int off, int len) throws IOException // 读取指定数据
public byte[] readAllBytes () throws IOException                // 读取所有数据
public int available () throws IOException                      // 返回字节数目

FileInputStream子类

文件读入无需缓冲区

public class FileInputStream extends InputStream
-----------------------------------------------------------------
public FileInputStream (File file) throws FileNotFoundException
public FileInputStream (String name) throws FileNotFoundException

继承结构

读入文件

输入流需判断文件存在,不存在报FileNotFoundException
read方法返回读取到的字节数,若读取完毕返回-1
read无参方法按顺序每次读取一个字节
read单参方法将文件读入字节数组中,每次读取尺寸为字节数组大小
read单参方法读取内容数量不足补余为0,造成空间浪费,用len解决
每调用一次read方法,默认从上次结束处开始读取

  • 逐字节读取文件内容
    File file = new File("D:" + File.separator + "file.txt");
    try (InputStream in = new FileInputStream(file)) {
    int item = -1;
        if (file.exists()) {
            while ((item = in.read()) != -1) {
                System.out.print((char) item);
            }
        }
    } catch (IOException e){
        e.printStackTrace();
    }
  • 逐字节数组读取source文件的内容写入新的文件target文件中
    File sourceFile = new File("D:" + File.separator + "source_file.txt");
    File targetFile = new File("D:" + File.separator + "target_file.txt");
    InputStream inputStream = null;
    OutputStream outputStream = null;
    if (sourceFile.exists()) {
        try {
            int len = -1;
            byte[] content = new byte[1024];
            inputStream = new FileInputStream(sourceFile);
            outputStream = new FileOutputStream(targetFile);
            while ((len = inputStream.read(content)) != -1) {
                outputStream.write(content, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            inputStream.close();
            outputStream.close();
        }
    }
  • readAllBytes方法一次性将文件全部读入字节数组,文件大小超过2GB会报OutOfMemoryError
    File file = new File("D:" + File.separator + "file.txt");
    InputStream inputStream = null;
    if (sourceFile.exists()) {
        try {
            inputStream = new FileInputStream(sourceFile);
            if(inputStream.available() < 2 * 1024 * 1024 * 1024){
                byte[] content = inputStream.readAllBytes();
                System.out.println(new String(content));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            inputStream.close();
            outputStream.close();
        }
    }

Writer抽象类

子类BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter

public abstract class Writer
extends Object
implements Appendable, Closeable, Flushable
-----------------------------------------------------------------
protected Writer ()                               // Writer本身同步
protected Writer (Object lock)                      // 传入对象同步
public Writer append (char c) throws IOException    // 追加单个字符
public Writer append (CharSequence csq) throws IOException
public Writer append (CharSequence csq, int start, int end) throws IOException
public abstract void close () throws IOException
public abstract void flush () throws IOException
public void write (char[] cbuf) throws IOException
public void write (String str) throws IOException
public void write (String str, int off, int len) throws IOException
public abstract void write (char[] cbuf, int off, int len) throws IOException

FileWriter子类

可直接输出单个字符、字符数组、字符串
接收CharSequence实例可使用StringBuffer、StringBuilder等

继承结构

写入文件

无需创建文件,只需保证父目录存在
同一FileWriter实例多次调用write方法,第一次覆盖,之后默认尾部追加

    File file = new File("D:" + File.separator + "directory" + File.separator + "file.txt");
    FileWriter writer = null;
    if(!file.getParentFile().exists()){
        file.getParentFile().mkdirs();
    }
    try {
        writer = new FileWriter(file);
        writer.write("Test0");
        writer.write(new char[]{'T', 'e', 's', 't', '1'});
        writer.write("Test2", 0, 4); // 0开始,写4个字符
        writer.write(new char[]{'T', 'e', 's', 't', '3'}, 0, 4);
        writer.append('e'); // 追加单个字符
    } catch (IOException e) {
        e.printStackTrace();
    }
    finally{
        writer.close();
    }

Reader抽象类

子类BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader, URLReader

public abstract class Reader
extends Object
implements Readable, Closeable
------------------------------------------------
protected Reader ()
protected Reader (Object lock)
------------------------------------------------
public abstract void close () throws IOException
public int read () throws IOException                                       // 读入一个字符,阻塞方法
public int read (char[] cbuf) throws IOException                            // 读入字符数组,阻塞方法
public abstract int read (char[] cbuf, int off, int len) throws IOException // 读入选定字符到数组,阻塞方法
public long skip (long n) throws IOException                                // 跳过n个字符,阻塞方法

FileReader子类

public class FileReader extends InputStreamReader
----------------------------------------------------------------
public FileReader (String fileName) throws FileNotFoundException
public FileReader (File file) throws FileNotFoundException

继承结构

读取字符

逐字符读入所有文件内容并输出

    File file = new File("D:" + File.separator + "file.txt");
    Reader reader = null;
    int item;
    if (file.exists()) {
        try {
            reader = new FileReader(file);
            while ((item = reader.read()) != -1)
                System.out.print((char) item);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            reader.close();
        }
    }

字符读入字符数组逐数组读取

    File file = new File("D:" + File.separator + "file.txt");
    int len = 0;
    Reader reader = null;
    char[] content = new char[1024];
    if (file.exists()) {
        try {
            reader = new FileReader(file);
            while ((len = reader.read(content)) != -1)
                System.out.print(new String(content, 0, len));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            reader.close();
        }
    }

字符流和字节流转换

字节流转换为字符流方便进行文本相关操作
FileOutputStream/FileInputStream均为字节流
FileWriter/FileReader类均经由转换流,将字节流转换为字符流

OutputStreamWriter类

public class OutputStreamWriter extends Writer
-----------------------------------------------------------------------------------------
public OutputStreamWriter (OutputStream out)
public OutputStreamWriter (OutputStream out, Charset cs)
public OutputStreamWriter (OutputStream out, CharsetEncoder enc)
-----------------------------------------------------------------------------------------
public Writer append (CharSequence csq) throws IOException
public Writer append (CharSequence csq, int start, int end) throws IOException
public void close () throws IOException
public void flush () throws IOException
public void write (char[] cbuf, int off, int len) throws IOException
public void write (int c) throws IOException
public void write (String str, int off, int len) throws IOException

继承结构

OutputStreamWriter是字符流Writer子类,接收OutputStream对象,向上转型为字符流

InputStreamReader类

public class InputStreamReader extends Reader
----------------------------------------------------------------------------------------------------------------------
public InputStreamReader (InputStream in)
public InputStreamReader (InputStream in, String charsetName) throws UnsupportedEncodingException
public InputStreamReader (InputStream in, Charset cs)
public InputStreamReader (InputStream in, CharsetDecoder dec)
----------------------------------------------------------------------------------------------------------------------
public void close () throws IOException
public int read () throws IOException
public int read (char[] cbuf, int offset, int length) throws IOException

继承结构

InputStreamReader是字符流Reader子类,接收InputStream对象,向上转型为字符流

转换实例

写操作要进行close方法或flush方法确保内容写入文件

    OutputStream out = null;
    Writer writer = null;
    try{
        File file = new File("D:" + File.separator + "file.txt");
        out = new FileOutputStream(file);
        writer = new OutputStreamWriter(out);
        writer.write("test_text");
    }catch (IOException e){
        e.printStackTrace();
    }finally {
        if (writer != null) { writer.close(); }
        if (out != null) { out.close(); }
    }

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

©2018-2024 Howell版权所有 备案号:冀ICP备19000576号