Java高级-File和IO流

File

概念  

      java.io.File用于表示文件(目录),可以通过File类在程序中操作硬盘上的文件和目录。File类只能用于描述文件(目录)的属性信息(名称、大小等),不能对文件内容进行访问(即不具有从文件读取信息和向文件写入信息的功能

文件路径

      文件路径尽量使用相对路径,"."表示当前路径(当前类所在项目的根目录)。文件路径分隔符尽量使用File.separator常量代替,它会根据不同操作系统返回不同的文件路径分隔符(windows返回\,Linux返回/)。

源码


public class File implements Serializable, Comparable<File>{
    //......
}

构造方法

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

使用

/**
 * 根据给定抽象路径创建对象,仅仅只是创建文件对象而不表示创建文件
 * 文件路径尽量使用相对路径
*/
File file = new File("." + File.separator + "1.txt");

常用方法

boolean exists()

测试此抽象路径所表示文件或者文件夹是否存在。

true表示存在;false表示不存在。

long length() 返回此抽象路径所表示的文件的长度
long lastModified() 返回此抽象路径所表示的文件最后一次被修改的时间毫秒
String getName() 返回此抽象路径所表示的文件或文件夹的名称
String getPath() 返回此抽象路径所表示的文件或文件夹的抽象路径

boolean isFile()

boolean isDirectory()

测试试此抽象路径所表示文件是否是一个标准的文件

测试试此抽象路径所表示文件是否是一个标准的文件夹

boolean createNewFile()

创建此抽象路径所表示的文件

返回true表示创建成功;返回false表示创建失败。

boolean delete()

删除此抽象路径所表示文件或文件夹

返回true表示删除成功;返回false表示删除失败。

注意事项:若此抽象路径表示文件夹其该文件夹下存在子文件或者文件夹,则需要将子文件或子文件夹删除之后才能删除当前文件夹。

boolean mkdir()

创建此抽象路径名指定的文件夹(只能创建一层目录结构,对于多层目录结构需要使用mkdirs()方法)。

返回true表示创建成功;返回false表示创建失败。

boolean mkdirs() 创建此抽象路径下指定的文件夹,包括所有必需但不存在的父目录。建议使用此方法。
String[] list() 返回此抽象路径下所有子文件和子文件夹的名称数组
File[] listFiles() 返回此抽象路径下所有子文件和子文件夹数组
File[] listFiles(FileFilter fileter)

返回此抽象路径下经过文件过滤规则筛选过的子文件和子文件夹。

FileFilter是一个接口,需要自定义一个类实现它。

class MyFileFilter implements FileFilter{

    //文件筛选的过滤逻辑。返回true则保留当前文件或文件夹;返回false则不保留。
    public boolean accept(File pathname){
           String fileName = pathname.getName(); //获取当前文件名

            //例如判断文件名以.txt结尾则返回true,否则返回false

            return fileName.endWith(".txt");
    }
}

或者使用匿名内部类方式:

FIle[] subFiles = file.listFiles(new FileFilter(){

    public boolean accept(File pathname){
           String fileName = pathname.getName(); 

            return fileName.endWith(".txt");
    }

});

IO流

IO流概念

      IO流指的是输入流(Input)和输出流(Output)。站在内存的角度作为参考,外部文件到内存叫做输入,内存到外部文件叫输出。

分类     

  • 字节流与字符流

         按照数据传输方式或是运输方式角度来看,可以将IO流分为:字节流字符流。两种区别如下:

1.字节流读取单个字节;字符流读取单个字符(一个字符根据编码的不同对应的字节也不同。如UTF-8编码是3个字节,中文编码是2个字节)。
2.字节流用来处理二进制文件(如图片、音频、视频文件等非文本文件)字符流只能用来处理纯文本文件(可以看做是特殊的二进制文件,使用了某种编码,人可以阅读。字节流也可以处理文本文件,故字节流使用较多。
3.形象比喻,字节是给计算机看的,字符是给用户看的。
  • 节点流与处理流

         按照流的功能可以将IO流分为:分为处理流节点流

处理流用于包装节点流,对其功能进行加强,处理流单独存在没有意义。

处理流(高级流)

1.BufferedInputStream, BufferedOutputStream

        使用如:BufferedInputStream bfInput = new BufferedInputStream(new FileInputStream(参数));

2.ObjectInputStream, ObjectOutputStream

3.OutputStreamWriter, InputStreamReader

4.BufferedReader, BufferedWriter, PrintWriter   

节点流(低级流)

1.FileInputStream, FileOutputStream

  • 规律
以InputStream结尾的流是字节出入流;以OutputStream结尾的流是字节输出流;以Reader结尾的流是字符输入流;以Writer结尾的流是字符输出流

体系结构

        常用的类:File开头的文件最基本的读写类;Buffered开头的文件读写带缓存区的类;Object开头的对象序列化和反序列化相关的类。

        从上图可以看见,IO的最基本的4个抽象类为:InputStream、OutputStream、Reader、Writer。

注意事项

        带缓冲的流需要调用close()方法关闭流。文件写入丢失数据现象的原因:对于带缓冲的输出流需要等待缓冲数组写满时才会一起被写入文件,因此流使用完一定要调用close()方法。close()方法内部会调用flush()方法,将缓存数组中剩余的数据强制刷新到文件中。

字节流

InputStream

       InputStream是所有字节输入流的父类,是抽象类(不能直接new)。其源码如下所示:

public abstract class InputStream implements Closeable {
    //MAX_SKIP_BUFFER_SIZE is used to determine the maximum buffer size to use when skipping.
    private static final int MAX_SKIP_BUFFER_SIZE = 2048;
    public abstract int read() throws IOException;
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }
    public int read(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        int c = read();
        if (c == -1) {
            return -1;
        }
        b[off] = (byte)c;

        int i = 1;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException ee) {
        }
        return i;
    }
    public long skip(long n) throws IOException {
        long remaining = n;
        int nr;

        if (n <= 0) {
            return 0;
        }

        int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
        byte[] skipBuffer = new byte[size];
        while (remaining > 0) {
            nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
            if (nr < 0) {
                break;
            }
            remaining -= nr;
        }

        return n - remaining;
    }
    public int available() throws IOException {
        return 0;
    }
    public void close() throws IOException {}
    public synchronized void mark(int readlimit) {}
    public synchronized void reset() throws IOException {
        throw new IOException("mark/reset not supported");
    }
    public boolean markSupported() {
        return false;
    }

}
  • 常用方法
int read()

从此输入流中一次读取一个字节,返回int值,低8位有效,高24位全部补0。

返回-1表示已经读取到文件的末尾。

int read(byte[] b)

从此输入流中将最多b.length个字节读入字节数组b中。

返回值代表实际读取的字节数个数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1

解码:将字节数组安按照给的字符集编码还原成为字符串,若不指定编码集,则按照系统默认的编码集。

       String s = new String(b, "编码格式(UTF-8、GBK等)");

注意:编码和解码使用的编码集要一致。

int read(byte[] b, int offset, int len) 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
void close() 关闭此输入流并释放与该流关联的所有系统资源。
long skip(long n) 跳过和丢弃此输入流中数据的 n 个字节。

OutputStream

       OutputStream是所有字节输出流的父类,是抽象类(不能直接new)。其源码如下所示:

public abstract class OutputStream implements Closeable, Flushable {
    public abstract void write(int b) throws IOException;
    public void write(byte b[]) throws IOException {
        write(b, 0, b.length);
    }   
    public void write(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if ((off < 0) || (off > b.length) || (len < 0) ||
                   ((off + len) > b.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }
        for (int i = 0 ; i < len ; i++) {
            write(b[off + i]);
        }
    }
    public void flush() throws IOException {}
    public void close() throws IOException {}
}
  • 常用方法
void write(int b) 一次写出一个字节,将int的低8位写出。

void wtite(byte[] b)

一次写出一个字节数组

注String的方法:byte[] getBytes(String charsetName)

将字符串按照给的的字符集编码转换成对应字节数组。

编码:将Unicode形式的字节数组转换成指定编码集的字节数组。若不指定编码集,则按照系统默认的编码集编码。Windows默认编码集为GBK,Linux默认编码集为UTF-8。

        byte[] b = s.getBytes("编码格式(UTF-8、GBK等)");

void write(byte[]b, int offset, int len) 从字节数组的offset位置开始连续写出len个字节到输出流中。
void flush()  刷新此输出流并强制写出所有的缓冲的输出字节。
void close() 关闭此输出流并释放与此流有关的所有系统资源。

关闭流

      关闭此文件输入流并释放与此流有关的所有系统资源都调用其close()方法。

      注意事项

1.关闭处理流内部会自动关闭其包装的节点流,故只需要关闭处理流即可。
2.文件写入丢失数据现象的原因:对于带缓冲的输出流需要等待缓冲数组写满时才会一起被写入文件,因此流使用完一定要调用close()方法。close()方法内部会调用flush()方法,将缓存数组中剩余的数据强制刷新到文件中。

      比如ObjectOutputStream的close()方法源码如下所示,调用了flush()方法:

public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants{
    //......
    public void close() throws IOException {
        flush();
        clear();
        bout.close();
    }
}

InputStream和OutputStream的子类      

FileInputStream

     FileInputStream是文件输入流,用于从文件系统中的某个文件中获得输入字节。以字节为单位,一次读取一个字节。用于读取诸如图像数据之类的原始字节流,要读取字符流,使用 FileReader

  • 源码
public class FileOutputStream extends OutputStream{
    //......
}
  • 构造方法
FileInputStream(File file) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
FileInputStream(FileDescriptor fdObj) 通过使用文件描述符 fdObj 创建一个 FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接。

FileOutputStream

      FileOutputStream是文件输出流,以字节为单位,一次向文件写出一个字节。用于写入诸如图像数据之类的原始字节的流。要写入字符流,使用 FileWriter

  • 源码
public class FileInputStream extends InputStream{
    //......
}
  • 构造方法
FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。默认以覆盖的方式
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。默认以覆盖的方式
FileOutputStream(FileDescriptor fdObj) 创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。
FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。以追加的方式。
FileOutputStream(String name, boolean append) 创建一个向具有指定名称的文件中写入数据的输出文件流。以追加的方式。

BufferedInputStream

       在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点,reset 操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次 mark 操作后读取的所有字节。

       将数据读取到内存中,从内存中获取数据比从文件中获取效率高。

  • 源码
public class BufferedInputStream extends FilterInputStream {
    private static int DEFAULT_BUFFER_SIZE = 8192;
    private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
    protected volatile byte buf[];
    private static final
        AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater =
        AtomicReferenceFieldUpdater.newUpdater
        (BufferedInputStream.class,  byte[].class, "buf");
    protected int count;
    protected int pos;
    protected int markpos = -1;
    protected int marklimit;

    private InputStream getInIfOpen() throws IOException {
        InputStream input = in;
        if (input == null)
            throw new IOException("Stream closed");
        return input;
    }

    private byte[] getBufIfOpen() throws IOException {
        byte[] buffer = buf;
        if (buffer == null)
            throw new IOException("Stream closed");
        return buffer;
    }

    public BufferedInputStream(InputStream in) {
        this(in, DEFAULT_BUFFER_SIZE);
    }

    public BufferedInputStream(InputStream in, int size) {
        super(in);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }

    private void fill() throws IOException {
        byte[] buffer = getBufIfOpen();
        if (markpos < 0)
            pos = 0;            /* no mark: throw away the buffer */
        else if (pos >= buffer.length)  /* no room left in buffer */
            if (markpos > 0) {  /* can throw away early part of the buffer */
                int sz = pos - markpos;
                System.arraycopy(buffer, markpos, buffer, 0, sz);
                pos = sz;
                markpos = 0;
            } else if (buffer.length >= marklimit) {
                markpos = -1;   /* buffer got too big, invalidate mark */
                pos = 0;        /* drop buffer contents */
            } else if (buffer.length >= MAX_BUFFER_SIZE) {
                throw new OutOfMemoryError("Required array size too large");
            } else {            /* grow buffer */
                int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
                        pos * 2 : MAX_BUFFER_SIZE;
                if (nsz > marklimit)
                    nsz = marklimit;
                byte nbuf[] = new byte[nsz];
                System.arraycopy(buffer, 0, nbuf, 0, pos);
                if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
                    // Can't replace buf if there was an async close.
                    // Note: This would need to be changed if fill()
                    // is ever made accessible to multiple threads.
                    // But for now, the only way CAS can fail is via close.
                    // assert buf == null;
                    throw new IOException("Stream closed");
                }
                buffer = nbuf;
            }
        count = pos;
        int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
        if (n > 0)
            count = n + pos;
    }

    public synchronized int read() throws IOException {
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
    }

    private int read1(byte[] b, int off, int len) throws IOException {
        int avail = count - pos;
        if (avail <= 0) {
            /* If the requested length is at least as large as the buffer, and
               if there is no mark/reset activity, do not bother to copy the
               bytes into the local buffer.  In this way buffered streams will
               cascade harmlessly. */
            if (len >= getBufIfOpen().length && markpos < 0) {
                return getInIfOpen().read(b, off, len);
            }
            fill();
            avail = count - pos;
            if (avail <= 0) return -1;
        }
        int cnt = (avail < len) ? avail : len;
        System.arraycopy(getBufIfOpen(), pos, b, off, cnt);
        pos += cnt;
        return cnt;
    }

    public synchronized int read(byte b[], int off, int len)
        throws IOException
    {
        getBufIfOpen(); // Check for closed stream
        if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        int n = 0;
        for (;;) {
            int nread = read1(b, off + n, len - n);
            if (nread <= 0)
                return (n == 0) ? nread : n;
            n += nread;
            if (n >= len)
                return n;
            // if not closed but no bytes available, return
            InputStream input = in;
            if (input != null && input.available() <= 0)
                return n;
        }
    }

    public synchronized long skip(long n) throws IOException {
        getBufIfOpen(); // Check for closed stream
        if (n <= 0) {
            return 0;
        }
        long avail = count - pos;

        if (avail <= 0) {
            // If no mark position set then don't keep in buffer
            if (markpos <0)
                return getInIfOpen().skip(n);

            // Fill in buffer to save bytes for reset
            fill();
            avail = count - pos;
            if (avail <= 0)
                return 0;
        }

        long skipped = (avail < n) ? avail : n;
        pos += skipped;
        return skipped;
    }

    public synchronized int available() throws IOException {
        int n = count - pos;
        int avail = getInIfOpen().available();
        return n > (Integer.MAX_VALUE - avail)
                    ? Integer.MAX_VALUE
                    : n + avail;
    }

    public synchronized void mark(int readlimit) {
        marklimit = readlimit;
        markpos = pos;
    }

    public synchronized void reset() throws IOException {
        getBufIfOpen(); // Cause exception if closed
        if (markpos < 0)
            throw new IOException("Resetting to invalid mark");
        pos = markpos;
    }

    public boolean markSupported() {
        return true;
    }

    public void close() throws IOException {
        byte[] buffer;
        while ( (buffer = buf) != null) {
            if (bufUpdater.compareAndSet(this, buffer, null)) {
                InputStream input = in;
                in = null;
                if (input != null)
                    input.close();
                return;
            }
            // Else retry in case a new buf was CASed in fill()
        }
    }
}

       其中FilterInputStream类继承自InputStream

  • 构造方法
BufferedInputStream(InputStream in)  创建一个 BufferedInputStream 
BufferedInputStream(InputStream in, int size)  创建具有指定缓冲区大小的 BufferedInputStream
  • 常用方法

        见InputStream类

BufferedOutputStream

        该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。

  • 源码
public class BufferedOutputStream extends FilterOutputStream {
    protected byte buf[];
    protected int count;

    public BufferedOutputStream(OutputStream out) {
        this(out, 8192);
    }
    public BufferedOutputStream(OutputStream out, int size) {
        super(out);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }
    /** Flush the internal buffer */
    private void flushBuffer() throws IOException {
        if (count > 0) {
            out.write(buf, 0, count);
            count = 0;
        }
    }

    public synchronized void write(int b) throws IOException {
        if (count >= buf.length) {
            flushBuffer();
        }
        buf[count++] = (byte)b;
    }

    public synchronized void write(byte b[], int off, int len) throws IOException{
        if (len >= buf.length) {
            /* If the request length exceeds the size of the output buffer,
               flush the output buffer and then write the data directly.
               In this way buffered streams will cascade harmlessly. */
            flushBuffer();
            out.write(b, off, len);
            return;
        }
        if (len > buf.length - count) {
            flushBuffer();
        }
        System.arraycopy(b, off, buf, count, len);
        count += len;
    }

    public synchronized void flush() throws IOException {
        flushBuffer();
        out.flush();
    }
}

       其中FilterOutputStream类继承自OutputStream

  • 构造方法
BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
  • 常用方法

        见OutputStream类

ObjectInputStream

  • 概念

      ObjectInputStream表示对象输入流。对使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。 

  • 源码   
public class ObjectInputStreamextends InputStream implements ObjectInput, ObjectStreamConstants{
    //......
}
  • 构造方法
ObjectInputStream(InputStream in)  创建写入指定 InputStream 的 ObjectInputStream。
  • 常用方法
Object readObjectj) 从输出流读取对象。

ObjectOutputStream

  • 概念

      ObjectOutputStream表示对象输出流,将 Java 对象的基本数据类型写入 OutputStream流,通过在流中使用文件可以实现对象的持久存储。

  • 源码
public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants{
    //......
}
  • 构造方法
ObjectOutputStream(OutputStream out)  创建写入指定 OutputStream 的 ObjectOutputStream。
  • 常用方法
void writeObject(Object obj) 将对象后出到输出流中。

      

字符流

Reader

       Reader是所有字符输入流的父类。

  • 源码
  • 常用方法
int read() 读取一个字符,返回的int值低16位有效
   

Writer

       Writer是所有字符输出流的父类。

  • 源码
  • 常用方法
void write(int c) 写出一个int值低16位表示的字符
void write(char[] chs) 将给的字符数组中所有的字符写出
void write(String str) 将给的字符串写出
void write(char[] chs, int offset, int len)  

Reader子类

InputStreamReader

      字符输入流,使用该字符流可以设置字符集,

BufferedReader

  • 源码
public class BufferedReader extends Reader {
    private Reader in;
    private char cb[];
    //......
}

     可以看到,定义了一个字符缓冲数组cb。

  • 常用方法
String readLine()

一次读取一行数据。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 回车后直接跟着换行

如果已到达流末尾,则返回 null

Writer子类

OutputStreamWriter

BufferedWriter

PrintWriter

      PrintWriter是具有自动行刷新的缓存字符输出流。

  • 源码
  • 构造方法
PrintWriter(File file) 使用指定文件创建不具有自动行刷新的新 PrintWriter。
PrintWriter(File file, String csn) 创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。
PrintWriter(OutputStream out) 根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。
PrintWriter(OutputStream out, boolean autoFlush)

通过现有的 OutputStream 创建是否带自动行刷新的 PrintWriter。

自动行刷新:指每调用一次println()方法,会强制刷新缓冲。会增加写出次数,从而降低IO性能。因此,对于及时性要求不高的系统不推荐使用

PrintWriter(String fileName) 创建具有指定文件名称且不带自动行刷新的新 PrintWriter。
PrintWriter(String fileName, String csn) 创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out) 创建不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out, boolean autoFlush) 创建新 PrintWriter。
  • 常用方法

Properties

概念

      Properties类是Map集合的实现类,表示了一个持久的属性集,具备键值对的特征,位于java.util包下。Properties类常常用于读取和加载属性配置文件(以.properties结尾的文件)。如下所示:db.properties

url=jdbc:mysql://localhost:3306/test
driver=com.mysql.cj.jdbc.driver
username=root
password=root

      注意事项:

1.一行只能书写一个配置,每个配置包含key-value键值对,以等号或者空格进行分隔。
2.不支持中文,如果输入了中文,则会将中文自动转换为对应的Unicode码。
3.注释使用#

源码

public class Properties extends Hashtable<Object,Object> {
    private static final long serialVersionUID = 4112578634029874840L;
    protected Properties defaults;

    public Properties() {
        this(null);
    }

    public Properties(Properties defaults) {
        this.defaults = defaults;
    }

    public synchronized Object setProperty(String key, String value) {
        return put(key, value);
    }    
    //......
}

构造方法

Properties() 创建一个无默认值的空属性列表。
Properties(Properties defaults) 创建一个带有指定默认值的空属性列表。

常用方法

void load(InputStream in)

void load(Reader reader)

 从输入流中读取属性列表(键和元素对)。

 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。

String getProperty(String key) 用指定的键在此属性列表中搜索属性。如果不存在对应的属性值,则返回null
String getProperty(String key, String defaultValue) 用指定的键在此属性列表中搜索属性。如果不存在对应的属性值,则返回defaultValue

示例

      读取上面的db.properties文件代码如下所示:

public class PropertiesDemo {
    public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
        //相当于类路径(src下)下去查询文件并返回该文件的资源输入流
        InputStream in = PropertiesDemo.class.getClassLoader().getResourceAsStream("db.properties");
        properties.load(in);
		
        System.out.println(properties.getProperty("url"));
        System.out.println(properties.getProperty("driver"));
        System.out.println(properties.getProperty("username"));
        System.out.println(properties);
    }
}
输出结果:
jdbc:mysql://localhost:3306/test
com.mysql.cj.jdbc.driver
root
root
发布了131 篇原创文章 · 获赞 39 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_35507234/article/details/97390276