1. IO流介绍
2. IO 流体系结构
字节流读取纯文本文件会出现乱码问题
2.1 FileOutputStream 字节输出流
package com.itheima.stream.output;import java.io.FileOutputStream;
import java.io.IOException;public class FileOutputStreamDemo3 {/*IO流的异常处理方式: jdk7版本之前*/public static void main(String[] args) {FileOutputStream fos = null;try {fos = new FileOutputStream("D:\\B.txt");fos.write("abc".getBytes());} catch (IOException e) {e.printStackTrace();} finally {if(fos != null){try {fos.close();} catch (IOException e) {e.printStackTrace();}}}}
}
2.2 FileInputStream 字节输入流
package com.itheima.stream.input;import java.io.FileInputStream;
import java.io.IOException;public class FileInputStreamDemo1 {/*字节流读取数据public int read() : 读取单个字节*/public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("D:\\A.txt");int i;while ((i = fis.read()) != -1) {System.out.println((char) i);}fis.close();}
}
package com.itheima.stream.input;import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;public class FileInputStreamDemo2 {/*字节流读取数据public int read(byte[] bys) : 读取一个字节数组- 将读取到的字节, 存入数组容器, 返回读取到的有效字节个数*/public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("D:\\A.txt");// 准备菜篮子, 用于装(字节)byte[] bys = new byte[2];int len;while( (len = fis.read(bys)) != -1 ){String s = new String(bys, 0, len);System.out.print(s);}fis.close();}
}
2.3 综合案例
package com.itheima.stream;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class CopyTest1 {/*将 D:\嘿嘿.png,拷贝到 E:\ 根目录下分析:1. 创建输入流对象读取文件2. 创建输出流对象关联数据目的3. 读写操作4. 关流释放资源*/public static void main(String[] args) throws IOException {
/* // 1. 创建输入流对象读取文件FileInputStream fis = new FileInputStream("D:\\猫咪.jpg");// 2. 创建输出流对象关联数据目的FileOutputStream fos = new FileOutputStream("E:\\猫咪.jpg");// 3. 读写操作byte[] bys = new byte[1024];int len;while( (len = fis.read(bys)) != -1){fos.write(bys, 0, len);}// 4. 关流释放资源fis.close();fos.close();*/// 1. 创建输入流对象读取文件FileInputStream fis = new FileInputStream("D:\\猫咪.jpg");// 2. 创建输出流对象关联数据目的FileOutputStream fos = new FileOutputStream("D:\\test\\猫咪.jpg");// 3. 读写操作byte[] bytes = new byte[1024];int len;while((len = fis.read(bytes))!=-1){fos.write(bytes,0,len);}// 4. 关流释放资源fis.close();fos.close();}
}
3. 字节缓冲流-(时间问题~暂时省略~)
4. 字符流介绍
4.1 FileReader 字符输入流
package com.itheima.stream.character.reader;import java.io.FileReader;
import java.io.IOException;public class FileReaderDemo1 {/*FileReader: 用于读取纯文本文件,解决中文乱码问题构造方法:1. public FileReader(String fileName) 字符输入流关联文件,路径以字符串形式给出2. public FileReader(File file) 字符输入流关联文件,路径以File对象形式给出成员方法:public int read() : 读取单个字符public int read(char[] cbuf) : 读取一个字符数组, 返回读取到的有效字符个数*/public static void main(String[] args) throws IOException {FileReader fr = new FileReader("D:\\A.txt");char[] chs = new char[1024];int len;// 读取多个字符while( (len = fr.read(chs)) != -1 ){String s = new String(chs, 0, len);System.out.println(s);}fr.close();}/*** 读取单个字符*/private static void method() throws IOException {FileReader fr = new FileReader("D:\\A.txt");int i;while ((i = fr.read()) != -1) {System.out.print((char)i);}fr.close();}
}
4.2 字符集与字符编码
package com.itheima.stream.character;import java.io.IOException;
import java.util.Arrays;public class StringDemo {/*平台默认字符编码 : Unicode - UTF-8的形式重点记忆: 中文字符, 通常都是由负数的字节进行组成的.特殊情况: 可能会出现正数, 但是就算有正数, 第一个字节肯定是负数注意事项: 今后如果出现乱码问题, 大概率是因为编解码方式不一致所导致的.编码: 字符转字节public byte[] getBytes() : 使用平台默认字符编码方式, 对字符串编码public byte[] getBytes(String charsetName) : 使用使用字符编码方式, 对字符串编码解码: 字节转字符public String(byte[] bytes) : 使用平台默认字符编码方式, 对字符串解码public String(byte[] bytes, String charsetName) : 使用使用字符编码方式, 对字符串解码*/public static void main(String[] args) throws IOException {String s = "你好,你好";byte[] bytes = s.getBytes();System.out.println(Arrays.toString(bytes));byte[] gbks = s.getBytes("gbk");System.out.println(Arrays.toString(gbks));System.out.println("----------------------------");byte[] utf8Bytes = {-28, -67, -96, -27, -91, -67, 44, -28, -67, -96, -27, -91, -67};byte[] gbkBytes = {-60, -29, -70, -61, 44, -60, -29, -70, -61};String s1 = new String(gbkBytes, "GBK");System.out.println(s1);}
}
4.3 FileWriter 字符输出流
package com.itheima.stream.character.writer;import java.io.FileWriter;
import java.io.IOException;public class FileWriterDemo1 {/*FileWriter字符输出流写出数据 :构造方法:FileWriter(String fileName): 字符输出流关联文件,路径以字符串形式给出FileWriter(String fileName, boolean append): 参数2: 追加写入的开关FileWriter(File file): 字符输出流关联文件,路径以File对象形式给出FileWriter(File file, boolean append): 参数2: 追加写入的开关成员方法:public void write(int c) 写出单个字符public void write(char[] cbuf) 写出一个字符数组public void write(char[] cbuf, int off, int len) 写出字符数组的一部分public void write(String str) 写出字符串public void write(String str, int off, int len) 写出字符串的一部分*/public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("D:\\C.txt");char[] chs = {'a','b','c'};fw.write('a');fw.write(chs);fw.write(chs, 0, 2);fw.write("你好你好~");fw.write("哈哈哈哈哈", 0, 2);fw.close();}
}
package com.itheima.stream.character.writer;import java.io.FileWriter;
import java.io.IOException;public class FileWriterDemo2 {/*注意事项: 字符输出流写出数据, 需要调用flush或close方法, 数据才会写出flush() : 刷出数据, 刷出后可以继续写出close() : 关闭流释放资源, 顺便刷出数据, 关闭后不可以继续写出*/public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("D:\\D.txt");fw.write("人活一世, 草木一秋");fw.write("\r\n");fw.write("今晚不减肥, 我要吃肉!");fw.close();}
}
5. IO 流-练习题
5.1 案例1-图片文件加解密
package com.itheima.stream;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;public class ImageTest {/*图片文件加密解密加密思路:改变原始文件中的字节,就无法打开了字节 ^ 2解密思路:将文件中的字节还原成原始字节即可字节 ^ 2*/public static void main(String[] args) throws IOException {// 1. 创建字节输入流对象, 关联要加密的图片FileInputStream fis = new FileInputStream("D:\\A.jpg");// 2. 创建一个集合容器, 用于存取读到的字节(为便于不用考虑容器长度大小, 使用集合)ArrayList<Integer> list = new ArrayList<>();// 3. 循环读取文件的字节, 并存入集合int i;while((i = fis.read()) != -1){list.add(i);}// 4. 关闭输入流fis.close();// 5. 创建字节输出流对象, 关联图片文件FileOutputStream fos = new FileOutputStream("D:\\A.jpg");// 6. 遍历集合, 从集合中取出字节, 并写入for (Integer myByte : list) {fos.write(myByte ^ 2);}// 7. 关闭输出流fos.close();}
}
5.2 案例2-统计字符次数
package com.itheima.stream;import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.function.BiConsumer;public class CharacterTest {/*统计文件中每一个字符出现的次数,随后展示在控制台效果:A(1)B(2)C(3)*/public static void main(String[] args) throws IOException {// 1. 准备map集合, 用于统计每个字符出现的次数HashMap<Character, Integer> hm = new HashMap<>();// 2. 创建字符输入流读取纯文本文件FileReader fr = new FileReader("D:\\info.txt");// 3. 将每个字符存入集合int i;while ((i = fr.read()) != -1){char c = (char) i;// 4. 统计每个字符出现的个数if (!hm.containsKey(c)){hm.put(c, 1);} else {hm.put(c, hm.get(c) + 1);}}// 5. 关闭输入流fr.close();// 6. 准备StringBuild对字符进行拼接操作StringBuilder sb = new StringBuilder();hm.forEach(new BiConsumer<Character, Integer>() {@Overridepublic void accept(Character key, Integer value) {sb.append(key).append("(").append(value).append(")");}});System.out.println(sb);}
}
5.3-案例3-文件夹拷贝
package com.itheima.stream;import java.io.*;public class CopyDirTest {/*拷贝一个文件夹, 考虑子文件夹将D:\\test文件夹, 拷贝到E:\\*/public static void main(String[] args) throws IOException {File src = new File("D:\\test");File dest = new File("E:\\");if (src.equals(dest)) {System.out.println("目标文件夹是源文件夹的子文件夹");} else {copyDir(src, dest);}}public static void copyDir(File src, File dest) throws IOException {File newDir = new File(dest, src.getName());newDir.mkdirs();// 从数据源中获取数据(File对象)File[] files = src.listFiles();// 遍历数组, 获取每一个文件或文件夹对象for (File file : files) {// 判断当前对象是否是文件if (file.isFile()) {// 是的话直接拷贝FileInputStream fis = new FileInputStream(file);FileOutputStream fos = new FileOutputStream(new File(newDir, file.getName()));int len;byte[] bys = new byte[1024];while ((len = fis.read(bys)) != -1) {fos.write(bys, 0, len);}fis.close();fos.close();} else {// 如果是文件夹, 递归调用方法copyDir(file, newDir);}}}
}