文章目录
1. IO流概述
小结
2. 字节流
2.1 字节输入流
1)每次读取一个字节
public class FileInputStreamDemo01 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字节输入流管道与源文件接通。
// InputStream is = new FileInputStream(new File("file-io-app\\src\\data.txt"));
// 简化写法
InputStream is = new FileInputStream("file-io-app\\src\\data.txt");
// 2、读取一个字节返回 (每次读取一滴水)
// int b1 = is.read();
// System.out.println((char)b1);
// 3、使用循环改进
// 定义一个变量记录每次读取的字节 a b 3 爱
// o o o [ooo]
int b;
while (( b = is.read() ) != -1){
System.out.print((char) b);
}
}
}
可以发现,当一个字节一个字节读取文件内容时,因为中文字符占3个字节,因此,这种操作会造成乱码问题
总结:
2)每次读取一个字节数组
代码演示:
public class FileInputStreamDemo02 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字节输入流管道与源文件接通
InputStream is = new FileInputStream("file-io-app/src/data02.txt");
// 2、定义一个字节数组,用于读取字节数组
// byte[] buffer = new byte[3]; // 3B
// int len = is.read(buffer);
// System.out.println("读取了几个字节:" + len);
// String rs = new String(buffer);
// System.out.println(rs);
// 3、改进使用循环,每次读取一个字节数组
byte[] buffer = new byte[3];
int len; // 记录每次读取的字节数。
while ((len = is.read(buffer)) != -1) {
// 读取多少倒出多少
System.out.print(new String(buffer, 0 , len));
}
}
}
依然无法解决乱码问题
3)读取文件的全部字节
注意,readAllBytes这个api时jdk9才提供的,jdk8没有
public class FileInputStreamDemo03 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字节输入流管道与源文件接通
File f = new File("D:\\java\\java学习文件\\io\\代码\\file-io-app\\src\\com\\itheima\\data03.txt");
InputStream is = new FileInputStream(f);
// 2、定义一个字节数组与文件的大小刚刚一样大。
byte[] buffer = new byte[(int) f.length()];
int len = is.read(buffer);
System.out.println("读取了多少个字节:" + len);
System.out.println("文件大小:" + f.length());
System.out.println(new String(buffer));
// 读取全部字节数组
/*byte[] buffer = is.readAllBytes();
System.out.println(new String(buffer));*/
}
}
2.2 字节输出流
1)简介及常用API
2)代码演示
public class OutputStreamDemo04 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("src/out04.txt" , true); // 追加数据管道
// OutputStream os = new FileOutputStream("file-io-app/src/out04.txt"); // 先清空之前的数据,写新数据进入
// 2、写数据出去
// a.public void write(int a):写一个字节出去
os.write('a');
os.write(98);
os.write("\r\n".getBytes()); // 换行
// os.write('徐'); // [ooo]
// b.public void write(byte[] buffer):写一个字节数组出去。
byte[] buffer = {'a' , 97, 98, 99};
os.write(buffer);
os.write("\r\n".getBytes()); // 换行
byte[] buffer2 = "我是中国人".getBytes();
// byte[] buffer2 = "我是中国人".getBytes("GBK");
os.write(buffer2);
os.write("\r\n".getBytes()); // 换行
// c. public void write(byte[] buffer , int pos , int len):写一个字节数组的一部分出去。
byte[] buffer3 = {'a',97, 98, 99};
os.write(buffer3, 0 , 3);
os.write("\r\n".getBytes()); // 换行
// os.flush(); // 写数据必须,刷新数据 可以继续使用流
os.close(); // 释放资源,包含了刷新的!关闭后流不可以使用了
}
}
3)小结
2.3 文件拷贝
代码实现:
public class CopyDemo05 {
public static void main(String[] args) {
try {
// 1、创建一个字节输入流管道与原视频接通
InputStream is = new FileInputStream("file-io-app/src/out04.txt");
// 2、创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("file-io-app/src/out05.txt");
// 3、定义一个字节数组转移数据
byte[] buffer = new byte[1024];
int len; // 记录每次读取的字节数。
while ((len = is.read(buffer)) != -1){
os.write(buffer, 0 , len);
}
System.out.println("复制完成了!");
// 4、关闭流。
os.close();
is.close();
} catch (Exception e){
e.printStackTrace();
}
}
}
3. 资源释放方式
3.1 try-catch-finally
public static int test(int a , int b){
try {
int c = a / b;
return c;
}catch (Exception e){
e.printStackTrace();
return -111111; // 计算出现bug.
}finally {
System.out.println("--finally--");
// 哪怕上面有return语句执行,也必须先执行完这里才可以!
// 开发中不建议在这里加return ,如果加了,返回的永远是这里的数据了,这样会出问题!
return 100;
}
}
3.2 try-with-resource
注意,放在try里面的需要为资源对象,资源对象实现了AutoCloseable或者Closeable接口。
public class TryCatchResouceDemo2 {
public static void main(String[] args) {
try (
// 这里面只能放置资源对象,用完会自动关闭:自动调用资源对象的close方法关闭资源(即使出现异常也会做关闭操作)
// 1、创建一个字节输入流管道与原视频接通
InputStream is = new FileInputStream("file-io-app/src/out04.txt");
// 2、创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("file-io-app/src/out05.txt");
// int age = 23; // 这里只能放资源
MyConnection connection = new MyConnection(); // 最终会自动调用资源的close方法
) {
// 3、定义一个字节数组转移数据
byte[] buffer = new byte[1024];
int len; // 记录每次读取的字节数。
while ((len = is.read(buffer)) != -1){
os.write(buffer, 0 , len);
}
System.out.println("复制完成了!");
} catch (Exception e){
e.printStackTrace();
}
}
}
class MyConnection implements AutoCloseable{
@Override
public void close() throws IOException {
System.out.println("连接资源被成功释放了!");
}
}
4. 字符流
我们首先思考一下以下问题
4.1 字符输入流
1) 每次读取一个字符
public class FileReaderDemo01 {
public static void main(String[] args) throws Exception {
// 目标:每次读取一个字符。
// 1、创建一个字符输入流管道与源文件接通
Reader fr = new FileReader("src\\data06.txt");
// 2、读取一个字符返回,没有可读的字符了返回-1
// int code = fr.read();
// System.out.print((char)code);
//
// int code1 = fr.read();
// System.out.print((char)code1);
// 3、使用循环读取字符
int code;
while ((code = fr.read()) != -1){
System.out.print((char) code);
}
}
}
2) 每次读取一个字符数组
public class FileReaderDemo02 {
public static void main(String[] args) throws Exception {
// 1、创建一个文件字符输入流与源文件接通
Reader fr = new FileReader("file-io-app/src/data07.txt");
// 2、用循环,每次读取一个字符数组的数据。 1024 + 1024 + 8
char[] buffer = new char[1024]; // 1K字符
int len;
while ((len = fr.read(buffer)) != -1) {
String rs = new String(buffer, 0, len);
System.out.print(rs);
}
}
}
4.2 字符输出流
构造器
写数据常用API
public class FileWriterDemo03 {
public static void main(String[] args) throws Exception {
// 1、创建一个字符输出流管道与目标文件接通
// Writer fw = new FileWriter("file-io-app/src/out08.txt"); // 覆盖管道,每次启动都会清空文件之前的数据
Writer fw = new FileWriter("file-io-app/src/out08.txt", true); // 覆盖管道,每次启动都会清空文件之前的数据
// a.public void write(int c):写一个字符出去
fw.write(98);
fw.write('a');
fw.write('徐'); // 不会出问题了
fw.write("\r\n"); // 换行
// b.public void write(String c)写一个字符串出去
fw.write("abc我是中国人");
fw.write("\r\n"); // 换行
// c.public void write(char[] buffer):写一个字符数组出去
char[] chars = "abc我是中国人".toCharArray();
fw.write(chars);
fw.write("\r\n"); // 换行
// d.public void write(String c ,int pos ,int len):写字符串的一部分出去
fw.write("abc我是中国人", 0, 5);
fw.write("\r\n"); // 换行
// e.public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去
fw.write(chars, 3, 5);
fw.write("\r\n"); // 换行
// fw.flush();// 刷新后流可以继续使用
fw.close(); // 关闭包含刷线,关闭后流不能使用
}
}
总结