IO
什么是流?
概念:内存与存储设备(硬盘)之间传输数据的通道。
数据借助流传输。
流的分类
按流向:
-
输入流:将【存储设备】中的数据内容读到【内存】中。
-
输出流:将【内存】中的数据内容读到【存储设备】中。
按单位:
-
字节流:以字节为单位,可以读写所有数据。
-
字符流:以字符为单位,只能读写文本数据。
按功能:
-
节点流:具有实际传输数据的读写功能。
-
过滤流:再节点流的基础之上增强功能。
字节流
字节流的父类(抽象类):
InputStream:
public int read(){}
public int read(byte[] b){}
public int read(byte[] b,int off,int len){}
OutputStream:
public void write(int n){}
public void write(byte[] b){}
public void write(byte[] b,int off,int len){}
FileInputStream的使用:
FileInputStream fis = new FileInputStream("D:\\a.txt"); --创建FileInputStream,并指定需要读取文件的路径
fis.read(); --单个字节读取文件内容
int data = 0;
while((data = fis.read()) != -1){
System.out.println((char)data);
}
fis.close(); --关闭
?
?
FileInputStream fis = new FileInputStream("D:\\a.txt");
byte[] buf = new byte[1024]; -- 一次性读取多个字节,使用数组进行缓冲
int count = 0;
while((count=fis.read(buf)) != -1){
System.out.println(new String(buf,0,count));
}
FileOutputStream的使用:
FileOutputStream fos = new FileOutputStream("D:\\b.txt",true); --创建FileOutputStream对象,指定输出文件的路径 当后面加上true时,则是在文件后面追加内容,而不是全部覆盖。
fos.write(97); --单个字节输出
fos.write('b');
fos.write('c');
?
String string = "helloword"; --多个字节输出,调用getBytes()方法,转化为字节
fos.write(string.getBytes());
fos.close();
应用:文件复制
FileInputStream fis = new FileInputStream("D:\\a.jpg");
FileOutputStream fos = new FileOutputStream("D:\\b.jpg");
byte[] buf = new byte[1024];
int count = 0;
while((count=fis.read(buf)) != -1){
fos.write(buf,0,count);
}
fis.close();
fos.close();
字节缓冲流
BufferedInputStream/BufferedOutputStream
-
提高IO效率,减少访问磁盘的次数。
-
数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close。
FileInputStream fis = new FileInputStream("D:\\a.jpg");
BufferedInputStream bis = new BufferedInputStream(fis);
int data = 0;
while((data = bis.read()) != -1){
System.out.print((char(data)));
}
bis.close();
System.out.print("执行完毕!");
FileOutputStream fos = new FileOutputStream("D:\\b.jpg");
BufferedOutputStream bos = new BufferedOutputStream(fos);
for(int i=0; i<10; i++){
bos.write("helloword\r\n".getBytes()); --只是写入缓冲区,还没有写入文件
bos.flush(); --刷新到硬盘
}
bos.close();
对象流
ObjectOutputStream/ObjectInputStream
-
增强了缓冲区功能。
-
增强了读写8种基本数据类型和字符串功能。
-
增强了读写对象的功能。
-
readObject() --从流中读取一个对象
-
writeObject() --向流中写入一个对象
-
使用流传输对象的过程称为序列化、反序列化。
序列化
使用ObjectOutputStream实现对象的序列化。
注意点:序列化的对象必须要实现Serializable接口,否则会报异常
?
1.创建对象流
FileOutputStream fos = new FileOutputStream("D:\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
2.序列化(写入操作)
Student lihui = new Student("lihui",20);
oos.writeObject(lihui);
3.关闭
oos.close();
System.out.print("执行完毕!")
?
public class Student implements Serializable{
?
}
反序列化
1.创建对象流
FileInputStream fis = new FileInputStream("D:\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
2.读取文件(反序列化)
Student s = (Student)ois.readObject();
3.关闭
ois.close();
System.out.println("执行完毕!");
System.out.println(s.toString());
注意事项:
-
序列化类必须要实现Serializable接口。
-
序列化类中对象属性要求实现Serializable接口(类属性里夹杂了其它类对象)。
-
序列化版本号ID serialVersionUID,保证系列化的类和反序列化的类是同一个类。
-
使用transient(瞬间的)修饰属性,这个属性不能被序列化。
-
静态属性不能被序列化。
-
序列化多个对象,可以借助集合实现。
字符编码
ISO-8859-1:一般是美国使用,英文中一个字母代表一字节。中国字比较复杂,1字节=8位。
1字节(byte)=8位(bit)
1024字节=1K
1024k=1M
UTF-8:国际使用,基本上所有语言都包括。
GBK2312:简体中文。
GBK:简体中文,扩充。
当编码方式与解码方式不一致时,会出现乱码。
字符流
读取文件中的中文内容,中文并不是一个字代表一个字节,而是一个字代表多个字节,因此,使用字节流读取会出现乱码,要使用字符流。
字符流的父类(抽象类):
Reader:字符输入流
public int read(){}
public int read(char[] c){}
public int read(char[] b,int off,int len){}
Writer:字符输出流
public void write(int n){}
public void write(String str){}
public void write(char[] c){}
文件字符流
-
FileReader:
public int read(char[] c)
-
FileWriter:
public void write(String str)
FileReader
1.创建FileReader 文件字符输入流
FileReader fr = new FileReader("D:\\hello.txt");
2.读取
char[] buf = new char[1024];
int count = 0;
while((count=fr.read(buf)) != -1){
System.out.println(new String(buf,0,count));
}
3.关闭
fr.close();
FileWriter
1.创建FileWriter对象
FileWriter fw = new FileWriter("D:\\hello.txt");
2.写入
for(int i=0; i<10; i++){
fw.writer("java是世界上最好的语言!");
fw.flush();
}
3.关闭
fw.close();
应用:字符流复制文件
1.创建写入写出对象
FileReader fr = new FileReader("D:\\hello.txt");
FileWriter fw = new FileWriter("D:\\hello1.txt");
2.读写
int data = 0;
while((data=fr.read()) != -1){
fw.write(data);
fw.flush();
}
fr.close();
fw.close();
注意:
-
使用FileReader和FileWriter复制文本文件,不能复制图片或二进制文件(0101010....)。
-
使用字节流可以复制任何形式文件。
字符缓冲流
BuffererReader\BufferedWrite
-
高效读写
-
支持输入换行符
-
可一次写一行、读一行 readLine()
1.创建缓冲流
FileReader fr = new FileReader("D:\\hello.txt");
BufferedReader br = new BufferedReader(fr);
2.读取
char[] buf = new char[1024];
int count = 0;
while((count = br.read()) != -1){
System.out.print(new String(buf, 0, count));
}
3.关闭
br.close();
?
-- 也可以一行一行读取
String line = null;
while((line = br.readLine() != null)){
System.out.println(line);
}
1.创建缓冲流
FileWrite fw = new FileWrite("D:\\HELLO.txt");
BufferedWrite bw = new BufferedWrite(fw);
2.写入
for(i =0; i<10; i++){
bw.write("好好学习,天天向上!");
bw.newLine(); --写入一个换行符
bw.flush();
}
3.关闭
bw.close();
打印流
PrintWrite()的使用:
-
封装了prInt()/println()方法,支持写入后换行。
-
支持数据原样打印。
1.创建打印流
PrintWrite pw = new PrintWrite("D:\\print.txt");
2.打印
pw.println(97);
pw.println(true);
pw.println('a');
3.关闭
pw.close();
转换流
桥转换流:InputStreamReader/OutputStreamWriter
-
可将字节流转换为字符流。
-
可设置字符的编码方式。
1.创建InputStreamReader对象
FileInputStream fis = new FileInputStream("D:\\write.txt");
InputStreamReader isr = new InputStreamReader(fis,"utf-8"); --带上编码方式
2.读取文件
int data = 0;
while((data=isr.read()) != -1){
System.out.println((char)data);
}
3.关闭
isr.close();
1.创建OutputStreamWrite
FileOutputStream fos = new FileOutputStream("D:\\info.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
2.写入
for(int i =0; i<10; i++){
osw.write("好好学习,天天向上!");
osw.flush();
}
3.关闭
osw.close();
File类
File类的使用:
-
分隔符。
-
文件操作。
-
文件夹操作。
-- 分隔符
public static void separator(){
System.out.println("路径分隔符"+File.pathSeparator); --路径分隔符 ;
System.out.println("名称分隔符"+File.separator); --名称分隔符 \
}
?
-- 文件操作
public static void fileOpe(){
?
1.创建文件
File file = new File("d:\\file.txt");
if(!file.exists){
boolean b = file.createNewFile();
System.out.println("创建结果" + b);
}
2.删除文件
file.delete();
3.获取文件信息
System.out.println("获取文件的绝对路径" + file.getAbsolutePath());
System.out.println("获取文件路径" + file.getPath());
System.out.println("获取文件的名称" + file.getName());
System.out.println("获取文件的父目录" + file.getParent());
System.out.println("获取文件的长度" + file.getLength());
System.out.println("获取文件的创建时间" + new Date(file.lastModified().toLocaleString());
4.判断
System.out.println("文件是否可写" + file.canWrite());
System.out.println("是否是文件" + file.isFile());
System.out.println("是否隐藏" + file.isHidden());
}
?
-- 文件夹的操作与文件的操作类似
有一点需要注意
dir.mkdir(); --只能创建单级目录
dir.mkdirs(); --可以创建多级目录
Properties
Map接口中还有一个实现类Hashtable,它和HashMap 十分相似,区别在于Hashtable是线程安全的。Hashtable存取元素时速度很慢,目前基本上被HashMap类所取代,但Hashtable类有一个子类Properties在实际应用中非常重要,Properties主要用来存储字符串类型的键和值,在实际开发中,经常使用Properties集合来存取应用的配置项。
-
Properties:属性集合。
-
特点:
-
存储属性名和属性值
-
属性名和属性值都是字符串类型
-
没有泛型
-
和流有关 可保存在流中或从流中加载
-
1.创建集合
Properties properties = new Properties();
2.添加数据
properties.setProperties("username", "lihui");
properties.setProperties("age", "20");
3.遍历
Set pronames = properties.stringPropertyNames();
for(String pro : pronames){
System.out.println(pro + "-----------" + propeoties.getProperties(pro));
}
?
-- 和流有关的方法
-- list 方法
PrintWriter pw = new PrintWriter("D:\\print.txt");
properties.list(pw);
pw.close();
?
-- store方法 保存
FileOutputStream fos = new FileOutputStream("D:\\store.properties");
properties.store(fos);
fos.close();
?
-- load方法 加载
FileInputStream fis = new FileInputStream("D:\\store.properties");
properties.load(fis);
fis.close();
总结:
-
内存与存储设备之间的传输数据的通道。
流的分类:
-
输入流,输出流;字节流,字符流;节点流,功能流。
序列化、反序列化:
-
将对象通过流写入到文件,或将对象通过流读取到内存,必须实现Serializable。
File对象: