1.File
在计算机中目录结构如下:
而File就表示一个目录或者一个普通文件。
File表示目录:
File表示普通文件:
我们先来看File的构造方法:
构造器 | 描述 |
---|---|
File(File parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例 |
File(String pathname) | 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径 |
File(String parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例 |
File(URI uri) | 通过uri来创建一个File 实例 |
但是通常都用File(String pathname)这个构造器来创建File对象,其他的构造器比较少用。
创建File实例:
public class CreateFileObject {
public static void main(String[] args) {
File file = new File("blog/dir/tmp.txt");
}
}
File类常用的方法基本都在下面了:
返回类型 | 方法名 | 描述 |
---|---|---|
String | getParent() | 返回 File 对象的父目录文件路径 |
String | getName() | 返回 FIle 对象的纯文件名称 |
String | getPath() | 返回 File 对象的文件路径 |
String | getAbsolutePath() | 返回 File 对象的绝对路径 |
String | getCanonicalPath() | 返回 File 对象的修饰过的绝对路径 |
boolean | exists() | 判断 File 对象描述的文件是否真实存在 |
boolean | isDirectory() | 判断 File 对象代表的文件是否是一个目录 |
boolean | isFile() | 判断 File 对象代表的文件是否是一个普通文件 |
boolean | createNewFile() | 根据 File 对象,自动创建一个空文件。成功创建后返回 true |
boolean | delete() | 根据 File 对象,删除该文件。成功删除后返回 true |
void | deleteOnExit() | 根据 File 对象,标注文件将被删除,删除动作会到JVM 运行结束时才会进行 |
String[] | list() | 返回 File 对象代表的目录下的所有文件名 |
File[] | listFiles() | 返回 File 对象代表的目录下的所有文件,以 File 对象表示 |
boolean | mkdir() | 创建 File 对象代表的目录 |
boolean | mkdirs() | 创建 File 对象代表的目录,如果必要,会创建中间目录 |
boolean | renameTo(File dest) | 进行文件改名 |
boolean | canRead() | 判断用户是否对文件有可读权限 |
boolean | canWrite() | 判断用户是否对文件有可写权限 |
补充一个文件路径的小知识:
. | 表示当前路径 |
.. | 表示上级目录 |
mkdirs()、getName()、getParent()、getPath()、getAbsolutePath()、getCanonicalPath()的使用
目录结构:
代码:
public class MethodTest1 {
public static void main(String[] args) throws IOException {
File file = new File("io/src/blog/dir/./tmp");
//创建dir目录并且会创建tmp这个目录
file.mkdirs();
//获取文件的名称
String filename = file.getName();
System.out.println("文件名->: " + filename);
//获取父目录的相对路径
String parent = file.getParent();
System.out.println("父目录的相对路径->: " + parent);
//获取相对路径
String path = file.getPath();
System.out.println("相对路径->: " + path);
//获取绝对路径
String absPath = file.getAbsolutePath();
System.out.println("绝对路径->: " + absPath);
//获取修饰后的绝对路径
String absPathMod = file.getCanonicalPath();
System.out.println("修饰后的绝对路径->: " + absPathMod);
}
}
结果:
文件名->: tmp
父目录的相对路径->: io\src\blog\dir\.
相对路径->: io\src\blog\dir\.\tmp
绝对路径->: H:\gitee\IdeaProgram\JavaEE\io\src\blog\dir\.\tmp
修饰后的绝对路径->: H:\gitee\IdeaProgram\JavaEE\io\src\blog\dir\tmp
exists()、isFile()、isDirectory()、list()、listFiles()的使用
目录结构:
代码:
public class MethodTest2 {
public static void main(String[] args) {
File file = new File("io/src/blog/dir/./tmp");
//判断文件是否存在
boolean isExists = file.exists();
System.out.println("文件是否存在->: " + isExists);
//判断是否为普通文件,比如xxx.txt
boolean isFile = file.isFile();
System.out.println("是否为普通文件->: " + isFile);
//判断是否是一个目录
boolean isDirctory = file.isDirectory();
System.out.println("是否为一个目录->: " + isDirctory);
//列出这个目录下面所有的文件,以String表示
String[] list = file.list();
System.out.println("tmp目录下所有的文件->: " + Arrays.toString(list));
//列出这个目录下面所有的文件,以File对象表示
File[] files = file.listFiles();
System.out.println("tmp目录下所有的文件->: " + Arrays.toString(files));
}
}
结果:
文件是否存在->: true
是否为普通文件->: false
是否为一个目录->: true
tmp目录下所有的文件->: [a.txt, b.txt]
tmp目录下所有的文件->: [io\src\blog\dir\.\tmp\a.txt, io\src\blog\dir\.\tmp\b.txt]
canRead()、canWrite()、renameTo()、delete()的使用
代码:
public class MethodTest3 {
public static void main(String[] args) throws IOException {
File file = new File("io/src/blog/dir/./tmp");
//判断是否可读
boolean canRead = file.canRead();
System.out.println("是否可读->: " + canRead);
//是否可写
boolean canWrite = file.canWrite();
System.out.println("是否可写->: " + canWrite);
//改名为file_tmp
file.renameTo(new File("io/src/blog/dir/./file_tmp"));
//删除下面的一个.txt后缀文件
File removeFile = new File("io/src/blog/dir/./file_tmp/a.txt");
boolean ret = removeFile.delete();
System.out.println("是否删除成功->: " + ret);
}
}
结果:
是否可读->: true
是否可写->: true
是否删除成功->: true
2.InputStream
InputStream可以认为是输入设备和内存(Memory)之间的一个流,而且数据流向是从输入设备(input device)到内存(Memory)的。
我们创建了一个InputStream,就相当于创建了一个输入流对象,可以从输入设备上读数据到内存中。
InputStream官方声明:
public abstract class InputStream
extends Object
implements Closeable
常用的方法:
方法 | 描述 |
---|---|
abstract int read() | 从输入流读取一个字节(byte)的数据,并返回 |
int read(byte[] b ) | 从输入流读取一些字节并存到b这个数组中 (读取多少个字节,取决于b数组的大小和文件中数据有多少) |
int read(byte[] b, int off, int len) | 最多读取len个字节到b数组中,从指定数组下标开始 |
void close() | 关闭输入流,释放资源 |
因为InputStream是抽象类,所以我们还得找这个类的子类。
InputStream的子类比较多,这里以FileInputStream举例,即文件流,也是经常使用的一个流。
文件流的输入设备就是磁盘(disk),更具体一点就是文件(File)。
FileInputStream的声明:
public class FileInputStream extends InputStream
FileInputStream常用的构造器:
构造器 | 描述 |
---|---|
FileInputStream(File file) | 根据File对象创建一个输入流 |
FileInputStream(String name) | 根据文件名创建一个输入流 |
下面是文件中的数据:
文件:filetest.txt
abcdefghijk
read()方法使用:
public static void test1() {
InputStream inputStream = null;
try {
//创建FileInputStream输入流对象
inputStream = new FileInputStream("io/filetest.txt");
//读取一个字节的数据,返回-1表示到达文件末尾
int data = inputStream.read();
//输出
System.out.println("data->: " + data);
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
data->: 97
int read(byte[] b)方法使用
public static void test2() {
InputStream inputStream = null;
try {
//创建FileInputStream输入流对象
inputStream = new FileInputStream("io/filetest.txt");
//读取数据到bytes数组中,返回读取到的字节数,返回-1表示到文件末尾,
byte[] bytes = new byte[32];
int ret = inputStream.read(bytes);
//输出
System.out.println(Arrays.toString(bytes));
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
[97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
int read(byte[] b, int off, int len)方法使用:
public static void test3() {
InputStream inputStream = null;
try {
//创建FileInputStream输入流对象
inputStream = new FileInputStream("io/filetest.txt");
//读取数据写到bytes数组指定的位置
byte[] b = new byte[32];
int ret2 = inputStream.read(b, 10, 10);
//输出
System.out.println(Arrays.toString(b));
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
不知道你有没有觉得上面的try…catch…finally这种写法有点繁琐,说白了就是丑😣。
上面的写法跟下面的等价。
public static void test() throws IOException {
try (InputStream inputStream = new FileInputStream("io/filetest.txt")) {
//读取一个字节的数据,返回-1表示到达文件末尾
int data = inputStream.read();
//输出
System.out.println("data->: " + data);
} catch (IOException e) {
e.printStackTrace();
}
}
这种写法叫,try-with-resource可以自动帮助我们释放资源,即自动调用close()方法。
- 当发生异常时,能自动调用close()方法,帮助我们释放资源。
但是并不是所有类都能这样用,只有实现AutoCloseable或者Closeable接口的类,并且重写close()方法才能用这种语法。
AutoCloseable和Closeable的关系:
public interface Closeable
extends AutoCloseable
底层释放资源伪代码如下:
AutoCloseable o = (AutoCloseable)inputStream;
o.close();
- 这里只是伪代码,帮助我们理解,而底层实现跟这个不一样。
3.OutputStream
OutputStream是从内存(Memory)到输出设备(output device)的一个流,且流向从内存到输出设备的。
官方声明:
public abstract class OutputStream
extends Object
implements Closeable, Flushable
常用的方法:
方法 | 描述 |
---|---|
abstract void write(int b) | 写入低八位的数据,后24位的数据是不会写入的 |
void write(byte[] b) | 将b数组中的全部字节写入到文件中 |
void write(byte[] b, int off, int len) | 从off这个位置开始,将数组b的字节写到文件中 |
void close() | 关闭输出流,释放资源 |
void flush() | 刷新内存中的缓冲区,把缓冲区的数据写入文件中 |
调用输出设备flush()方法执行的过程如下:
OutputStream也是抽象类,最常用的子类是FileOutputStream(文件输出流)。
FileOutputStream常用的构造器:
构造器 | 描述 |
---|---|
FileOutputStream(File file) | 根据File对象创建一个输出流 |
FileOutputStream(String name) | 根据文件名创建一个输出流 |
FileOutputStream(File file, boolean append) | 根据File对象创建一个输出流 并且指定是否可追加 |
FileOutputStream(String name, boolean append) | 根据文件名创建一个输出流 并且指定是否可追加 |
example:
public class OutputStreamTest {
public static void main(String[] args) throws IOException {
//文件路径
String path = "./io/filetest.txt";
//创建文件输出流对象
try ( FileOutputStream fileOutputStream = new FileOutputStream(path)) {
//调用wirite(int b)方法, 将
fileOutputStream.write(1);
//调用write(byte[] b)方法,将byte数组里的每个字节写入文件
fileOutputStream.write(new byte[]{2, 3, 4});
}
}
}
文件内容:
在idea中显示的内容:
ascii码表:
-
因为文件是二进制文件,以字节为单位,1对应了中的SOH
2对应STX,3对应ETX,4对应EOT。 -
记事本是不会显示控制字符的,会用其他的字符代替,所以就出现了乱码。而在idea中打开就可以显示每个字节对应的字符。
追加的方式打开文件并写入byte数组:
public class OutputStreamTest2 {
public static void main(String[] args) {
appendConstructorTest();
}
public static void appendConstructorTest() {
//路径
String path = "io/filetest.txt";
//以追加的方式打开文件输出流
try (FileOutputStream fileOutputStream = new FileOutputStream(path, true)) {
//把byte数组写入文件
fileOutputStream.write(new byte[]{5, 6, 7});
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
寄语
清风拂来头发飞扬,指间跳动理想锋芒。