文件目录结构
注:io流的操作 基本都是固定的 1.实例化节点0流 2.实例化处理流3.数据的操作4.流的关闭
一.File
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.util.Date;
//file 指文件 或 文件目录 俗称文件夹
//相对路径 从module下开始
//分隔符 windows dos “/” unix:\ 详情可参考file中的separator
public class FileTest {
@Test
public void InstantiateFile() {
//创建file方式一 File(filepath)
//此时只是创建一个内存对象 并未操作
File file1 = new File("hello.txt");
File file2 = new File("E:\\Jdbc\\IOTe\\he.txt");
// System.out.println(file1);
// System.out.println(file2);
//构造器2 File(String parent, String child)
File file3 = new File("E:\\Jdbc\\","IOTe");
System.out.println(file3);
//构造器3 (File parent, String child)
File file4 = new File(file3,"h.txt");
// System.out.println(file4);
}
@Test
public void CommonMethod1(){
//常用方法
File file = new File("hello.txt");
//绝对路径
System.out.println(file.getAbsoluteFile());
//是否可读
System.out.println(file.canRead());
//是否可写
System.out.println(file.canWrite());
//获取名字
System.out.println(file.getName());
//获取相对路径
System.out.println(file.getPath());
//获取上层路径 若无 返回null 因为是相对路径 所以是null
System.out.println(file.getParent());
System.out.println(file.getParentFile());
//获取文件长度 字节数 不能获取目录
System.out.println(file.length());
//最后一次的修改时间 毫秒值
System.out.println(new Date(file.lastModified()));
}
@Test
public void CommonMethod2(){
//关于文件目录的方法
//目录必须存在
File file = new File("E:\\Java");
String[] list = file.list();
for (String s: list) {
System.out.println(s);
}
//列出全路径
System.out.println();
System.out.println();
File[] file1 = file.listFiles();
for (File f: file1) {
System.out.println(f);
}
}
@Test
public void ParticularMethod(){
//特殊方法renameTo:public boolean renameTo(File dest) 将文件一的内容复制到文件二当中
File f1 = new File("hello.txt");//文件1必须存在
File f2 = new File("hi.txt");//文件2必须不存在,存在即false
boolean b = f1.renameTo(f2);
System.out.println(b);
}
@Test
public void JudgeMethod(){
//常见的判断方法
File file = new File("hello.txt");
//判断是否是文件目录
System.out.println(file.isDirectory());
//判断是否是文件
System.out.println(file.isFile());
//判断是否存在
System.out.println(file.exists());
//是否可读
System.out.println(file.canRead());
//是否可写
System.out.println(file.canWrite());
//是否可隐藏
System.out.println(file.isHidden());
}
@Test
public void CreateFile() throws IOException {
//创建硬盘中对应的文件或文件目录 本身就存在 不创建并返回false
//file类的创建、删除、重命名、修改时间等方法均需抛异常,且file不存在修改文件的内容等操作
//修改内容等操作需要用到IO流去操作
File file = new File("a.txt");
System.out.println(file.createNewFile());
File directory = new File("D:\\file");
//文件上层目录存在创建,不存在则不创建
System.out.println(directory.mkdir());
//文件上层目录存在创建,不存则一并创建
System.out.println(directory.mkdirs());
}
}
二.节点流
1.FileReader
public class FileReaderTest {
@Test
public void test1() {
//为了一定能关闭流的操作,要用try catch
FileReader fr = null;
try {
//1.file 的实例化 指出操纵的对象
File f = new File("hi.txt");
//2.提供具体的流
fr = new FileReader(f);
//3.数据的读入 read()返回读入的一个字符,到达末尾返回-1.
int data = fr.read();
//返回的是unicode码 即a=97 所以下面用到转换
while (data != -1) {
System.out.print((char) data);
data = fr.read();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//这个是防止fr在实例化时失败,即没有fr对象
assert fr != null;
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//4.流的关闭操作
//对于jvm的垃圾回收功能 数据库连接 输入输出流 Socket连接 jvm回收不了,
//需要手动关闭
}
@Test
public void test2() {
//read() 进阶版
FileReader fr = null;
try {
File f = new File("hi.txt");
fr = new FileReader(f);
//read(char[] cb):返回每次读入cb数组中字符的个数 如果读到最后一个值返回-1
char[] cb = new char[5];
int len;
while ((len = fr.read(cb)) != -1) {
/* 错误的写法 说明存入数据的时候是一个一个存的 而并非一次性存满整个数组
方式一
for (char c : cb) {
System.out.print(c);
}
结果guess234ss
方式二
String str = new String(cb);
System.out.println(str);
*/
//正确的 即读进去几个就遍历几个
//方式一
// for (int i = 0; i <len ; i++) {
// System.out.print(cb[i]);
// }
//方式二
//从0开始读每次读len个
String str = new String(cb,0,len);
System.out.print(str);
//结果guess234
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//read(char cb[], int off, int len)
//reed 的三个参数的方法 比如cb的长度是5,但是在存入的时候存放len个长度
}
2.FileWriter
public class FileWriterTest {
@Test
//1.写入的操作中,允许文件不存在,如果不存在则在输出的过程直接进行创建
//2.如果本身文件就存在:
// (1):writer(file)/writer(file,false) 则会对原文件进行覆盖
// (2):writer(file,true)则会对原文件进行追加内容
public void test1() throws IOException {
//1.file 的实例化
File f = new File("hello.txt");
//2.FileWrite的实例化
FileWriter fw = new FileWriter(f);
//3.对数据进行操作
fw.write("Position");
fw.write("You can see ?");
//4.进行资源的关闭
fw.close();
}
@Test
public void copy() throws Exception {
//1.实例化file
File file = new File("hi.txt");
File fl = new File("hi1.txt");
//2.创建输入输出流对象
FileReader fr = new FileReader(file);
FileWriter fw = new FileWriter(fl, true);
//3.操作数据
char[] cb = new char[5];
int len;
while ((len = fr.read(cb)) != -1) {
//我的里面8个字符 第一次len=5,第二次len=3
String str = new String(cb, 0, len);
fw.write(str, 0, len);
}
//4.资源关闭
fw.close();
fr.close();
}
}
3.FileInputStream 和 FileOutputStream
public class FileInputOutputStream {
@Test
public void copyImg() {
//注 字节流可以可以拿来复制文本文件的东西 在内存层面读可能会出出现乱码,但是复制好之后不会出现乱码
//数组的长度,不同长度 影响读取的速度 并非越大越好
FileOutputStream fos = null;
FileInputStream fis = null;
try {
//1.实例化file 注意路径符\\
File file1 = new File("src\\img\\1.png");
File file2 = new File("2.png");
//2.实例化流
fos = new FileOutputStream(file2);
fis = new FileInputStream(file1);
//3.操作数据
byte[] by = new byte[5];
int len;
while((len=fis.read(by)) != -1){
fos.write(by,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//流的关闭
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
三.处理流
1.缓冲流 BufferedInputStream BufferedOutputStream
public class Buffer1 {
@Test
public void copyImgPlus() throws IOException {
//1.实例化file
File file1 = new File("src\\img\\1.png");
File file2 = new File("3.png");
//2.创建节点流
FileInputStream fis = new FileInputStream(file1);
FileOutputStream fos = new FileOutputStream(file2);
//3.创建处理流 处理流就是套接在节点流之上
//缓冲流作用 增加读写速度(原因是因为内部提供了一个缓冲区)
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//bis.flush;刷新缓冲区,Java后台自动刷新所以不用写
//4.操作数据
byte[] by = new byte[5];
int len;
while ((len=bis.read(by)) != -1){
bos.write(by,0,len);
}
//5.流的关闭 先关外层的再关内层的 关闭外层流的同时,内层流也会自动关闭
// 然后 try catch 快捷建 Alt Shift z
bos.close();
bis.close();
}
@Test
public void copyPlus() {
//用匿名对象 实例化file 实例化流
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(new File("hi.txt")));
bw = new BufferedWriter(new FileWriter(new File("hi1.txt")));
//操作数据 方式一
// char[] cr = new char[5];
// int len;
// while ((len=br.read(cr)) != -1){
// bw.write(cr,0,len);
// }方式二 缓冲流里有直接读取一行的方法
String data;
while((data=br.readLine()) !=null){
// bw.write(data); 此时数据没有换行
//加换行符 或者直接 bw.newline()
bw.write(data+"\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//流的关闭
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
//加密操作
public void encrypt() {
//实例化
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("24.png");
// public FileInputStream(String name) 有这个形参 所以直接可以放文件路径
fos = new FileOutputStream("28.png");
//操作数据
byte[] bt = new byte[10];
int len;
while ((len=fis.read(bt)) != -1){
//主要就是进行异或运算 两次异或之后就得到了原来的文件
for (int i = 0; i < len; i++) {
bt[i] = (byte) (bt[i] ^ 2);
}
fos.write(bt,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//流的关闭
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2.转换流 InputStreamReader OutputStreamWriter
public class ChangeStream {
//转换流
//InputStreamReader 将字节的输入流转换为字符的输入流
//OutputStreamWriter 将字符的文件 转换为字节的文件
//作用 实现流之间的转换
// 解码 字节——>字符 编码 字符->字节
@Test
public void changeOut() throws IOException {
//1.实例化流 节点流
FileInputStream fis = new FileInputStream("hi.txt");
//2.实例话处理流(处理流)
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
//次方法有 只有一个参数 参数为节点流对象 默认为的字符集是编译软件所设置的 两个参数的 第二个参数为文件保存时的字符集
//3.操作数据
char[] ca = new char[5];
int len;
while ((len= isr.read(ca)) != -1){
for (int i = 0; i < len; i++) {
System.out.print(ca[i]);
}
}
//4.流的关闭 容易观看 未用try catch
}
@Test
public void changeInOut() throws Exception {
//用字节流读取utf-8格式的文件 再以 gbk的形式输出
FileInputStream fis = new FileInputStream("hi.txt");
InputStreamReader isr = new InputStreamReader(fis);
FileOutputStream fos = new FileOutputStream("hi_gbk.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
char[] ca = new char[5];
int len;
while ((len= isr.read(ca)) != -1){
osw.write(ca,0,len);
}
isr.close();
osw.close();
}
}
3.对象流 ObjectInputStream ObjectOutputStream
public class ObjectStream {
//ObjectInputStream ObjectOutputStream
//作用 用于存储和读取基本类型的数据或对象的处理流 持久化Java中的数据
@Test
public void xlh() throws Exception {
//序列化 过程:将内存层面的数据存到磁盘中或者进行网络传输 ObjectOutputStream
//1.创建一个序列化对象 后缀名可以随意,因为不是用来给我们看的
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("result.sj"));
//2.把对象写进去
String s="我是最帅的";
oos.writeObject(s);
oos.flush();
//刷新操作
oos.writeObject(new Teacher(99,"帅B"));
oos.flush();
//3.关闭流 记得try catch finally alt shift z
oos.close();
}
@Test
public void reverseXlh() throws Exception {
//反序列化 就是把序列化的数据还原到内存层面
//1.创建反序列化对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("result.sj"));
//2.把对象读出来
String s = (String) ois.readObject();
Teacher teacher = (Teacher) ois.readObject();
//测试数据是否读出
System.out.println(s);
System.out.println(teacher);
//3.关闭流 记得try catch finally alt shift z
ois.close();
}
}
注:关于序列化
public class Teacher implements Serializable {
//要想序列化一个对象 需要满足的条件
//1.继承 Serializable接口(该接口并没有具体的方法(这样的接口一般叫做标识))
//2.实例化一个常量 serialVersionUID = 42L
//3.注 static transient 修饰的成员变量不能序列化
//特殊: 当你所序列化的对象中含有其他对象属性没继承Serializable接口 也会出现问题
//解决: 把其他对象也实现此接口并赋予一个值serialVersionUID
private int id;
private String name;
//自己随便写一个 long类型的 如果未写 会自动生成 不过当再次修改之后再进行反序列化会出现一些问题
//作用 就是标识 就像身份证号一样
private static final long serialVersionUID =456464445452L;
public Teacher() {
}
public Teacher(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Teacher{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
}
四.其他的流(部分流未写)
标准的输入输出流以及打印流
public class OtherStream {
public static void main(String[] args) throws Exception {
//标准的输入流: System.in 默认从键盘输入
//标准的输出流: System.out 默认从控制台输出
//setIn (InputStream)设置输入 setOut(PrintStream) 设置输出
// 键盘输入字符串->“整行”输出大写字符串 exit结束(@Test执行时会执行不了)
//1.接收数据 用转换流的原因 字节流才能使用System.in 用完之后要转换成字符
System.out.println("请输入想要转换的字符串");
InputStreamReader isr = new InputStreamReader(System.in);
//2.把数据放入缓冲流(因为缓冲流有接收一行的方法)
BufferedReader br = new BufferedReader(isr);
//3。操作数据
while (true){
String data= br.readLine();
//不区分大小写
if ("exit".equalsIgnoreCase(data)) {
break;
}
//转为大写
String result = data.toUpperCase();
System.out.println(result);
}
//4.关闭流(记得try catch finally)
br.close();
}
@Test
public void printStream() {
//打印流
//PrintStream PrintWriter
//特点 1.不会抛IOException 2.只能接受相对应的流 3.都有自动flush()功能
//4.打印的所有字符都是使用平台的默认字符转换编码转换为字节,在需要使用字符而不是字节的情况下用PrintWriter
//1.实例化 注意不能用FileWrite printStream不能接收FileWrite的对象
PrintStream ps = null;
try {
FileOutputStream fos = new FileOutputStream("hi21.txt");
//2.创建打印流 true 是设置自动刷新(换行即刷新)
ps = new PrintStream(fos,true);
System.setOut(ps);
for (int i = 50; i <255; i++) {
//输出的是
System.out.print((char)i);
//实现每读取5个数据进行换行
if (i % 50==0) {
System.out.println();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (ps != null) {
try {
ps.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}