JavaSE个人学习笔记03:IO流

时间:2021-06-04 21:34:09

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();
    }

    }