IO
|字数总计:3.1k|阅读时长:13分钟|阅读量:
文件
创建文件
主要方法:
new File(String pathname)
:根据路径构建一个 File 对象
1 2 3 4 5
| public void create01() throws IOException { String pathname = "/Users/suweijin/Desktop/test.txt"; File file = new File(pathname); file.createNewFile(); }
|
new File(File parent,String child)
:根据父目录文件 + 子路径构建
1 2 3 4 5 6
| public void create02() throws IOException { File parent = new File("/Users/suweijin/Desktop/"); String child = "test.txt"; File file = new File(parent,child); file.createNewFile(); }
|
new File(String parent,String child)
:根据父目录 + 子路径构建
1 2 3 4 5 6
| public void create03() throws IOException { String parent = "/Users/suweijin/Desktop/"; String child = "test.txt"; File file = new File(parent, child); file.createNewFile(); }
|
获取文件信息
部分方法:
getName()
:获取文件名
getAbsolutePath()
:获取文件绝对路径
getParent()
:获取文件父目录
length()
:获取文件大小,单位字节
exists()
:判断文件是否存在
isFile()
:判断是否是一个文件
isDirectory()
:判断是否是一个目录
1 2 3 4 5 6 7 8 9 10
| public void info() { File file = new File("/Users/suweijin/Desktop/test.txt"); System.out.println(file.getName()); System.out.println(file.getAbsolutePath()); System.out.println(file.getParent()); System.out.println(file.length()); System.out.println(file.exists()); System.out.println(file.isFile()); System.out.println(file.isDirectory()); }
|
目录操作
mkdir()
:创建一级目录
mkdirs()
:创建多级目录
1 2 3 4
| public void dir() { File file = new File("/Users/suweijin/Desktop/test"); file.mkdirs(); }
|
delete()
:删除空目录或文件
1 2 3 4 5 6 7 8 9 10 11 12
| public void dir() { File file = new File("/Users/suweijin/Desktop/test"); if (file.exists()){ if (file.delete()){ System.out.println("删除成功"); }else { System.out.println("删除失败"); } }else { System.out.println("目录不存在"); } }
|
IO 流
文件在程序中以流的形式进行操作。
分类
- 按操作单位划分:字节流和字符流。
- 按流向划分:输入流和输出流。
- 按角色划分:节点流和处理流/包装流。
抽象基类 |
字节流 |
字符流 |
输入流 |
InputStream |
Reader |
输出流 |
OuputStream |
Writer |
- Java 中的 IO 流涉及 40 多个类,都是从以上四个抽象基类派生而来。
- 由这四个类派生出来的子类名都是以父类名作为后缀。
字节流
1)FileInputStream
构造方法:
FilelnputStream(File file)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过 File 对象指定。
FileInputStream(FileDescriptor fdObj)
通过使用文件描述符 fdObj 创建一个 FileInputStream,该文件描述符表示到实际文件的现有连接。
FileInputStream(String name)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过路径名指定。
普通方法:
int available()
:返回输入流中剩余未被读取的字节数;
void close()
:关闭此文件输入流并释放与流有关的系统资源;
void finalize()
:可以在输入流对象被回收时调用其 close 方法;
FileChannel getChannel()
:返回与此输入流有关的唯一 FileChannel 对象,该对象提供了对底层 I/O 操作的支持,允许对文件进行更低级别的操作;
FileDescriptor getFD()
:返回此连接的 FileDescriptor 对象;
int read()
:从输入流中读取一个字节数据,将数据存储在 int 类型并返回,若返回 -1
表示读取完毕;
int read(byte[] b)
:从输入流中读取最多 b.length
个字节到 byte 数组中。返回实际读取字节数,若返回 -1
表示读取完毕;
int read(byte[] b, int off, int len)
:读取最多 len 个字节到 byte 数组中,off 表示在字节数组中存储数据的起始偏移量;
long skip(long n)
:跳过并丢弃输入流中 n 个字节数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public void read() throws IOException { String filepath = "/Users/suweijin/Desktop/test.txt"; FileInputStream fileInputStream = null; int data; try { fileInputStream = new FileInputStream(filepath); while ((data = fileInputStream.read()) != -1) { System.out.print((char) data); } } catch (FileNotFoundException e) { System.out.print("文件不存在"); } finally { assert fileInputStream != null; fileInputStream.close(); } }
|
如果文件存在中文,由于一个中文不止一个字节,而上述代码每读取一个字节就进行输出,必然导致乱码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public void read() throws IOException { String filepath = "/Users/suweijin/Desktop/test.txt"; FileInputStream fileInputStream = null; byte[] data = new byte[10]; int len; try { fileInputStream = new FileInputStream(filepath); while ((len = fileInputStream.read(data)) != -1) { System.out.print(new String(data, 0, len)); } } catch (FileNotFoundException e) { System.out.print("文件不存在"); } finally { assert fileInputStream != null; fileInputStream.close(); } }
|
如果文件存在中文,很有可能造成乱码。因为中文还是可能被拆分在两次读取中。
2)FileOuputStream
构造方法和 FilelnputStream
一致,同时新增了以下方法:
FileOutputStream(String name, boolean append)
FileOutputStream(File file, boolean append)
append
表示是否以追加的方式写入文件,默认 flase
。
普通方法:
close()
;
finalize()
;
getChannel()
;
getFD()
;
write(byte[] b)
:将 b.length
个字节从 byte 数组中写入文件输出流中;
write(byte[] b, int off, int len)
:将 byte 数组中从偏移量 off 开始的 len 个字节写入文件输出流;
write(int b)
:将指定字节写入文件输出流。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public void write() throws IOException { String filepath = "/Users/suweijin/Desktop/test.txt"; FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(filepath); String str = "Hello World"; fileOutputStream.write(str.getBytes()); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { assert fileOutputStream != null; fileOutputStream.close(); } }
|
文件拷贝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public void copy() throws IOException { FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; String oldPath = "/Users/suweijin/Documents/img/blog-img/painting-3995999_1280.jpg"; String newPath = "/Users/suweijin/Desktop/test.jpg"; try { fileInputStream = new FileInputStream(oldPath); fileOutputStream = new FileOutputStream(newPath); byte[] data = new byte[1024]; int len; while ((len = fileInputStream.read(data)) != -1) { fileOutputStream.write(data, 0, len); } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { assert fileInputStream != null; fileInputStream.close(); assert fileOutputStream != null; fileOutputStream.close(); } }
|
字符流
1)FileReader
构造方法:
new FileReader(File file)
new FileReader(String name)
new FileReader(FileDescriptor fdObj)
相关方法:
int read()
:每次读取一个字符,并返回该字符,文件结束返回 -1
;
int read(char[] cbuf)
:最多读取字符数组大小的数据,返回成功读取的字符数,文件结束返回 -1
;
int read (CharBuffer target)
:返回成功读取的字符数,如果达到文件末尾,则返回 -1
;
1
| CharBuffer charBuffer = CharBuffer.allocate(1024);
|
int read (char[] cbuf, int offset, int Length)
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public void read() throws IOException { FileReader fileReader = null; try { fileReader = new FileReader("/Users/suweijin/Desktop/test.txt"); char[] cbuff = new char[10]; int len; while ((len = fileReader.read(cbuff)) != -1) { System.out.print(new String(cbuff, 0, len)); } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { assert fileReader != null; fileReader.close(); } }
|
2)FileWriter
构造方法和 FileOuputStream
一致。
相关方法:
write(int)
:写入单个字符;
write(String)
:写入字符串;
write(String, off, len)
:写入字符串的指定部分;
write(char[])
:写入字符数组;
write(char[], off, len)
:写入字符数组的指定部分。
1 2 3 4 5 6 7 8 9 10 11 12
| public void write() throws IOException { FileWriter fileWriter = null; try { fileWriter = new FileWriter("/Users/suweijin/Desktop/test.txt"); fileWriter.write("你好"); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { assert fileWriter != null; fileWriter.close(); } }
|
FileWriter
使用后,必须进行关闭(close
)或刷新(flush
),否则写入不到指定的文件。
节点流/处理流
- 节点流:从一个特定的数据源读写数据,如
FileReader
、 FileWriter
。
- 处理流(包装流):包装已存在的流,为程序提供更强大的读写功能,如
BufferedReader
、BufferedWriter
。
以 BufferedReader
为例,此类内部存在一个 Reader
变量,可以给 BufferedReader
传入某个 Reader
的子类,BufferedReader
类中的代码逻辑中实现了对传入流的包装,以提供更丰富的功能。
BufferedReader
和 BufferedWriter
属于字符流,是以字符为单位来读写数据的。不要用它去操作二进制文件(视频、图片、doc、pdf 等),可能造成文件损坏。
BufferedInputStream
和 BufferedOuputStream
属于字节处理流。
字符处理流
1)BufferedReader
1 2 3 4 5 6 7 8 9 10
| public void read() throws IOException { FileReader fileReader = new FileReader("/Users/suweijin/Desktop/test.txt"); BufferedReader bufferedReader = new BufferedReader(fileReader); String line; while ((line = bufferedReader.readLine()) != null) { System.out.println(line); } bufferedReader.close(); }
|
2)BufferedWriter
1 2 3 4 5 6 7 8
| public void write() throws IOException { FileWriter fileWriter = new FileWriter("/Users/suweijin/Desktop/test.txt"); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); bufferedWriter.write("Hello"); bufferedWriter.newLine(); bufferedWriter.write("World"); bufferedWriter.close(); }
|
字节处理流 BufferedInputStream
和 BufferedOuputStream
同理。
对象处理流
需求:将 int i = 100
这个 int
数据保存到文件中,不是只保存 100
这个数字,而是保存 int 100
。并且能够从文件中直接恢复 int = 100
。
对象处理流能够将基本数据类型
或者对象
保存到文件并能够从文件中恢复。前提对象必须实现序列化
。
对象处理流本质是字节处理流,需要传入 InputStream
或 OutputStream
的子类。
1)ObjectOutputStream
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public class App { public static void main(String[] args) throws IOException { String filepath = "/Users/suweijin/Desktop/data.dat"; FileOutputStream fileOutputStream = new FileOutputStream(filepath); ObjectOutputStream oos = new ObjectOutputStream(fileOutputStream); oos.writeInt(100); oos.writeBoolean(true); oos.writeChar('a'); oos.writeDouble(6.6); oos.writeUTF("Hello,World"); oos.writeObject(new User("围巾", 24)); oos.close(); } }
class User implements Serializable { private String name; private int age;
public User(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
|
2)ObjectInputStream
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Test public void read() throws IOException, ClassNotFoundException { String filepath = "/Users/suweijin/Desktop/data.dat"; FileInputStream fileInputStream = new FileInputStream(filepath); ObjectInputStream ois = new ObjectInputStream(fileInputStream); System.out.println(ois.readInt()); System.out.println(ois.readBoolean()); System.out.println(ois.readChar()); System.out.println(ois.readDouble()); System.out.println(ois.readUTF()); System.out.println(ois.readObject()); ois.close(); }
|
1 2 3 4 5 6
| 100 true a 6.6 Hello,World User{name='围巾', age=24}
|
- 虽然是字节处理流,但经过包装后是可以正确处理中文的;
- 如果类中成员变量是一个对象,该对象所属类也需实现序列化;
- 对于
static
和 transient
修饰的变量,不会被序列化;
- 如果某个类实现了序列化,它所有的子类默认也实现了序列化。
转换流
InputStreamReader
:用于将字节输入流转换为字符输入流,属于字符流(Reader 的子类)。
InputStreamReader
:用于将字节输出流转换为字符输出流,属于字符流(Writer 的子类)。
不同文件可能使用不同的字符集,使用之前的流进行读写可能导致乱码。可以通过转换流指定输入输出所使用的字符集,从而避免乱码。
1)InputStreamReader
1 2 3 4 5 6 7 8
| public void trans() throws IOException { FileInputStream fileInputStream = new FileInputStream("/Users/suweijin/Desktop/test.txt"); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String s = bufferedReader.readLine(); System.out.println(s); bufferedReader.close(); }
|
2)InputStreamReader
1 2 3 4 5 6
| public void trans() throws IOException { FileOutputStream fileOutputStream = new FileOutputStream("/Users/suweijin/Desktop/test.txt"); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8); outputStreamWriter.write("围巾"); outputStreamWriter.close(); }
|
标准输入/输出流
System.in
:类型是 InputStream
字节输入流,具体使用 BufferedInputStream
处理流。
System.out
:类型是 PrintStream
字节输出流。
打印流
PrintStream
:字节输出流。
PrintWriter
:字符输出流。
1)PrintStream
1 2 3 4
| PrintStream out = System.out; out.print("hello"); out.close();
|
1 2 3
| System.setOut(new PrintStream("/Users/suweijin/Desktop/test.txt")); System.out.print("hello");
|
2)PrintWriter
1 2 3 4
| PrintWriter printWriter = new PrintWriter(System.out); printWriter.write("hello"); printWriter.close();
|
1 2 3 4 5
| FileWriter fileWriter = new FileWriter("/Users/suweijin/Desktop/test.txt"); PrintWriter printWriter = new PrintWriter(fileWriter); printWriter.write("world"); printWriter.close();
|
读写配置文件
配置文件:
传统方式:
1 2 3 4 5 6 7 8 9 10
| public static void main(String[] args) throws IOException { FileReader fileReader = new FileReader("src/main/java/test.properties"); BufferedReader bufferedReader = new BufferedReader(fileReader); String line; while ((line = bufferedReader.readLine()) != null) { String[] split = line.split("="); System.out.println("key: " + split[0] + " value: " + split[1]); } bufferedReader.close(); }
|
1 2
| key: name value: scarf key: account value: zero
|
使用 java.util.Properties
类:
常见方法:
load
:加载配置文件到 Properties
对象;
list
:可以传入打印流,将数据显示到指定位置(例如显示器或文件);
getProperty(key)
:根据键获取值;
setProperty(key, value)
:设置键值对到 Properties
对象;
store
:将 Properties
对象中的键值对存储到配置文件,如果含有中文,会存储为 unicode
码。
1 2 3 4 5 6 7 8 9 10 11
| public static void main(String[] args) throws IOException { String filepath = "src/main/java/test.properties"; FileReader fileReader = new FileReader(filepath); Properties properties = new Properties(); properties.load(fileReader); properties.list(System.out); System.out.println(properties.get("name")); properties.setProperty("account", "0"); properties.setProperty("age", "66"); properties.store(new FileWriter(filepath), null); }
|