JavaSE个人学习笔记03:IO流

03 IO流

IO的API方法少且较为固定,有一定的规律,需要熟悉掌握并学会使用特定情况下所使用的代码。
详情参考JDK最新版本的API官方文档,此处只做简单介绍。



概念

IO流即输出流和输入流

将外设的数据读取到内存中:输入
将内存的数据读取到外设中:输出

字符流与字节流
字节流是由字节组成的,不仅可以操作字符,还可以操作其他媒体文件,处理的最小单位是byte.
字符流是由字符组成的,只能操作字符数据,处理的最小单位是char.
字符流的由来:字节流读取字节数据后,查找指定的编码表获得对应的文字,再对该文字进行操作。字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的。简单来说,字符流=字节流+编码表

字节流的两个顶层抽象父类InputStreamReader和OutputStreamWriter
字符流的两个顶层抽象类Reader和Writer


类的介绍

字符流顶层父类Reader ###

常用方法与说明

abstract void close():关闭该流并释放与之关联的所有资源。
int read():读取单个字符,如果已到达流的末尾,则返回 -1。
int read(char[] cbuf):将字符读入数组,返回读入数据的长度。
abstract int read(char[] cbuf, int off, int len): 将字符读入数组的某一部分,返回读入数据的长度。

字符流顶层父类Writer

常用方法与说明

Writer append(char c):将指定字符添加到此 writer。
Writer append(CharSequence csq):将指定字符序列添加到此 writer。
Writer append(CharSequence csq, int start, int end):将指定字符序列的子序列添加到此 writer.Appendable。
void write(int c):写入单个字符。
void write(String str):写入字符串。
void write(String str, int off, int len):写入字符串的某一部分。
abstract void close():关闭此流,会调用flush方法刷新它。
abstract void flush(): 刷新该流的缓冲。
void write(char[] cbuf):写入字符数组。
abstract void write(char[] cbuf, int off, int len):写入字符数组的某一部分。


FileReader

构造方法及常用方法

FileReader(File file):根据给定File对象创建FileReader对象
FileReader(String fileName):根据给定文件名创建FileReader对象

使用示例

FileReaderDemo1.java

public class FileReaderDemo1{
    public static void main( String[] args ) throws IOException{
        // 单个字符读取文件流
        FileReader fReader = new FileReader( "input.txt" );//IOException需要处理或者抛出
        int ch;
        // 如果已到达流的末尾,则返回 -1
        while ( (ch = fReader.read()) != -1 )
        {
            System.out.print( (char)ch );
            ch = fReader.read();
        }
        fReader.close();// 关闭文件输出流,释放资源
    }
}

FileReaderDemo2.java

public class FileReaderDemo2{
    public static void main( String[] args ) throws IOException{
        // 使用字符数组读取文件流
        FileReader fReader = new FileReader( "input.txt" );
        char[] ch = new char[1024];
        int count = 0;
        while ( (count = fReader.read( ch )) != -1 )//IOException需要处理或者抛出
        {
            System.out.println( count + new String( ch, 0, count ) );
        }
        fReader.close();
    }
}

FileWriter

构造方法及常用方法

FileWriter(File file):根据给定的 File 对象创建 FileWriter 对象。
FileWriter(File file, boolean append):根据给定的 File 对象构造一个 FileWriter 对象,如果 append为true,那么对该文件进行续写。
FileWriter(String fileName):根据给定的文件名创建FileWriter对象。
FileWriter(String fileName, boolean append):根据给定的文件名创建FileWriter对象。

使用示例

FileWriterDemo1.java

public class FileWriterDemo1{
    public static void main( String[] args ) throws IOException{
        /*
         * 创建一个文件字符输出流对象
         * 构造函数FileWriter(String fileName)
         * 若文件不存在,则自动创建
         * 若文件存在,则覆盖原文件
         */
        FileWriter fWriter = new FileWriter( "output.txt" );//IOException需要处理或者抛出
        // 调用write写入数据到临时存储缓冲区
        fWriter.write( "Hello World" + LINE_SEPARATOR + "hiahia" + LINE_SEPARATOR );//IOException需要处理或者抛出
        // 每次写入都进行flush刷新流,保证数据不丢失
        fWriter.flush();
        // 关闭文件流。关闭前会调用flush刷新缓冲
        fWriter.close();
    }
}

FileWriterDemo2.java

public class FileWriterDemo2{
    public static void main( String[] args ) throws IOException{
        // 使用字符串进行write操作,也可以使用字符数组(略)
        FileWriter fWriter = new FileWriter( "output.txt" );
        String s = "Hello World";
        fWriter.write( s );
        fWriter.close();
    }
}

程序实现:拷贝text文件,使用数组作为缓冲区,并做异常处理
CopyFileByCharArrays.java

public class CopyFileByCharArrays{
    public static void main( String[] args ) throws IOException{
        String source, destination;
        source = "input.txt";
        destination = "output.txt";
        FileReader fReader = null;
        FileWriter fWriter = null;
        try{
            fReader = new FileReader( source );
            fWriter = new FileWriter( destination );
            char[] arr = new char[1024];// 创建临时容器,用于缓存读取到的字符,容器大小一般为1024的整数倍
            int len = 0;// 定义一个变量记录读取到的字符数
            while( (len = fReader.read( arr )) != -1 ){
                fWriter.write( arr, 0, len );
            }
        } catch( Exception e ){
            throw new RuntimeException( "读写失败" );
        } finally{
            if( fReader != null )//健壮性判断
                try{
                    fReader.close();
                } catch( IOException e1 ){
                    e1.printStackTrace();
                }
            if( fWriter != null )
                try{
                    fWriter.close();
                } catch( IOException e ){
                    e.printStackTrace();
                }
        }
    }
}

BufferedReader

作用:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
使用目的:提高读取效率。
readLine():读取文本行。实现原理:使用读取缓冲区的read方法,将读取到的字符进行缓冲并判断换行标记,将标记前的数据变成字符串返回

构造方法

BufferedReader(Reader in):创建一个使用默认大小输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int size):创建一个使用指定大小输入缓冲区的缓冲字符输入流。

常用方法

String readLine():读取一个文本行。
*其余方法参考Reader

使用示例

BufferedReader.java

public class CopyFileByCharArrays{
    public static void main( String[] args ){
        FileReader fReader = new FileReader( "input.txt" );
        // 为提高读取效率,使用字符流读取的缓冲区
        // 创建一个和被缓冲的读取流对象相关联的字符读取流的缓冲区对象BufferedReader
        BufferedReader bReader = new BufferedReader( fReader );
        String line = null;
        while ( (line = bReader.readLine()) != null )
        {
            // 读取文本行,不包含换行符
            System.out.println( line );
        }

        // 关闭缓冲区,其实就是关闭了被缓冲的对象,同时也调用了flush方法
        bReader.close();// 等同于 fWriter.close();
    }
}
MyBufferedReader

模拟BufferedReader,自定义读取缓冲区(装饰设计模式

MyBufferedReader.java

/**
 * 实现原理:使用读取缓冲区的read方法,将读取到的字符进行缓冲并判断换行标记,将标记前的数据变成字符串返回
 * @classname MyBufferedReader
 * @author LiShengc
 */
public class MyBufferedReader extends Reader
{
    private final int BUFFER_SIZE = 1024;
    private Reader reader;
    char[] buffer;
    int index, len;

    public MyBufferedReader( Reader reader )
    {
        this.reader = reader;
        buffer = new char[BUFFER_SIZE];
        index = 0;
        len = 0;
    }

    public String myReadLine() throws IOException
    {
        StringBuilder sb = new StringBuilder();
        int ch;
        while( (ch = read()) != -1 )
        {
            // 判断换行符
            if( ch == '\r' )
                continue;
            if( ch == '\n' )
                return sb.toString();
            sb.append( (char)ch );
        }
        // 健壮性判定,判断当前行是否最后一行
        if( sb.length() > 0 )
            return sb.toString();
        return null;
    }

    @Override
    public int read( char[] cbuf, int off, int len ) throws IOException
    {
        if( index == len )
        {
            len = reader.read( buffer );
            index = 0;
        }
        if( len == -1 )
            return -1;
        return buffer[index++];
    }

    @Override
    public void close() throws IOException
    {
        reader.close();
    }
}

BufferedWriter

构造方法

*参考BufferedReader

常用方法

newLine():写入一个行分隔符。分隔符字符串由系统属性 line.separator定义,可使用 private final static String LINE_SEPARATOR = System.getProperty( "line.separator" ); 语句定义一个静态常量并获取当前系统下的换行符。
*其余方法参考Writer

使用示例

BufferedWriterDemo.java

public class BufferedWriterDemo{
    public static void main( String[] args ) throws IOException{
        FileWriter fWriter = new FileWriter( "output.txt" );
        // 为提高写入效率,使用字符流写入的缓冲区
        // 创建一个和被缓冲的写入流对象相关联的字符写入流的缓冲区对象BufferedWriter
        BufferedWriter bWriter = new BufferedWriter( fWriter );
        bWriter.write( "abcd" );
        // 写入换行符
        bWriter.newLine();
        // 刷新缓冲区
        bWriter.flush();
        // 关闭缓冲区,其实就是关闭了被缓冲的对象,同时也调用了flush方法
        bWriter.close();// 等同于 fWriter.close();
    }
}

*装饰设计模式

对一组对象的功能进行增强时,使用该模式进行问题的解决。
装饰设计模式和继承都能实现一样的特点——进行某种功能的扩展。
继承方法实现的缺点:
1. 为体系的每个类实现一个功能扩展的子类会导致该继承体系臃肿,且当体系进行扩展时,问题更加突出。
2. 使用不够灵活。

例子:BufferedRead,BufferedWriter类

装饰设计模式:将所需要增强的功能进行单独封装,并将该功能和具体对象相结合。在构造函数中只需要传入该体系的顶层父类,在体系扩展时无需改动,更为灵活。
特点:装饰类和被装饰类都必须同属于一个接口或者父类

LineNumberReader

构造方法

LineNumberReader(Reader in):使用默认输入缓冲区的大小创建LineNumberReader对象。
LineNumberReader(Reader in, int size):使用指定的输入缓冲区的大小创建LineNumberReader对象。

常用方法

int getLineNumber():获得当前行号。
void setLineNumber(int lineNumber)设置当前行号。默认为0,每获取一行+1。
*其余方法及构造方法参考父类Reader

使用示例

LineNumberReaderDemo.java

public class LineNumberReaderDemo
{
    public static void main( String[] args ) throws IOException
    {
        FileReader fReader = new FileReader( "IO流.txt" );
        LineNumberReader lnReader = new LineNumberReader( fReader );
        String s = null;
        // 可设置起始行号,默认为0
        // lnReader.setLineNumber( 100 );
        while ( (s = lnReader.readLine()) != null )
        {
            System.out.println( lnReader.getLineNumber() + ":" + s );
        }
        lnReader.close();
    }
}

字节流顶层父类OutputStream

常用方法

void close()
void write(byte[] b)
void write(byte[] b, int off, int len)
abstract void write(int b)

字节流顶层父类InputStream

常用方法

void close()
void mark(int readlimit)
abstract int read()
int read(byte[] b)
int read(byte[] b, int off, int len)
int available():返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。读取大文件时慎用,内存可能溢出。

FileInputStream

构造方法

FileInputStream(File file):创建一个向指定 File 对象表示的文件中读取数据的FileInputStream对象。
FileInputStream(String name):创建一个向具有指定名称的文件中写入数据的FileInputStream对象。

常用方法

*参考父类InputStream

FileOutputStream

构造方法

FileOutputStream(File file)
FileOutputStream(File file, boolean append)
FileOutputStream(String name)
FileOutputStream(String name, boolean append)

常用方法

*参考父类OutputStream

使用示例:读取键盘录入

使用标准输入对象 System.in 进行读取键盘输入。

ReadKeyToUpperCase1.java

/*
 * 需求;获取用户输入的数据,并将小写字母变成大写显示在控制台上。
 *  如果输入的是“over”,结束键盘输入
 * 
 * 思路:
 * 1.需要将输入的每行数据拼接成字符串
 * 2.使用容器StringBuilder
 * 3.在用户回车之前将录入的数据变成字符串即可
 */
import java.io.IOException;
import java.io.InputStream;

public class ReadKeyToUpperCase1
{

    public static void main( String[] args ) throws IOException
    {
        //readKey();
        readWords();

    }

    public static void readWords() throws IOException
    {

        StringBuilder sb = new StringBuilder();
        InputStream in = System.in;
        int ch = 0;
        while( (ch = in.read()) != -1 )
        {
            // 回车换行不进行存储输出
            if( ch == '\r' )
                continue;
            if( ch == '\n' )
            {
                String temp = sb.toString();
                if( "over".equals( temp ) )
                    break;
                System.out.println( temp.toUpperCase() );
                sb.delete( 0, sb.length() );// 清空sb数据
            } else
                sb.append( (char)ch );
        }
    }

    public static void readKey() throws IOException
    {
        InputStream in = System.in;//获取System.in对象,即标准输入对象
        int ch = in.read();//阻塞式方法
        System.out.println( ch );
        //windows下回车换行符占用两个字节
        ch = in.read();
        System.out.println( ch );
        ch = in.read();
        System.out.println( ch );

        //无需关闭in,关闭后此程序将无法再次使用和创建
    }

}

转换流InputStreamReader

它是字节流通向字符流的桥梁(解码):它使用指定的 charset 读取字节并将其解码为字符,所使用的字符集可以由名称指定或显式给定,否则接受平台默认的字符集。
为了达到最高效率,可以考虑在BufferedReader内包装InputStreamReader。

构造方法

InputStreamReader(InputStream in):创建一个使用默认字符集的 InputStreamReader。
InputStreamReader(InputStream in, Charset cs):创建使用给定字符集的 InputStreamReader。
InputStreamReader(InputStream in, String charsetName):创建使用指定字符集的 InputStreamReader。

常用方法

*参考父类Reader

使用示例

上述一题的第二种做法:
ReadKeyToUpperCase2.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class ReadKeyToUpperCase2
{

    public static void main( String[] args ) throws IOException
    {
        InputStream in = System.in;
        //将字节流转成字符流
        InputStreamReader inReader = new InputStreamReader( in );
        BufferedReader biStream = new BufferedReader( inReader );

        String lnString = null;
        while( (lnString = biStream.readLine()) != null )
        {
            if( "over".equals( lnString ) )
                break;
            System.out.println( lnString.toUpperCase() );
        }
    }

}

转换流:OutputStreamWriter

它是字符流通向字节流的桥梁(编码):可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

构造方法

OutputStreamWriter(OutputStream out)
OutputStreamWriter(OutputStream out, Charset cs)
OutputStreamWriter(OutputStream out, String charsetName)

常用方法

*参考父类Writer

使用示例

使用OutputStreamWriter实现基于上一题的需求,代码如下:
TransToByteStream.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

public class TransToByteStream
{

    public static void main( String[] args ) throws IOException
    {
        BufferedReader biStream = new BufferedReader(
                new InputStreamReader( System.in ) );

        // 完整形式
        // OutputStream out = System.out;
        // OutputStreamWriter outWriter = new OutputStreamWriter( out );
        // BufferedWriter boWriter = new BufferedWriter( outWriter );
        BufferedWriter bWriter = new BufferedWriter( new OutputStreamWriter( System.out ) );
        String lnString = null;
        while( (lnString = biStream.readLine()) != null )
        {
            if( "over".equals( lnString ) )
                break;
            boWriter.write( lnString.toUpperCase() );
            boWriter.newLine();
            boWriter.flush();
        }
    }
}
使用情景
  1. 源或目的设备是字节流,但是操作的是文本数据,可以使用转换流将字节流转换为字符流,提高对文本操作的便捷。
  2. 一旦操作文本涉及到具体的指定字符集时,必须使用转换流。

流的操作规律总结

四个明确

  1. 明确源和目的
    • 源:InputStream Reader
    • 目的:OutputStream Writer
  2. 明确数据是否是纯文本数据

    1. 是纯文本
      • 源:Reader
      • 目的:InputStream
    2. 非纯文本
      • 源:InputStream
      • 目的:Writer

    到此处就可以明确需求中具体要使用哪个体系

  3. 明确具体设备

    • 源设备:
    • 硬盘:File输入流
    • 键盘:System.in(标准输入)
    • 内存:数组
    • 网络:Socket流
    • 目的设备:
    • 硬盘:File输出流
    • 控制台:System.out(标准输出)
    • 内存:数组
    • 网络:Socket流
  4. 是否需要额外功能
    • 需要高效读写,使用buffer:BufferedReader和BufferedWriter
    • 转换流: InputStreamReader 和 OutputStreamWriter

File类

将文件或者文件夹封装成对象,方便对文件与文件夹的操作

构造方法

File(String pathname):通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
File(String parent, String child):根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(File parent, String child):根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
File(URI uri):通过将给定的 URI 转换为一个抽象路径名来创建一个新的 File 实例。

具体实现:

File f1=new File( "c:\\test.txt" );
File f2=new File( "c:\\","test.txt" );
File f3=new File( new File( "c:\\" ),"test.txt" );

字段摘要 ###

static String pathSeparator:包含与系统有关的路径分隔符字符的字符串。在 UNIX 系统上,此字段为 ‘:’;在 Microsoft Windows 系统上,它为 ‘;’。与System.getProperty("path.separator")功能相同。
static char pathSeparatorChar
static String separator:包含与系统有关的默认名称分隔符字符的字符串。。在 UNIX 系统上,此字段的值为 ‘/’;在 Microsoft Windows 系统上,它为 ‘\’。与System.getProperty("file.separator")功能相同。
static char separatorChar

常用方法


  1. 获取

  • 文件名:String getName()
  • 文件大小:long length()
  • 最后修改时间:long lastModified(),返回毫秒值
  • 文件路径名(不包含文件名):String getParent()
  • 绝对路径名:String getAbsolutePath(), String getCanonicalPath()
  • 指定路径名下的分区未分配的字节数:long getFreeSpace()
  • 当前目录下的文件名以及目录名(包含隐藏文件):String[] list()
    **调用list方法的File对象中封装的必须是目录,否则将传回null,访问会发生NullPointerException。
    如果File对象中封装的是系统级目录或者不存在的目录,调用list方法也将返回null。
    如果目录存在但为空,会返回一个长度为0的空字符串数组**
  • long getTotalSpace():返回此抽象路径名下的分区大小。
  • long getFreeSpace():未分配的字节数。
  • long getUsableSpace(): 可用于此虚拟机的字节数。
  • File getAbsoluteFile():返回此抽象路径名的绝对路径名表示的File对象。
  • File getCanonicalFile():同上。
  • File getParentFile():返回此抽象路径名父目录的抽象路径名表示的File对象。
  • static File[] listRoots():列出可用的文件系统根(盘符)。
  • String[] list(FilenameFilter filter)
  • ……
  • 创建
    • boolean createNewFile():当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。如果文件不存在,则创建;如果存在,则不创建。
    • boolean mkdir():创建此抽象路径名指定的目录。
    • boolean mkdirs():创建多级目录。
    • static File createTempFile(String prefix, String suffix):在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。
    • static File createTempFile(String prefix, String suffix, File directory):在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。
  • 删除
    • boolean delete():删除此抽象路径名表示的文件或目录。
    • void deleteOnExit():在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。
  • 判断
    • boolean exists():判断此抽象路径名表示的文件或目录是否存在。
    • boolean isAbsolute():测试是否为绝对路径名。
    • boolean isDirectory():测试是否目录。
    • boolean isFile():测试是否标准文件。
    • boolean isHidden():测试是否隐藏文件。
    • ……
  • 重命名(移动)
    • boolean renameTo(File dest):重新命名此文件。当源路径和目的路径不一致时,该操作为移动。
  • 过滤器

    接口FilenameFilter的实现
    过滤器FilenameFilter及list方法的使用: ListDemo.java
    import java.io.File;
    import java.io.FilenameFilter;
    
    class FilenameFilterSuffixByPDF implements FilenameFilter // 接口FilenameFilter的实现
    {
        @Override
        public boolean accept( File dir, String name )
        {
            return name.endsWith( ".pdf" );
        }
    }
    
    public class ListDemo
    {
        public static void main( String[] args )
        {
            File file = new File( "d:\\" );
            String[] fileList = null;
    
            // 显示d盘下所有文件和目录名称
            fileList = file.list();
            for( String string : fileList )
            {
                System.out.println( string );
            }
    
            // 输出d盘下所有以".pdf"为后缀名的文件
            fileList = file.list( new FilenameFilterSuffixByPDF() );// 使用过滤器筛选结果
            for( String string : fileList )
            {
                System.out.println( string );
            }
        }
    }
    接口FileFilter的实现
    过滤器FileFilter及listFiles的使用: ListFilesDemo.java
    import java.io.File;
    import java.io.FileFilter;
    
    class FilterByHindden implements FileFilter // 接口FileFilter的实现
    {
        @Override
        public boolean accept( File pathname )
        {
            return pathname.isHidden();
        }
    }
    
    public class ListFilesDemo
    {
        public static void main( String[] args )
        {
            // 获取c:\下所有具有隐藏属性的文件的File对象
            File f = new File( "c:\\" );
            File[] files = f.listFiles( new FilterByHindden() );
            for( File file : files )
            {
                System.out.println( file );
            }
    
            // 输出d:\目录下所有以".pdf"为后缀名的文件
            f = new File( "d:\\" );
            files = f.listFiles( new FilenameFilterSuffixByPDF() );// 使用过滤器筛选结果
            for( File file : files )
            {
                System.out.println( file );
            }
        }
    }

    小程序:深度遍历文件夹

    ListAll.java
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    
    import javax.swing.filechooser.FileSystemView;
    
    public class ListAll
    {
    
        public static void main( String[] args ) throws IOException
        {
            // 获取当前电脑的桌面目录
            String desktopPath = FileSystemView.getFileSystemView()
                    .getHomeDirectory().getAbsolutePath();
    
            BufferedWriter bWriter = new BufferedWriter(
                    new FileWriter( desktopPath + "\\AllFiles.txt" ) );
    
            // 获取各个盘符路径
            File[] roots = File.listRoots();
            for( File root : roots )
            {
                // 遍历盘符
                listAll( root, bWriter, 0 );
            }
    
            bWriter.close();
        }
    
        /**
         * 获取当前目录下的所有文件夹和文件对象,并输出
         * 
         * @param file
         * @param bWriter
         * @param count层数计数器,用于带有层次感的缩进输出
         * @throws IOException
         * @return void
         * @author LiShengc
         */
        public static void listAll( File file, BufferedWriter bWriter, int count )
                throws IOException
        {
            // 判断是否为盘符目录,是则输出分割行
            if( count == 0 )
            {
                for( int i = 0; i < 80; i++ )
                    bWriter.write( "*" );
                bWriter.newLine();
                bWriter.newLine();
            }
            tab( bWriter, count );
            count++;
            bWriter.write( file.getAbsolutePath() );// 输出目录路径
            bWriter.newLine();
            // 获取当前目录下的所有文件夹和文件对象
            File[] files = file.listFiles();
            if( files != null )
                for( int i = 0; i < files.length; i++ )
                {
                    if( files[i].isDirectory() )
                    {
                        // 递归
                        listAll( files[i], bWriter, count );
                    } else
                    {
                        tab( bWriter, count );
                        try
                        {
                            // 输出文件绝对路径
                            bWriter.write( files[i].getAbsolutePath() );
                            bWriter.newLine();
                        } catch( IOException e )
                        {
                            throw new RuntimeException(
                                    "写入" + bWriter.toString() + "失败" );
                        }
                    }
                }
        }
    
        /**
         * 用于层级缩进
         */
        public static void tab( BufferedWriter bWriter, int count )
                throws IOException
        {
            for( int i = 0; i < count; i++ )
            {
                bWriter.write( "  |  " );
            }
            bWriter.write( "  |--" );
        }
    
    }

    小程序:删除非空文件夹

    import java.io.File;
    
    public class RemoveDir
    {
    
        public static void main( String[] args )
        {
            String path = "path";
            File dir = new File( path );
            removeDir( dir );
    
        }
    
        public static void removeDir( File file )
        {
            File[] files = file.listFiles();
            for( File f : files )
            {
                if( f.isDirectory() )
                    removeDir( f );
                else
                    System.out.println( f + ":删除" + (f.delete() ? "成功" : "失败") );
            }
            System.out.println( file + ":删除" + (file.delete() ? "成功" : "失败") );
        }
    
    }
    

    Properties集合

    集合与IO相结合,通常该集合用于操作以键值对形式存在的配置文件 Map

    特点

    • 该集合中的键和值都是字符串类型
    • 集合中的数据可以保存到流中,或者从流中获取

    使用示例

    propertiesDemo1.java

    Properties对象数据的存储、修改和获取。

    import java.util.Properties;
    import java.util.Set;
    
    public class propertiesDemo1
    {
        public static void main( String[] args )
        {
            Properties prop = new Properties();
    
            // 存储元素
            prop.setProperty( "zhangsan", "30" );
            prop.setProperty( "lisi", "24" );
            prop.setProperty( "wangwu", "35" );
            prop.setProperty( "zhaoliu", "29" );
    
            // 修改元素
            prop.setProperty( "wangwu", "15" );// 键相同,值覆盖
            // 取出所有元素
            Set<String> names = prop.stringPropertyNames();
            for( String name : names )
            {
                String age = prop.getProperty( name );
                System.out.println( name + ":" + age );
            }
        }
    }
    
    propertiesDemo2.java

    通过Properties对象获取本机系统信息,并输出到标准输出流上。

    import java.util.Properties;
    
    public class propertiesDemo2
    {
        public static void main( String[] args )
        {
            /*
             * 获取系统信息
             */
            Properties prop = new Properties();
            prop = System.getProperties();
            prop.list( System.out );
        }
    }
    

    store方法

    可将Properties对象中保存的字符串信息持久化,即存储到文件中。

    方法概要:
    void store(OutputStream out, String comments):以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。comments为属性列表的描述。
    void store(Writer writer, String comments)

    PropertiesDemo3.java

    将集合中的数据输出到propertiesInfo.txt文件中。

    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.Properties;
    
    public class PropertiesDemo3
    {
        public static void main( String[] args ) throws IOException
        {
            Properties prop = new Properties();
            prop.setProperty( "zhangsan", "30" );
            prop.setProperty( "lisi", "24" );
            prop.setProperty( "wangwu", "35" );
            prop.setProperty( "zhaoliu", "29" );
    
            // 关联输出流
            FileOutputStream foStream = new FileOutputStream(
                    "propertiesInfo.txt" );
    
            // 将数据存储到文件中
            prop.store( foStream, "name-age" );
    
            foStream.close();
        }
    }
    PropertiesDemo4.java

    读取已保存在文件的数据,并输出。

    PropertiesDemo4.java

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.Properties;
    import java.util.Set;
    
    public class PropertiesDemo4
    {
        public static void main( String[] args ) throws IOException
        {
            Properties prop = new Properties();
    
            // 将数据文件读入集合中,必须要保证该文件中的数据是键值对
            // 关联文件输入流
            FileInputStream fiStream = new FileInputStream( "propertiesInfo.txt" );
    
            // 读取文件输入流
            prop.load( fiStream );
    
            Set<String> names = prop.stringPropertyNames();
            for( String name : names )
            {
                String age = prop.getProperty( name );
                System.out.println( name + ":" + age );
            }
            fiStream.close();
        }
    }
    
    PropertiesDemo5.java

    对已有的配置文件中的信息进行修改。

    PropertiesDemo5.java

    import java.io.File;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Properties;
    
    public class PropertiesDemo5
    {
        public static void main( String[] args ) throws IOException
        {
            // 判断文件是否存在,不存在则创建,确保读取成功
            File file = new File( "propertiesInfo.txt" );
            if( !file.exists() )
            {
                file.createNewFile();
            }
            FileReader fReader = new FileReader( file );
            Properties prop = new Properties();
    
            prop.load( fReader );
    
            prop.setProperty( "wangwu", "21" );
    
            // 创建FileWriter对象会把file中的内容清空
            FileWriter fWriter = new FileWriter( file );
            prop.store( fWriter, "name-age" );
    
            fReader.close();
            fWriter.close();
        }
    }
    PropertiesDemo6.java

    综合练习:
    需求:记录程序的使用次数,如果运行次数超过5次,则输出提示信息,并结束程序。

    package properties;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.Properties;
    
    public class PropertiesDemo6
    {
    
        public static void main( String[] args ) throws IOException
        {
            getAppCounts();
        }
    
        public static void getAppCounts() throws IOException
        {
            File config = new File( "count.properties" );
            if( !config.exists() )
                config.createNewFile();
    
            FileInputStream fiStream = new FileInputStream( config );
            Properties prop = new Properties();
            prop.load( fiStream );
    
            String value = prop.getProperty( "times" );
            int count = 0;
            // 判断是否不是第一次使用
            if( value != null )
            {
                count = Integer.parseInt( value );
                // 判断使用次数是否大于等于5次
                if( count >= 5 )
                {
                    // 抛出异常,结束程序的运行
                    throw new RuntimeException( "使用次数已使用完毕,请开通会员,给钱!" );
                }
            }
            count++;
            System.out.println( "已经使用" + count + "次。尚余使用次数:" + (5 - count) + "次." );
    
            prop.setProperty( "times", count + "" );
    
            FileOutputStream foStream = new FileOutputStream( config );
            prop.store( foStream, "" );
    
            fiStream.close();
            foStream.close();
        }
    
    }
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值