声明:本笔记大部分来自观看该文章的心得: 原文链接 博主:宜春 本人文章仅用于查阅和本人记录知识点,如有侵权本人会自行删除。
IO文件流
IO流的含义:
Java的IO流是实现输入和输出的基础,可以方便的实现数据的输入和输出操作。在java中把不同的输入/输出源(键盘,文件,网络连接等)抽象表述为“流”(stream)。
流的分类
- 按照 流的文件类型:字节流(InputStream、OutputStream)和字符流(Reader,Writer)
- 按照 流的流向:输入流和输出流
- 按照 功能 :节点流 和 过滤流
所有文件数据(文本、图片、视频等)在存储时,都是二进制数字的形式,也就是一个一个的字节,传输时一样如此。所以,字节流可以传输任意文件数据。 绝对路径:一个完整的路径,以盘符开头,例如F://123.txt
相对路径:一个简化的路径,不以盘符开头,例如//123.txt//b.txt。
常用API
字符流
输入流创建
File file = new File("xxx.txt");
FileReader reader= new FileReader(file);
FileReader reader = new FileReader("a.txt");
读取字符数据
FileReader reader = new FileReader("xxx.txt");
int len = -1;
while ((len = reader .read())!=-1) {
System.out.println((char)len);
}
reader .close();
输出流类比一下
获取功能
getAbsolutePath() :返回此File的绝对路径名字符串。 getPath() :将此File转换为路径名字符串。 getName() :返回由此File表示的文件或目录的名称。 length() :返回由此File表示的文件的长度(字节)
如果File是目录,则返回值未指定。
判断功能
exists() :此File表示的文件或目录是否存在。 isDirectory() :此File表示的是否为 目录。 isFile() :此File表示的是否为 文件。
创建、删除功能
createNewFile() :文件不存在,创建一个新的空文件并返回true,文件存在,不创建文件并返回false。 delete() :删除由此File表示的文件或目录。 mkdir() :创建由此File表示的目录。如果父类不存在,则创建失败 mkdirs():创建由此File表示的目录,同时创建不存在的父级目录。 所以一般选用 mkdirs()
遍历目录
public static List<File> searchFiles(File directory, Predicate<File> predicate) {
List<File> files = searchFiles(directory);
File dir = new File("G:\光标");
File[] files = dir.listFiles();
for (File file : files) {
System.out.println(file);
}
}
listFiles指定目录必须存在,且必须指定目录,指定文件会发生空指针异常
File file=new File("D:\\XXX");
List<File> list = Arrays.asList(file.listFiles());
if (file != null) {
for (File f : list) {
if (f.isDirectory()) searchFiles(f);
else list.add(f);
}
}
那么什么时候用字节流什么时用字符流呢 在遍历文件时候,一般选择字符流 而对文件的内容进行读写操作时一般用字节流 无论使用什么样的流对象,底层传输的始终为二进制数据。但在用字符流读写文件内容时,规定的字符容器可能会大于需要读写的的内容(字节)
字节流
字节输、出流(OutputStream) 构造方法 public FileOutputStream(File file):以File对象为参数创建对象。 public FileOutputStream(String name): 以名称字符串为参数创建对象。
开发常用第二种,指定路径字符串
注意:创建输出流对象的时候,如果路径不存在,系统会自动去对应位置创建对应文件 输入流对象的时候,文件不存在则会报FileNotFoundException异常
写出字节、字节数组、指定长度字节数组:
FileOutputStream out = new FileOutputStream("XXX.系统自己创建的.txt");
out .write(97);
out .write(98);
out .write(99);
fos.close();
byte[] b = "麻麻我想吃烤山药".getBytes();
out .write(b);
out.write(b,0,2);
fos.close();
new FileOutputStream(“xxx.txt”,boolean b); 当我向有数据的文件中写出字节时,可以传入第二个参数Boolean boolean为ture时,表示追加数据,不会对元数据进行覆盖。 false 表示不追加 也就是清空原有数据。 ——————————————————————————————————————————————————
字节输入流(InputStream) 构造方法类比输出流 同样推荐第二种狗构造方法
当你创建一个流对象时,传入的路径下,该文件,会抛出FileNotFoundException 。
关于使用字节输入流,读取字节数组时,可能出现的问题:
FileInputStream in = new FileInputStream("read.txt");
int len = -1;
byte[] b = new byte[2];
while (( len= in .read(b))!=-1) {
System.out.println(new String(b));
}
输出结果为 ab cd ed 为何:因为长度为2的数组,每次读取2个字符,下次读取时,另外两个字符将原字符覆盖 第一次:ab 第二次:c覆盖a,d覆盖b 结果为cd 第三次:e覆盖d,原来的d没有被覆盖,所以结果为 ed
close() :关闭流 flush() :强制缓冲的输出字节写出。 write(byte[] b):将Byte数组 .length()个字节数组写入输出流。 write(byte[] b, int off, int len) :从偏移量 off开始输出到此输出流,读取len个字符 write(int b) :将指定的字节输出流。
缓冲流(掌握即可)
创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
构造方法: public BufferedInputStream(InputStream in) :创建一个新的缓冲输入流,注意参数类型为InputStream。 字节输出流一样。 举例: BufferedInputStream bis = new BufferedInputStream(new FileInputStream(“xxx.txt”));
字符缓冲流: BufferedReader,BufferedWriter 字符缓冲流特有方法:
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
String line = null;
while ((line = br.readLine())!=null) {
System.out.print(line);
System.out.println("------");
}
br.close();
字节与字符的转换:
编码:字符(能看懂的) –> 字节(看不懂的) 解码:字节(看不懂的) –> 字符(能看懂的)
FileReader 读取项目中的文本文件。由于IDEA的设置,都是默认的UTF-8编码 但是,由于Windows系统的默认是GBK编码,读取Windows系统中创建的文本文件时,就会出现乱码。
FileReader reader = new FileReader("C:\\xxx.txt");
int len = -1;
while ((len = reader .read()) != -1) {
System.out.print((char)len );
}
reader .close();
序列化与反序列化
Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息
1.该类必须实现java.io.Serializable 接口,Serializable 是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSerializableException 。 2.该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用transient 关键字修饰。
public class User implements Serializable {
private static final long serialVersionUID = -6180688742475305117L;
private Integer id ;
private String username ;
private transient String password ;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("id=").append(id);
sb.append(", username='").append(username).append('\'');
sb.append(", password='").append(password).append('\'');
sb.append('}');
return sb.toString();
}
}
——————————
public class UserSerializer {
@Test
public void test() throws Exception {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:/user.txt"));
User user = new User();
user.setId(1);
user.setUsername("张三");
user.setPassword("1234567");
out.writeObject(user);
out.close();
}
@Test
public void test2() throws Exception{
ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:/user.txt"));
Object o = in.readObject();
if (o instanceof User) {
User user = (User) o ;
System.out.println(user);
}
}
}
序列化练习题:
public class Test2 {
@Test
public void test(){
Goods goods = new Goods("001","奔驰",50.0,1);
System.out.println(JSONArray.toJSON(goods));
String josn = "{\"Id\":001,\"Name\":奔驰,\"Num\":1,\"Price\":50.0";
Goods goods1 = JSONArray.parseObject(josn,Goods.class);
System.out.println(goods1);
}
}
@AllArgsConstructor
@NoArgsConstructor
class Goods{
private String Id;
private String Name;
private Double Price;
private Integer Num;
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Goods{");
sb.append("Id='").append(Id).append('\'');
sb.append(", Name='").append(Name).append('\'');
sb.append(", Price=").append(Price);
sb.append(", Num=").append(Num);
sb.append('}');
return sb.toString();
}
public String getId() {
return Id;
}
public void setId(String id) {
Id = id;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public Double getPrice() {
return Price;
}
public void setPrice(Double price) {
Price = price;
}
public Integer getNum() {
return Num;
}
public void setNum(Integer num) {
Num = num;
}
}
装饰模式(掌握即可)
一种类与类交互的模式 甜品抽象类:
public abstract class Sweet {
public abstract int sell() ;
public abstract int sellPrice() ;
}
蛋糕类
public class CakeSweet extends Sweet{
@Override
public int sell() {
System.out.println("普通蛋糕");
return sellPrice();
}
@Override
public int sellPrice() {
return 50;
}
}
装饰(加工)类 这我自己取的名字哈 别乱用
public class CakeDecrator extends Sweet{
private Sweet sweet ;
private String fruit ;
public CakeDecrator(Sweet sweet, String fruit) {
this.sweet = sweet ;
this.fruit = fruit ;
}
public void sellFruit() {
System.out.println("本次出售的是" + fruit);
}
@Override
public int sell() {
int price = sellPrice();
sweet.sell();
System.out.println("本次甜点添加了" + fruit);
return price ;
}
@Override
public int sellPrice() {
int price = switch (fruit) {
case "苹果" -> 3 ;
case "葡萄" -> 6 ;
default -> 1 ;
};
return sweet.sellPrice() + price;
}
}
|