文件
什么是文件
文件就是保存数据的地方
文件流
文件在程序中是以流的形式来操作的
流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流:数据从数据源(文件)到程序(内存)的路径
输出流:数据从程序(内存)到数据源(文件)的路径、
常用的文件操作
创建文件的三种方式
方式1:
| @Test public void create01() { String filePath = "D:\\Test\\IO\\news1.txt"; File file = new File(filePath); try { file.createNewFile(); System.out.println("文件创建成功!"); } catch (IOException e) { e.printStackTrace(); System.err.println("创建出错了"); } }
|
方式2:
| @Test public void create02() { File parentFile = new File("D:\\Test\\IO\\"); String fileName = "news2.txt"; File file = new File(parentFile, fileName); try { file.createNewFile(); System.out.println("文件创建成功"); } catch (IOException e) { e.printStackTrace(); } }
|
方式3:
| @Test public void create03() { String filePath = "D:\\Test\\IO\\"; String fileName = "news3.txt"; File file = new File(filePath, fileName); try { file.createNewFile(); System.out.println("创建成功"); } catch (IOException e) { e.printStackTrace(); } }
|
获取文件的相关信息
| @Test public void info() { File file = new File("D:\\Test\\IO\\news1.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 创建多级目录,delete 删除空目录
或文件
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 34 35 36 37 38 39 40 41 42 43 44 45 46
| @Test public void m1() { File file = new File("D:\\Test\\IO\\news1.txt"); if (file.exists()) { if (file.delete()) { System.out.println("删除成功!"); } else { System.out.println("删除失败"); } } else { System.err.println("该文件不存在..."); } }
@Test public void m2() { File file = new File("D:\\Test\\IO222"); if (file.exists()) { if (file.delete()) { System.out.println("删除成功"); } else { System.out.println("删除失败"); } } else { System.out.println("该目录不存在..."); } }
@Test public void m3() { File file = new File("D:\\Test\\a\\b"); if (!file.exists()) { if (file.mkdirs()) { System.out.println("创建成功"); } else { System.out.println("创建失败"); } } else { System.out.println("该目录已存在..."); } }
|
IO 流原理及流的分类
Java IO流原理
- I /O 是 Input / Output 的缩写,I/O技术是非常实用的技术,用于数据传输。如 读/写文件,网络通讯等。
- Java程序中,对于数据的输入/输出操作以
"流(stream)"
的方式进行 - java.io 包下提供了各种”流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
- 输入 input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中
- 输出output:将承租(内存)数据输出到磁盘、光盘等存储设备中
IO流—常用的类
InputStream抽象类是所有类字节输入流的超类
InputStream 常用的子类
- FilelnputStream:文件输入流
- BufferedInputStream:缓冲字节输入流
- ObjectlnputStream:对象字节输入流
FilelnputStream 字节输入流
单个字节的读取:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
@Test public void readFile01() throws IOException { String filePath = "D:\\Test\\hello.txt"; int readData = 0; FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(filePath); while ((readData = fileInputStream.read()) != -1) { System.out.print((char) readData); } } catch (IOException e) { e.printStackTrace(); } finally { fileInputStream.close(); } }
|
字节数组方式
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
|
@Test public void readFile02() throws IOException { String filePath = "D:\\Test\\hello.txt"; byte[] buf = new byte[8]; int bufLen = 0; FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(filePath); while ((bufLen = fileInputStream.read(buf)) != -1) { System.out.print(new String(buf, 0, bufLen)); } } catch (IOException e) { e.printStackTrace(); } finally { fileInputStream.close(); } }
|
留空。。
FileOutputStream (字节输出流)
例子:
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
| @Test public void writeFile() throws IOException {
String filePath = "D:\\Test\\a.txt"; FileOutputStream fileOutputStream = null; try {
fileOutputStream = new FileOutputStream(filePath, true);
String str = "hello,world";
fileOutputStream.write(str.getBytes(), 0, str.length());
} catch (IOException e) { e.printStackTrace(); } finally { 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 24 25 26 27 28 29 30 31 32 33
|
@Test public void copy01() throws IOException { String srcfilePath = "D:\\Test\\login.jpg"; String dscfilePath = "D:\\Test\\IO\\login.jpg"; FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(srcfilePath); fileOutputStream = new FileOutputStream(dscfilePath); byte[] buf = new byte[1024]; int readLen = 0; while ((readLen = fileInputStream.read(buf)) != -1) { fileOutputStream.write(buf, 0, readLen); } System.out.println("拷贝成功~"); } catch (IOException e) { e.printStackTrace(); } finally { if (fileInputStream != null) fileInputStream.close(); if (fileOutputStream != null) fileOutputStream.close(); } }
|
FileReader (字符输入流)
单个字符读取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
@Test public void reader01() throws IOException { String filePath = "D:\\Test\\a.txt"; FileReader fileReader = null; int data = 0; try { fileReader = new FileReader(filePath); while ((data = fileReader.read()) != -1) { System.out.print((char) data); } } catch (IOException e) { e.printStackTrace(); } finally { if (fileReader != null) fileReader.close(); } }
|
使用字符数组读取
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
|
@Test public void reader02() throws IOException { String filePath = "D:\\Test\\a.txt"; FileReader fileReader = null; int readLen = 0; char[] buf = new char[10]; try { fileReader = new FileReader(filePath); while ((readLen = fileReader.read(buf)) != -1) { System.out.print(new String(buf, 0, readLen)); } } catch (IOException e) { e.printStackTrace(); } finally { if (fileReader != null) fileReader.close(); } }
|
FileWrite(字符输出流)
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
| @Test public void write01() throws IOException { String filePath = "D:\\Test\\b.txt"; FileWriter fileWriter = null; try { fileWriter = new FileWriter(filePath); String str = "努力努力在努力!";
fileWriter.write(str);
} catch (IOException e) { e.printStackTrace(); } finally { if (fileWriter != null) fileWriter.close(); } System.out.println("执行成功..."); }
|
节点流和处理流
节点流 可以从一个特定的数据源读写数据
,如 FileReader,FileWriter
处理流(也叫包装流
)是 ==连接==在已存在的流(节点流或处理流)纸上,为程序提供更为强大的读写功能,如 BufferedReader、BufferedWriter
览图
节点流和处理流的区别和联系
1.节点流是底层流/低级流,直接跟数据源相接。
2.处理流(包装流)
包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法
来完成输入输出。[源码理解]
3.处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据
源相连[模拟修饰器设计模式]
处理流的功能主要体现在以下两个方面:
性能的提高:主要以增加缓冲的方式来提高输入输出的效率。
操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便
BufferedReader
例子:
| @Test public void read() throws Exception { String path = "D:\\Test\\a.txt"; BufferedReader bufferedReader = new BufferedReader(new FileReader(path)); String readLine; while ((readLine = bufferedReader.readLine()) != null) { System.out.println(readLine); } bufferedReader.close(); }
|
BufferedWriter
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Test public void write() throws IOException { String path = "D:\\Test\\aaaaa.txt"; BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(path)); bufferedWriter.write("hello,我是测试用的·····"); bufferedWriter.newLine(); bufferedWriter.write("H"); bufferedWriter.newLine(); bufferedWriter.write("我是字符数组写入".toCharArray()); bufferedWriter.newLine(); bufferedWriter.write("我是指定写入", 0, 6); bufferedWriter.close(); System.out.println("运行完毕·····"); }
|
文件拷贝(字符流)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
@Test public void copy_() throws IOException { String dirPath = "D:\\Test\\aaaaa.txt"; String newPath = "D:\\Test\\bbbbbb.txt"; BufferedReader bufferedReader = new BufferedReader(new FileReader(dirPath)); BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(newPath)); String line; while ((line = bufferedReader.readLine()) != null) { bufferedWriter.write(line); bufferedWriter.newLine(); } if (bufferedReader != null) bufferedReader.close(); if (bufferedWriter != null) bufferedWriter.close(); }
|
文件拷贝(字节流)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Test public void copy() throws IOException { String dirPath = "D:\\Test\\login.jpg"; String newPath = "D:\\Test\\test.jpg";
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(dirPath)); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(newPath)); byte[] bytes = new byte[1024]; int len = 0; while ((len = bufferedInputStream.read(bytes)) != -1) { bufferedOutputStream.write(bytes, 0, len); } System.out.println("运行结束····"); if (bufferedInputStream != null) bufferedInputStream.close(); if (bufferedOutputStream != null) bufferedOutputStream.close(); }
|
对象处理流
看一个需求
- 将 int num = 100 和这个int 数据保存到文件汇总,注意不是 100 数字,而是 int 100,并且,能够从文件中直接恢复 int 100
- 将 Dog dog = new Dog(“小黄”,3) 这个dog对象保存到文件中,并且能够从文件中恢复
上面的要求,就是能够基本数据类型或者对象进行序列化
和反序列化
操作
序列化和反序列化
- 序列化就是在保存数据时,保存数据的值和数据类型
- 反序列化就是在恢复数据时,恢复数据的值和数据类型
- 需要让某个对象支持序列化机制,则必须让其类时刻序列化的,为了让某个类时刻序列化的,该类必须实现以下两个接口之一:
Serializable
这是一个标记接口Externalizable
ObjectOutputStream 提供序列化功能
ObjectInputStream 提供反序列化功能
ObjectOutputStream (序列化)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
@Test public void write() throws IOException { String filePath = "D:\\Test\\test.dat"; ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(filePath));
outputStream.writeInt(100); outputStream.writeBoolean(true); outputStream.writeChar('J'); outputStream.writeDouble(2.33); outputStream.writeUTF("哈哈哈哈");
outputStream.writeObject(new Dog("小黄", 3));
outputStream.close(); }
|
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 Dog implements Serializable { private String name; private Integer age;
public Dog(String name, Integer age) { this.name = name; this.age = age; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
@Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + '}'; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Test public void test() throws Exception { String filePath = "D:\\Test\\test.dat"; ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(filePath)); System.out.println("int类型:" + inputStream.readInt()); System.out.println("boolean类型:" + inputStream.readBoolean()); System.out.println("char类型:" + inputStream.readChar()); System.out.println("double类型:" + inputStream.readDouble()); System.out.println("String类型:" + inputStream.readUTF()); Object object = inputStream.readObject(); Dog dog = (Dog) object; System.out.println("dog对象:" + object); System.out.println(dog.getName()); inputStream.close(); }
|
注意事项和细节
- 读写顺序要一致
- 要求实现序列化或反序列化对象,需要实现 Serializable
- 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
- 序列化对象时,默认将里面所有属性都进行序列化,但余了staticgtransien修饰的成员
- 序列化对象时,要求里面属性的类型也需要实现序列化接口
- 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化
标准输入输出流
| 类型 | 默认设备 |
---|
System.in 标准输入 | InputStream | 键盘 |
System.out 标准输出 | OutputStream | 显示器 |
代码解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class InputAndOutput { public static void main(String[] args) {
System.out.println(System.in.getClass());
System.out.println(System.out.getClass());
} }
|
转换流(可以设置编码)
介绍
- InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成Reader(字符流)
- OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)
- 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流
- 可以在使用时指定编码格式(比如utf-8, gbk , gb2312, ISO8859-1等)
| @Test public void read() throws IOException { String filePath = "D:\\Test\\a.txt"; InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(filePath), "GBK"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String data; while ((data = bufferedReader.readLine()) != null) { System.out.println(data); } bufferedReader.close(); }
|
OutputStreamWriter
| @Test public void write() throws IOException { String filePath = "D:\\Test\\ccc.txt"; FileOutputStream fileOutputStream = new FileOutputStream(filePath); String charset = "utf8"; OutputStreamWriter osw = new OutputStreamWriter(fileOutputStream, charset); BufferedWriter bufferedWriter = new BufferedWriter(osw); bufferedWriter.write("哈哈哈"); bufferedWriter.close(); System.out.println("按照" + charset + "编码保存文件···"); }
|
打印流(只有输出流,没有输入流)
PrintStream(字节打印流)
代码
| @Test public void printTest() throws IOException { PrintStream out = new PrintStream(System.out); out.println("哈哈哈哈哈"); out.write("哈哈哈2222".getBytes()); out.close();
System.setOut(new PrintStream("D:\\Test\\ces.txt")); System.out.println("看看打印在哪···"); }
|
PrintWrite(字符打印流)
代码:
| @Test public void printTest() throws IOException { PrintStream out = new PrintStream(System.out); out.println("哈哈哈哈哈"); out.write("哈哈哈2222".getBytes()); out.close();
System.setOut(new PrintStream("D:\\Test\\ces.txt")); System.out.println("看看打印在哪···"); }
|
Properties配置文件
| ip=127.0.0.1 user=root pwd=123456
|
传统方法取值
| @Test public void read() throws IOException { BufferedReader bufferedReader = new BufferedReader(new FileReader("src\\test.properties")); String Line = ""; while ((Line = bufferedReader.readLine()) != null) {
String[] split = Line.split("="); System.out.println(split[0] + "的值是:" + split[1]); } }
|
Properties类
专门用于读写配置文件的集合类
配置文件的格式:
键值
键=值
注意:键值对不需要有空格,值不需要用引号一起来。默认类型是String
- Properties的常见方法
- load:加载配置文件的键值对到Properties对象
- list:将数据显示到指定设备
- getProperty(key):根据键获取值
- setProperty(key,value):设置键值对到Properties对象
- store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
使用Properties类
| @Test public void test() throws IOException { Properties properties = new Properties(); properties.load(new FileReader("src\\test.properties")); properties.list(System.out); String user = properties.getProperty("user"); System.out.println("--------"); System.out.println(user); }
|
创建或修改
| @Test public void test() throws IOException { Properties properties = new Properties(); properties.setProperty("charset", "utf8"); properties.setProperty("username", "仅安c"); properties.setProperty("age", "22"); properties.store(new FileOutputStream("src\\test222.properties"), null); System.out.println("保存配置文件成功···"); }
|
码云地址
https://gitee.com/only_ann/java-io-learning-test