目前是怎么存储数据的?弊端是什么?
在内存中存储的数据是用来处理、修改、运算的,不能长久保存。
int a = 10;
int[] array = {1, 2, 3};
List<String> list = new ArrayList<>();
计算机中,有没有一样硬件可以永久存储数据的?
思路:
关于File、IO流,需要学会什么?
File类:
File类创建对象:
| 方法名称 | 说明 |
|---|---|
| public File(String pathname) | 根据文件路径创建文件对象。 |
| public File(String parent, String child) | 从父路径名字符串和子路径名字符串创建文件对象。 |
| public File(File parent, String child) | 根据父路径对应文件对象和子路径名字符串拆创建文件对象。 |
绝对路径和相对路径:
绝对路径:Windows从盘符开始,Linux从根目录开始。
File file = new File("/home/jwu/Desktop/java/code/javasepro/day11-oop-demo/src/com/javase/filedemo1/picture.jpg");
相对路径:相对到工程目录下。
File file1 = new File("day11-oop-demo/src/com/javase/filedemo1/picture.jpg");
Test.java
package com.javase.filedemo1;
import java.io.File;
/**
* 目标:学会创建File对象定位操作系统的文件(文件 文件夹)
*/
public class Test {
public static void main(String[] args) {
// 绝对路径
File file = new File("/home/jwu/Desktop/java/code/javasepro/day11-oop-demo/src/com/javase/filedemo1/picture.jpg");
System.out.println(file.length());
// 相对路径 相对到工程目录下
File file1 = new File("day11-oop-demo/src/com/javase/filedemo1/picture.jpg");
System.out.println(file1.length());
// 判断文件夹是否存在
File path = new File("day11-oop-demo/src/com/javase/filedemo1/");
System.out.println(path.exists());
}
}
File类的判断文件类型、获取文件信息功能:
| 方法名称 | 说明 |
|---|---|
| public boolean isDirectory() | 测试此抽象路径名表示的File是否为文件夹。 |
| public boolean isFile() | 测试此抽象路径名表示的File是否为文件。 |
| public boolean exists() | 测试此抽象路径名表示的File是否存在。 |
| public String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串。 |
| public String getPath() | 将此抽象路径名转换为路径名字符串。 |
| public String getName() | 返回由此抽象路径名表示的文件或文件夹的名称。 |
| public long lastModified() | 返回文件最后修改的时间毫秒值。 |
Test.java
package com.javase.filedemo1;
import java.io.File;
import java.text.SimpleDateFormat;
public class Test {
public static void main(String[] args) {
File file = new File("day11-oop-demo/src/com/javase/filedemo1/picture.jpg");
// 获取绝对路径
// /home/jwu/Desktop/java/code/javasepro/day11-oop-demo/src/com/javase/filedemo1/picture.jpg
System.out.println(file.getAbsoluteFile());
// 获取文件定义的时候使用的路径
// day11-oop-demo/src/com/javase/filedemo1/picture.jpg
System.out.println(file.getPath());
// 获取文件名(带后缀)
// picture.jpg
System.out.println(file.getName());
// 获取文件的字节个数
// 1637926
System.out.println(file.length());
// 获取文件的最后修改时间
long time = file.lastModified();
// 最后修改时间:2021/06/16 17:02:19
System.out.println("最后修改时间:" + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(time));
// 判断是文件还是文件夹
System.out.println(file.isFile());
System.out.println(file.isDirectory());
}
}
File类创建文件的功能:
| 方法名称 | 说明 |
|---|---|
| public boolean createNewFile() | 创建一个新的空的文件。 |
| public boolean mkdir() | 只能创建一级文件夹。 |
| public boolean mkdirs() | 可以创建多级文件夹。 |
File类删除文件的功能:
| 方法名称 | 说明 |
|---|---|
| public boolean delete() | 删除由此抽象路径名表示的文件或空文件夹。 |
Test.java
package com.javase.filedemo1;
import java.io.File;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
File file = new File("day11-oop-demo/src/com/javase/filedemo1/picture.jpg");
// 创建新文件
// false
System.out.println(file.createNewFile());
// 创建一级目录
File file1 = new File("day11-oop-demo/src/com/javase/filedemo1/dirdemo1/");
// true
System.out.println(file1.mkdir());
// 创建多级目录
File file2 = new File("day11-oop-demo/src/com/javase/filedemo1/dirdemo2/a/b/c/");
// true
System.out.println(file2.mkdirs());
// 删除文件或者空文件夹 只能删除空文件夹
System.out.println(file1.delete());
}
}
File类的遍历功能:
| 方法名称 | 说明 |
|---|---|
| public String[] list() | 获取当前目录下所有的“一级文件名称”到一个字符串数组中去返回。 |
| public File[] listFiles() | 获取当前目录下所有的“一级文件对象”到一个文件对象数组中去返回。 |
listFiles注意事项:
什么是方法递归?
递归的形式:
方法递归存在的问题?
public class Test {
public static void main(String[] args) {
test();
}
public static void test() {
System.out.println("===Test被执行===");
test();
}
}
需求:
分析:
阶乘公式 f(n) = 1 * 2 * 3 * 4 * 5 * 6 * 7 * … * (n - 1) * n。
公式等价形式:f(n) = f(n - 1) * n。
如果求的是1-5的阶乘的结果,手工描述公式计算。
f(5) = f(4) * 5
f(4) = f(3) * 4
f(3) = f(2) * 3
f(2) = f(1) * 2
f(1) = 1
Test.java
/**
* 目标:掌握递归的算法和执行流程
*/
public class Test {
public static void main(String[] args) {
// 计算 1-5 的阶乘
System.out.println(f(5));
}
/**
* 计算 1-n 的阶乘
* @param n n
* @return 计算 1-n 的阶乘结果
*/
public static int f(int n) {
if (n == 1) {
return 1;
} else {
return f(n - 1) * n;
}
}
}
递归解决问题的思路:
递归算法三大要素大体可以总结为:
案例:计算 1-n 的和。
需求:
分析:
Test.java
public class Test {
public static void main(String[] args) {
// 计算 1-5 的和
System.out.println(f(5));
}
/**
* 计算 1-n 的和
* @param n n
* @return 1-n 的和
*/
public static int f(int n) {
if (n == 1) {
return 1;
} else {
return f(n - 1) + n;
}
}
}
猴子吃桃问题:
猴子第一天摘下若干桃子,当即吃了一半,觉得好吃不过瘾,于是又多吃了一个。第二天又吃了前天剩余桃子数量的一半,觉得好吃不过瘾,于是又多吃了一个。以后每天都是吃前天剩余桃子数量的一半,觉得好吃不过瘾,又多吃了一个,等到第10天的时候发现桃子只有1个了。
请问猴子第一天摘了多少个桃子?
Test.java
/**
* f(x) - f(x)/ 2 - 1 = f(x+1)
* 2f(x) - f(x) - 2 = 2f(x+1)
* f(x) = 2f(x+1) + 2
*
* 求:f(1) = ?
* 总结点:f(10) = 1
*/
public class Test {
public static void main(String[] args) {
// 第一天桃子数量
System.out.println(f(1));
// 第二天桃子数量
System.out.println(f(2));
}
/**
* 求第 n 天的桃子数量
* @param n 天数
* @return 桃子数量
*/
public static int f(int n) {
if (n == 10) {
return 1;
} else {
return 2 * f(n+1) + 2;
}
}
}
需求:
- 文件搜索,从Linux根目录/Windows C盘中,搜索出某个文件名称并输出绝对路径。
分析:
- 先定位出一级文件对象。
- 遍历全部一级文件对象,判断是否是文件。
- 如果是文件,判断是否是自己想要的文件。
- 如果是文件夹,需要继续递归进去重复上述过程。
Test.java
package com.javase.recursiondemo1;
import java.io.File;
public class Test {
public static void main(String[] args) {
searchFile(new File("/home"), "picture.jpg");
}
/**
* 查找文件
*
* @param dir 文件夹对象
* @param fileName 目标文件名
*/
public static void searchFile(File dir, String fileName) {
// 判断dir是否为目录
if (dir != null && dir.isDirectory()) {
// 获取dir目录下所有文件或文件夹
File[] files = dir.listFiles();
if (files != null && files.length > 0) {
for (File file : files) {
// 如果是文件
if (file.isFile()) {
if (file.getName().contains(fileName)) {
System.out.println("找到了:" + file.getAbsolutePath());
}
} else {
// 如果是文件夹 递归查找
searchFile(file, fileName);
}
}
}
} else if (dir == null || !dir.isFile()) {
System.out.println("抱歉,当前搜索的位置不是文件夹!" + dir);
}
}
}
需求:
- 啤酒2元1瓶,4个盖子可以换一瓶,2个空瓶可以换一瓶,请问10元钱可以喝多少瓶酒,剩余多少空瓶和盖子。
Test.java
/**
* 啤酒2元1瓶,4个盖子可以换一瓶,2个空瓶可以换一瓶,请问10元钱可以喝多少瓶酒,剩余多少空瓶和盖子?
*/
public class Test {
// 啤酒瓶数
public static int totalBeerNumber;
// 瓶子数
public static int lastBottleNumber;
// 盖子数
public static int lastCoverNumber;
public static void main(String[] args) {
// 买酒
buyBeer(10);
System.out.println(totalBeerNumber);
System.out.println(lastBottleNumber);
System.out.println(lastCoverNumber);
}
/**
* 买酒
*
* @param money 金额
*/
public static void buyBeer(int money) {
// 购买瓶子数
int beerNumber = money / 2;
totalBeerNumber += beerNumber;
// 盖子数
int coverNumber = lastCoverNumber + beerNumber;
// 瓶子数
int bottleNumber = lastBottleNumber + beerNumber;
// 盖子和瓶子换的钱
int allMoney = 0;
// 盖子换成钱
if (coverNumber >= 4) {
allMoney += (coverNumber / 4) * 2;
}
// 刷新盖子数
lastCoverNumber = coverNumber % 4;
// 瓶子换成钱 1
if (bottleNumber >= 2) {
allMoney += (bottleNumber / 2) * 2;
}
// 刷新瓶子数
lastBottleNumber = bottleNumber % 2;
if (allMoney >= 2) {
buyBeer(allMoney);
}
}
}
字符集基础知识:
结论:计算机底层可以表示十进制编号。计算机可以给人类字符进行编号存储,这套编号规则就是字符集。
ASCII字符集:
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码):包括了数字、英文、符号。
ASCII使用1个字节存储一个字符,一个字节是8为,总共可以表示128个字符信息,对于英文,数字来说是够用的。
0110 0001 = 97 => a
0110 0010 = 98 => b
GBK:
Unicode码表:
注意:
汉字存储和展示过程解析:
总结:
String编码:
| 方法名称 | 说明 |
|---|---|
| byte[] getBytes() | 使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中。 |
| byte[] getBytes(String charsetName) | 使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中。 |
String解码:
| 方法名称 | 说明 |
|---|---|
| String(byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组来构造新的String。 |
| String(byte[] bytes, String charsetName) | 通过指定的字符集解码指定的字节数组来构造新的String。 |
Test.java
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Test {
public static void main(String[] args) throws UnsupportedEncodingException {
/* 编码 */
String name = "abc和平统一";
byte[] bytes = name.getBytes();
// 15 -> 1 1 1 3 3 3 3
System.out.println(bytes.length);
// [97, 98, 99, -27, -110, -116, -27, -71, -77, -25, -69, -97, -28, -72, -128]
System.out.println(Arrays.toString(bytes));
byte[] bytes1 = name.getBytes("GBK");
// 11 -> 1 1 1 2 2 2 2
System.out.println(bytes1.length);
// [97, 98, 99, -70, -51, -58, -67, -51, -77, -46, -69]
System.out.println(Arrays.toString(bytes1));
/* 解码 */
String rs = new String(bytes);
// 乱码 未使用对应编码 abc��ƽͳһ
// String rs = new String(bytes1);
// abc和平统一
System.out.println(rs);
String rs1 = new String(bytes1, "GBK");
System.out.println(rs1);
}
}
IO流也称为输入、输出流,就是用来读写数据的。
IO流概述:
IO流分类:
按流的方向:
按流中的数据最小单位分为:
总结流的四大类:
文件字节输入流:FileInputStream
| 构造器 | 说明 |
|---|---|
| public FileInputStream(File file) | 创建字节输入流管道与源文件对象接通。 |
| public FileInputStream(String pathname) | 创建字节输入流管道与源文件路径接通。 |
| 方法名称 | 说明 |
|---|---|
| public int read() | 每次读取一个字节返回,如果字节已经没有可读的返回-1。 |
| public int read(byte[] buffer) | 每次读取一个字节数组返回,如果字节已经没有可读的返回-1。 |
data.txt
abc
Test.java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class Test {
public static void main(String[] args) throws Exception {
// 创建文件字节输入流管道与源文件接通
// InputStream inputStream = new FileInputStream(new File("data.txt"));
InputStream inputStream = new FileInputStream("day11-oop-demo/src/data.txt");
// // 读取一个字节 a
// int byte1 = inputStream.read();
// System.out.println((char) byte1);
//
// // 读取一个字节 b
// int byte2 = inputStream.read();
// System.out.println((char) byte2);
//
// // 读取一个字节 c
// int byte3 = inputStream.read();
// System.out.println((char) byte3);
//
// // 读取完毕返回 -1
// int byte4 = inputStream.read();
// System.out.println(byte4);
/* 循环读取 a b c */
// 该方法读取中文乱码
int b;
while ((b = inputStream.read()) != -1) {
System.out.println((char) b);
}
}
}
总结:
文件字节输入流,每次读取一个字节的API是哪个?
| 方法名称 | 说明 |
|---|---|
| public int read() | 每次读取一个字节返回,如果字节已经没有可读的返回-1。 |
每次读取一个字节存在什么问题?
data.txt
abcdefgh
Test.java
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* 目标:使用文件字节输入流每次读取一个字节数组的数据
*/
public class Test {
public static void main(String[] args) throws Exception {
InputStream inputStream = new FileInputStream("day11-oop-demo/src/data.txt");
// // 定一个字节数组 用于读取字节数组
// byte[] bytes = new byte[3];
//
// // 读取
// int length = inputStream.read(bytes);
// // 3
// System.out.println("读取了" + length + "个字节");
// // 解码
// String string = new String(bytes);
// // abc
// System.out.println(string);
//
// // 读取
// int length1 = inputStream.read(bytes);
// // 3
// System.out.println("读取了" + length1 + "个字节");
// // 解码
// String string1 = new String(bytes);
// // def
// System.out.println(string1);
//
// // 读取
// int length2 = inputStream.read(bytes);
// // 2
// System.out.println("读取了" + length2 + "个字节");
// // 解码
// String string2 = new String(bytes);
// // 读取多少 解码多少
// // String string2 = new String(bytes, 0, length2);
// // ghf
// // 上一次读取 [def] 剩余 gh
// // 本次读取 gh放入前两个位置 [ghf]
// System.out.println(string2);
//
// // 读取
// int length3 = inputStream.read(bytes);
// // 读取完毕 -1
// System.out.println(length3);
/* 循环读取 */
byte[] bytes = new byte[3];
// 记录每次读取的字节数
int length;
while ((length = inputStream.read(bytes)) != -1) {
System.out.print(new String(bytes, 0, length));
}
}
}
总结:
文件字节输入流,每次读取一个字节数组的API是哪个?
| 方法名称 | 说明 |
|---|---|
| public int read(byte[] buffer) | 每次读取一个字节数组返回,如果字节已经没有可读的返回-1。 |
每次读取一个字节数组存在什么问题?
方式一:
自己定义一个字节数组与文件的大小一样大,然后使用读取字节数组的方法,一次性读取完成。
| 方法名称 | 说明 |
|---|---|
| public int read(byte[] buffer) | 每次读取一个字节数组返回,如果字节已经没有可读的返回-1。 |
方式二:
官方为字节输入流InputStream提供了如下API可以直接把文件的全部数据读取到一个字节数组中。
| 方法名称 | 说明 |
|---|---|
| public byte[] readAllBytes() throws IOException | 直接将当前字节输入流对应的文件对象的字节数据装到一个字节数组返回。 |
Test.java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class Test {
public static void main(String[] args) throws Exception {
// 创建一个文件字节输入流管道与源文件接通
File file = new File("day11-oop-demo/src/data1.txt");
InputStream inputStream = new FileInputStream(file);
// /* 方式一 */
// // 定义一个数组与文件的大小刚刚一样大
// byte[] bytes = new byte[(int) file.length()];
//
// // 读取数据到数组中
// int length = inputStream.read(bytes);
// System.out.println("读取了" + length + "个字节");
//
// // 解码
// System.out.println(new String(bytes));
/* 方式二 */
// 读取全部字节数组
byte[] bytes1 = inputStream.readAllBytes();
System.out.println(new String(bytes1));
}
}
文件字节输出流(FileOutputStream)写数据出去的API:
| 方法名称 | 说明 |
|---|---|
| public void write(int a) | 写一个字节出去。 |
| public void write(byte[] buffer) | 写一个字节数组出去。 |
| public void write(byte[] buffer, int pos, int len) | 写一个字节数组的一部分出去。 |
流的关闭与刷新:
| 方法 | 说明 |
|---|---|
| flush() | 刷新流,还可以继续写数据。 |
| close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据。 |
Test.java
import java.io.FileOutputStream;
import java.io.OutputStream;
public class Test {
public static void main(String[] args) throws Exception {
// 创建一个文件字节输出流管道与目标文件接通
// 先清空之前的数据 重新写入数据
OutputStream outputStream = new FileOutputStream("day11-oop-demo/src/dataOut.txt");
// 追加写入数据
// OutputStream outputStream = new FileOutputStream("day11-oop-demo/src/dataOut.txt", true);
// 写数据出去
outputStream.write('a');
outputStream.write(100);
// 换行
outputStream.write("\r\n".getBytes());
// 写中文会乱码
//outputStream.write('中');
// 写一个字节数组出去
outputStream.write("我是中国人".getBytes());
// 换行
outputStream.write("\r\n".getBytes());
// 写一个字节数组的一部分出去
byte[] bytes = {'a', 'b', 'c', 100, 101};
outputStream.write(bytes, 0, 5);
// 换行
outputStream.write("\r\n".getBytes());
// 刷新数据
outputStream.flush();
// 释放资源 包含刷新
outputStream.close();
}
}
需求:
思路:
Test.java
import java.io.*;
public class Test {
public static void main(String[] args) {
try {
// 创建一个字节流输入管道与原文件接通
InputStream inputStream = new FileInputStream("day11-oop-demo/src/oldData.txt");
// 创建一个字节输出流管道于目标文件接通
OutputStream outputStream = new FileOutputStream("day11-oop-demo/src/newData.txt");
// 定义一个字节数组转移数据
byte[] bytes = new byte[1024];
// 记录每次读取的字节数
int length;
while ((length = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, length);
}
System.out.println("拷贝完成!");
// 关闭流
inputStream.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
视频进度:14:27
Test.java
import java.io.*;
public class Test {
public static void main(String[] args) {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
// 创建一个字节流输入管道与原文件接通
inputStream = new FileInputStream("day11-oop-demo/src/oldData.txt");
// 创建一个字节输出流管道于目标文件接通
outputStream = new FileOutputStream("day11-oop-demo/src/newData.txt");
// 定义一个字节数组转移数据
byte[] bytes = new byte[1024];
// 记录每次读取的字节数
int length;
while ((length = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, length);
}
System.out.println("拷贝完成!");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 无论代码是否正常结束 最后都要执行
System.out.println("===finally===");
// 关闭流
try {
if (inputStream != null) inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (outputStream != null) outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
finally虽然可以用于释放资源,但是释放资源的代码过于繁琐。JDK 7 和JDK 9 中都简化了资源释放操作。
基本做法:手动释放资源。
try {
// 可能出现异常的代码
} catch (异常类名 变量名) {
// 异常的处理代码
} finally {
// 执行所有资源释放操作
}
JDK 7 改进方案:
try (定义流对象) {
// 可能出现异常的代码
} catch (异常类名 变量名) {
// 异常的处理代码
}
JDK 9 改进方案:资源用完最终自动释放。
// 定义输入流对象
// 定义输出流对象
try (输入流对象; 输出流对象) {
// 可能出现异常的代码
} catch (异常类名 变量名) {
// 异常的处理代码
}
注意:
JDK 7 以及 JDK 9的 try () 中 只能放置资源对象,否则报错。
什么是资源?
资源都是实现了 Closeable/AutoCloseable接口的类对象。
public abstract class InputStream implements Closeable {}
public abstract class OutputStream implements Closeable, Flushable {}
Test.java
import java.io.*;
/**
* JDK 7 释放资源方式
*/
public class Test2 {
public static void main(String[] args) {
try (
// 创建一个字节流输入管道与原文件接通
InputStream inputStream = new FileInputStream("day11-oop-demo/src/oldData.txt");
// 创建一个字节输出流管道于目标文件接通
OutputStream outputStream = new FileOutputStream("day11-oop-demo/src/newData.txt");
// 自定义资源类 会自动调用资源的close方法
MyConnection myConnection = new MyConnection();
) {
// 定义一个字节数组转移数据
byte[] bytes = new byte[1024];
// 记录每次读取的字节数
int length;
while ((length = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, length);
}
System.out.println("拷贝完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyConnection implements AutoCloseable {
/**
* @throws Exception
*/
@Override
public void close() throws Exception {
System.out.println("连接资源自动被成功释放!");
}
}
Test.java
import java.io.*;
/**
* JDK 9 释放资源方式
*/
public class Test {
public static void main(String[] args) throws IOException {
// 创建一个字节流输入管道与原文件接通
InputStream inputStream = new FileInputStream("day11-oop-demo/src/oldData.txt");
// 创建一个字节输出流管道于目标文件接通
OutputStream outputStream = new FileOutputStream("day11-oop-demo/src/newData.txt");
try (inputStream; outputStream) {
// 定义一个字节数组转移数据
byte[] bytes = new byte[1024];
// 记录每次读取的字节数
int length;
while ((length = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, length);
}
System.out.println("拷贝完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
文件字符输入流:Reader
| 构造器 | 说明 |
|---|---|
| public FileReader(File file) | 创建字符输入流管道与源文件对象接通。 |
| public FileReader(String pathname) | 创建字符输入流管道与源文件路径接通。 |
| 方法名称 | 说明 |
|---|---|
| public int read() | 每次读取一个字符返回,如果字符已经没有可读的返回-1。 |
| publict int read(char[] buffer) | 每次读取一个字符数组,返回读取的字符个数,如果字符已经没有可读的返回-1。 |
Test.java
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
public class Test {
public static void main(String[] args) throws Exception {
/* 每次读取一个字符 */
// 创建一个字符输入流管道与源文件接通
Reader reader = new FileReader("day11-oop-demo/src/dataOut.txt");
// // 读取一个字符返回 没有可读字符返回-1
// int code = reader.read();
// System.out.println((char) code);
//
// int code1 = reader.read();
// System.out.println((char) code1);
/* 循环读取字符 */
int code;
while ((code = reader.read()) != -1) {
System.out.print((char) code);
}
// 关闭流
reader.close();
}
}
总结:
文件字符输入流,每次读取一个字符的API的哪个?
| 方法名称 | 说明 |
|---|---|
| public int read() | 每次读取一个字符返回,如果字节已经没有可读的返回-1。 |
字符流的好处,每次读取一个字符存在什么问题?
Test.java
import java.io.FileReader;
import java.io.Reader;
public class Test {
public static void main(String[] args) throws Exception {
// 创建一个文件字符输入流于源文件接通
Reader reader = new FileReader("day11-oop-demo/src/dataOut.txt");
// 用循环每次读取一个字符数组的数据
char[] chars = new char[1024];
int length;
while ((length = reader.read(chars)) != -1) {
String rs = new String(chars, 0, length);
System.out.println(rs);
}
}
}
总结:
文件字符输入流,每次读取一个字符数组的API是哪个?
| 方法名称 | 说明 |
|---|---|
| publict int read(char[] buffer) | 每次读取一个字符数组,返回读取的字符个数,如果字符已经没有可读的返回-1。 |
每次读取一个字符数组的优势?
文件字符输出流:FileWriter
| 构造器 | 说明 |
|---|---|
| public FileWriter(File file) | 创建字符输出流管道与源文件对象接通。 |
| public FileWriter(File file, boolean append) | 创建字符输出流管道与源文件对象接通,可追加数据。 |
| public FileWriter(String filepath) | 创建字符输出流管道与源文件路径接通。 |
| public FileWriter(String filepath, boolean append) | 创建字符输出流管道与源文件路径接通,可追加数据。 |
文件字符输出流(FileWriter)写数据出去的API:
| 方法名称 | 说明 |
|---|---|
| void write(int c) | 写一个字符。 |
| void write(char[] cbuf) | 写入一个字符数组。 |
| void writer(char[] cbuf, int off, int len) | 写入字符数组的一部分。 |
| void writer(String str) | 写一个字符串。 |
| void write(String str, int off, int len) | 写一个字符串的一部分。 |
| void write(int c) | 写一个字符。 |
Test.java
import java.io.FileWriter;
import java.io.Writer;
public class Test {
public static void main(String[] args) throws Exception {
// 创建一个字符输出管道与目标文件接通
// 覆盖管道 每次启动都会清空文件之前的数据
Writer writer = new FileWriter("day11-oop-demo/src/dataOutFileWriter.txt");
// 追加数据 不覆盖之前的数据
// Writer writer = new FileWriter("day11-oop-demo/src/dataOutFileWriter.txt", true);
// 写一个字符出去
writer.write('A');
writer.write("\r\n");
// 写一个字符串出去
writer.write("我是中国人");
writer.write("\r\n");
// 写一个字符数组出去
writer.write(new char[]{'A', 'B', 'C'});
writer.write("\r\n");
// 写字符串的一部分出去
writer.write("全世界无产者,联合起来!", 0, 5);
writer.write("\r\n");
// 写字符数组的一部分出去
writer.write(new char[]{'一', '二', '三', '四', '五', '六', '七'}, 0, 5);
writer.write("\r\n");
// 刷新流
writer.flush();
// 关闭流
writer.close();
}
}