我们先来认识狭义上的?件(file)。针对硬盘这种持久化存储的I/O设备,当我们想要进?数据保存时,往往不是保存成?个整体,?是独?成?个个的单位进?保存,这个独?的单位就被抽象成?件的概念,就类似办公桌上的?份份真实的?件?般。
?件除了有数据内容之外,还有?部分信息,例如?件名、?件类型、?件??等并不作为?件的数据?存在,我们把这部分信息可以视为?件的元信息。
如何在?件系统中如何定位我们的?个唯?的?件就成为当前要解决的问题,但这难不倒计算机科学家,因为从树型结构的?度来看,树中的每个结点都可以被?条从根开始,?直到达的结点的路径所描述,?这种描述?式就被称为?件的绝对路径(absolute path)。
除了可以从根开始进?路径的描述,还有相对路径,先指定一个”当前目录“/ “工作目录”/"基准目录“,从当前目录出发,找到目标文件。
在实际开发中用的更多的是相对路径
1.文本文件:是按照”文本“ / 字符串方式来理解文件内容(文本文件里面的二进制内容都是表示的字符串),进一步的,可以认为,二进制文件的内容,都是合法的字符(字符编码/普通字母/汉字)
2.二进制文件:没有上述限制,这里的内容任何数据都可以
如何判断呢?
使用记事本打开文件,如果是乱码,就是二进制文件,否者是文本文件
Java 中通过 java.io.File 类来对?个?件(包括?录)进?抽象的描述。注意,有 File 对象,
并不代表真实存在该?件。
我们先来看看 File 类中的常?属性、构造?法和?法
相对路径:
public class Test1 {
public static void main(String[] args) throws IOException {
// File file = new File("D:\\java_cc\\javase\\IODemo/11.txt");
//ctrl+D直接复制上一行内容
File file = new File("./11.txt");
System.out.println(file.exists());
System.out.println(file.getParent());
System.out.println(file.getName());
System.out.println(file.getPath());
System.out.println(file.getAbsoluteFile());
System.out.println(file.getCanonicalFile());
}
}
运行结果
true
.
11.txt
.\11.txt
D:\java_cc\javase\IODemo.\11.txt
D:\java_cc\javase\IODemo\11.txt
绝对路径:
public class Test1 {
public static void main(String[] args) throws IOException {
File file = new File("D:\\java_cc\\javase\\IODemo/11.txt");
//ctrl+D直接复制上一行内容
System.out.println(file.exists());
System.out.println(file.getParent());
System.out.println(file.getName());
System.out.println(file.getPath());
System.out.println(file.getAbsoluteFile());
System.out.println(file.getCanonicalFile());
}
}
运行结果:
true
D:\java_cc\javase\IODemo
11.txt
D:\java_cc\javase\IODemo\11.txt
D:\java_cc\javase\IODemo\11.txt
D:\java_cc\javase\IODemo\11.txt
对比相对路径和绝对路径,get的运行结果有所差异
public class Test2 {
public static void main(String[] args) throws IOException {
File file = new File("22.txt");//开始不存在
System.out.println(file.exists());
System.out.println(file.isDirectory());
System.out.println(file.isFile());
System.out.println(file.createNewFile());
System.out.println(file.exists());
System.out.println(file.isDirectory());
System.out.println(file.isFile());
System.out.println(file.createNewFile());
}
}
运行结果
false
false
false
true
true
false
true
false
public class IODemo3 {
public static void main(String[] args) throws InterruptedException {
File file = new File("./test.txt");
// boolean ret = file.delete();
file.deleteOnExit();
Thread.sleep(5000);
// System.out.println(ret);
}
}
程序运行结束后被删除
public class Test3 {
public static void main(String[] args) {
File file = new File("some-dir");
System.out.println(file.isDirectory());
System.out.println(file.isFile());
System.out.println(file.mkdir());
System.out.println(file.isDirectory());
System.out.println(file.isFile());
}
}
运行结果:
false
false
true
true
false
创建多级目录
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
File dir = new File("some-parent\\some-dir"); // some-parent 和 so
System.out.println(dir.isDirectory());
System.out.println(dir.isFile());
System.out.println(dir.mkdirs());
System.out.println(dir.isDirectory());
System.out.println(dir.isFile());
}
}
运行结果:
false
false
true
true
false
创建some-parent下的some-dir目录
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("some-file.txt"); // 要求 some-file.txt 得存在
File dest = new File("dest.txt"); // 要求 dest.txt 不存在
System.out.println(file.exists());
System.out.println(dest.exists());
System.out.println(file.renameTo(dest));
System.out.println(file.exists());
System.out.println(dest.exists());
}
}
运行结果:
true
false
true
false
true
流是操作系统提供的概念
Java标准库对于流进行了一系列的封装,提供了一组类来负责进行这些工作
大致分为两大类别:
1.字节流:以字节为单位进行读写,一次最少读写一个字节
代表类:InputStream(输入),OutputStream(输出)
2.字符流:以字符为单位进行读写,比如,如果utf8表示汉字,三个字节就是一个汉字,每次读写都得是以三个字节为一个单位,来进行读写,不能一次读写半个汉字
代表类:Reader(输入) Writer(输出)
方法
说明
InputStream只是?个抽象类,要使?还需要具体的实现类。关于InputStream的实现类有很多,基
本可以认为不同的输?设备都可以对应?个InputStream类,我们现在只关?从?件中读取,所以使?FileInputStream
构造方法
?例1
将?件完全读完的两种?式。相?较??,后?种的IO次数更少,性能更好。
import java.io.*;
// 需要先在项??录下准备好?个 hello.txt 的?件,??填充 "Hello" 的内容
public class Main {
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
while (true) {
int b = is.read();
if (b == -1) {
// 代表?件已经全部读完
break;
}
System.out.printf("%c", b);
}
}
}
}
import java.io.*;
// 需要先在项??录下准备好?个 hello.txt 的?件,??填充 "Hello" 的内容
public class Main {
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
byte[] buf = new byte[1024];
int len;
while (true) {
len = is.read(buf);
if (len == -1) {
// 代表?件已经全部读完
break;
}
for (int i = 0; i < len; i++) {
System.out.printf("%c", buf[i]);
}
}
}
}
}
?例2
这?我们把?件内容中填充中?看看,注意,写中?的时候使?UTF-8编码。hello.txt中填写"你好中国"
注意:这?我利?了这?个中?的UTF-8编码后?度刚好是3个字节和?度不超过1024字节的现
状,但这种?式并不是通?的
import java.io.*;
// 需要先在项??录下准备好?个 hello.txt 的?件,??填充 "你好中国" 的内容
public class Main {
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
byte[] buf = new byte[1024];
int len;
while (true) {
len = is.read(buf);
if (len == -1) {
// 代表?件已经全部读完
break;
}
// 每次使? 3 字节进? utf-8 解码,得到中?字符
// 利? String 中的构造?法完成
// 这个?法了解下即可,不是通?的解决办法
for (int i = 0; i < len; i += 3) {
String s = new String(buf, i, 3, "UTF-8");
System.out.printf("%s", s);
}
}
}
}
}
上述例?中,我们看到了对字符类型直接使?InputStream进?读取是?常?烦且困难的,所以,我们使??种我们之前?较熟悉的类来完成该?作,就是Scanner类。
import java.io.*;
import java.util.*;
// 需要先在项??录下准备好?个 hello.txt 的?件,??填充 "你好中国" 的内容
public class Main {
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
try (Scanner scanner = new Scanner(is, "UTF-8")) {
while (scanner.hasNext()) {
String s = scanner.next();
System.out.print(s);
}
}
}
}
}
说明
OutputStream同样只是?个抽象类,要使?还需要具体的实现类。我们现在还是只关?写??件
中,所以使?FileOutputStream
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
os.write('H');
os.write('e');
os.write('l');
os.write('l');
os.write('o');
// 不要忘记 flush
os.flush();
}
}
}
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
byte[] b = new byte[] {
(byte)'G', (byte)'o', (byte)'o', (byte)'d'
};
os.write(b);
// 不要忘记 flush
os.flush();
}
}
}
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
byte[] b = new byte[] {
(byte)'G', (byte)'o', (byte)'o', (byte)'d', (byte)'B', (byte)'a'
};
os.write(b, 0, 4);
// 不要忘记 flush
os.flush();
}
}
}
mport java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
String s = "Nothing";
byte[] b = s.getBytes();
os.write(b);
// 不要忘记 flush
os.flush();
}
}
}
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
String s = "你好中国";
byte[] b = s.getBytes("utf-8");
os.write(b);
// 不要忘记 flush
os.flush();
}
}
}
上述,我们其实已经完成输出?作,但总是有所不?便,我们接来下将OutputStream处理下,使?PrintWriter类来完成输出,因为PrintWriter类中提供了我们熟悉的print/println/printf?法
OutputStream os = ...;
OutputStreamWriter osWriter = new OutputStreamWriter(os, "utf-8"); // 告诉
PrintWriter writer = new PrintWriter(osWriter);
// 接下来我们就可以?便的使? writer 提供的各种?法了
writer.print("Hello");
writer.println("你好");
writer.printf("%d: %s\n", 1, "没什么");
// 不要忘记 flush
writer.flush();
示例:
import java.io.*;public class Main {
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
try (OutputStreamWriter osWriter = new OutputStreamWriter(os, "UTF-8
try (PrintWriter writer = new PrintWriter(osWriter)) {
writer.println("我是第??");
writer.print("我的第??\r\n");
writer.printf("%d: 我的第三?\r\n", 1 + 1);
writer.flush();
}
}
}
}
}