写在前面:
createNewFile() mkdir() mkdirs() |
delete() |
exists() isDirectory() isFile() getName() getPath() getAbsolutePath() list() listFile() |
抽象类 InputStream OutputStream | 文件: FileInputStream (path/File) FileOutputStream (path/File, [true | fis.read(空/ byte[]) fos.write(int/ byte[]/ byte[], int,int) |
缓冲: BufferedInutStream(InputStream) BufferedOutputStream(OutputStream) | 同上 | |
对象序列化: ObjectOutputStream(OutputStream) 对象反序列化: ObjectInputStream(InputStream) | oos.writeObject(Object) ois.readObject()
相应的类: 实现接口 Serializable 定义静态常量 SerialVersionUID 不序列化的对象需要用 transient 修饰 | |
打印类 PrintStream (path) | 转码: ps.write(int/ byte[]/ byte[], int,int) //同OutputStream 不转码: ps.print(xxx) ps.println(xxx) |
抽象类 Reader Writer | InputStreamReader (Inputstream, [String OutputStreamWriter (OutputStream, [Stirng | isr.read (空/ char[])
osw.write (int /char[]/ String / char[],int,int/ String,int,int)
osw.flush() |
上面的简化:默认编码 FileReader (path) FileWriter (patn) | 同上 | |
缓冲: BufferedReader (Reader) BufferedWriter (Writer) | 同上
另:特有方法 br.readLine() bw.newLine() | |
打印类 PrintWriter(path / Writer,boolean) boolean为true: 自动刷新 | 使用同打印字节流
另:没有自动刷新时 添加刷新方法 pw.flush() |
针对Object类型,使用同map | prop.put (k,v) prop.get (k) prop.keySet() |
针对 String 类型,特有方法 | prop.setProperty (k,v) prop.getProperty (k) prop.StringPropertyNames() |
与 IO 结合 | 文件内容 写入 Properties: prop.load (InputStream/ Reader) Properties内容 写入 文件: prop.store (OutputStream/ Writer, String |
1. File
File:文件和路径名的抽象表示,仅仅是一个路径而已
File重写了toString()方法,返回路径名
//三种构造方法:只是一个路径名,并没有做创建等操作
File file01=new File("/Users/rainbow/Desktop/test01.txt");
File file02=new File("/Users/rainbow/Desktop","test02.txt");
File file031=new File("/Users/rainbow/Desktop");
File file03=new File(file031,"test03.txt");
createNewFile() | 创建文件;文件不存在返回true,存在返回false |
mkdir() | 创建目录 |
mkdirs() | 创建多级目录 |
File file01=new File("/Users/rainbow/Desktop/test01/test02");
File file02=new File("/Users/rainbow/Desktop/test01/test02/test.txt");
file01.mkdirs();
try {
file02.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
delete() | 删除文件或目录;目录下有内容时,不能直接删除 |
exists() isDirectory() isFile() | 是否存在 是不是目录 是不是文件 |
getName() getPath() getAbsolutePath() | 文件名 路径名 绝对路径名 |
list() listFile() | 目录下的文件和目录 String[]格式 目录下的文件和目录 File[]格式 |
2. 字节流
流:数据传输
IO流:设备间的数据传输
输入流/输出流:读数据--输入流,写数据--输出流
字节流/字符流:txt不能读懂的--字节流(万能的),txt能读懂的--字符流
- 抽象类:InputStream、OutputStream
InputStream:字节输入流的超类,子类以InputStream作后缀
OutputStream:字节输出流的超类,子类以OutputStream作后缀
- 文件输出流:FileOutputStream(向文件写数据)
简单流程:
//1. 创建文件;创建字节流对象;字节流对象指向文件
FileOutputStream fos=new FileOutputStream("test01.txt");
//2. 写文件:写的是字节,文件中显示a
fos.write(97);
//3. 所有IO相关的操作都要释放资源并关闭流
fos.close();
追加写入:
new FileOutputStream(path, true); //path处可以是String,也可以是File
写文件:
write(int b); //写一个字节
write(byte[] b); //多个字节:定义byte[],或者string.getBytes()
write(byte[] b, int off, int len); //多个字节,从字节的索引off开始写len个字节
写回车:
linux \n
mac \r
window \r\n
- 文件输入流:FileInputStream(从文件读数据)
简单流程:
//1. 创建文件;创建字节流对象;字节流对象指向文件
FileInputStream fis=new FileInputStream("test01.txt");
//2. 读文件:返回int,返回值 -1 结束
fis.read();
//3. 所有IO相关的操作都要释放资源并关闭流
fis.close();
读文件:
read(); //一个字节
read(byte[]); //读一个字节数组,返回实际读到的个数 (注意:会读到换行符)
一般定义的数组大小为1024及其整数倍:byte[] b=new byte[1024];
//例子:复制图片
public void fileCopy(){
FileInputStream fis=null;
FileOutputStream fos=null;
try {
fis=new FileInputStream("/Users/rainbow/Pictures/1.jpg");
fos=new FileOutputStream("copy.jpg");
byte[] bytes=new byte[1024];
int len;
while ((len=fis.read(bytes)) != -1){
fos.write(bytes,0,len); //读多长,就写多长
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally { //close
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//(JDK7之后的改进)异常处理的改进
public void fileCopy(){
try (FileInputStream fis=new FileInputStream("/Users/rainbow/Pictures/1.jpg");
FileOutputStream fos=new FileOutputStream("copy.jpg");) {
byte[] bytes=new byte[1024];
int len;
while ((len=fis.read(bytes)) != -1){
fos.write(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
//自动释放资源
}
- 字节缓冲流:BufferedInputStream、BufferedOutputStream
只提供缓冲区,读写数据还是要靠基本的字节流对象
内置缓冲区数组,数组大小默认8192
BufferedOutputStream:向 底层输出流 写入字节,不用每个字节都调用底层系统
简单流程:
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("test.txt"));
bos.write("abc".getBytes());
bos.close();
//例子:复制视频
public void videoCpoy(){
try (BufferedInputStream bis=new BufferedInputStream(new FileInputStream("/Users/rainbow/Desktop/小猫.mp4"));
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("copyVideo.mp4"));) {
byte[] bytes=new byte[1024];
int len;
while((len=bis.read(bytes)) != -1){
bos.write(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
3. 字符流:字节流+编码表
汉字:汉字存储,第一个字节一定是负数
BGK编码:2个字节
UTF-8编码:3个字节
字节流操作汉字不方便,所以提供字符流
编码和解码要用同一个编码表(比如都用UTF-8)
//例子
public void code(){
String str="中国";
byte[] bytes= new byte[0];
try {
//编码
bytes = str.getBytes("UTF-8");
for (byte by:bytes) {
System.out.println(by);
}
//解码
String string=new String(bytes,"UTF-8");
System.out.println(string);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
- 抽象类:Writer、Reader
-
Writer:字符输出流的超类,子类以Writer作后缀
Reader:字符输入流的超类,子类以Reader作后缀
- OutputStreamWriter、InputStreamReader
可以采用系统默认编码,也可以指定编码
简单流程:(写文件)
FileOutputStream fos=new FileOutputStream("/Users/rainbow/Desktop/test01.txt");
OutputStreamWriter ost=new OutputStreamWriter(fos, "UTF-8");
ost.write("你好");
ost.flush();
ost.close();
new OutputStreamWriter(OutputStream子类对象, 编码格式); //编码格式不写,表示采用系统默认编码格式
flush方法://刷新流
字符流写数据,不能直接写入文件,会先写入缓冲区
调用flush方法,将缓冲区中内容写入文件
flush方法后可继续写文件
close方法:
close方法,释放资源并关闭流
在关闭流之前会先刷新(flush),所以调用close方法时,可以不调用flush方法
read() 参数:
空:一次一个字节,返回读到的信息
char[ ]:一次一个字符数组,返回实际读到的数组长度
write() 参数:
int:一次一个字符
char[ ]:一次一个字符数组
char[] c,int off,int len:从数组的off索引开始,取长度len
String:字符串
String,int off,int len:字符串从索引off开始,读取len长度
- FileReader、FileWriter:简化
采用默认编码方式
构造方法可以直接写路径:FileReader(String path)
使用方法同:InputStreamReader、OutputStreamWriter
- BufferedReader、BufferedWriter:字符缓冲流
缓冲区默认数组大小8192
简单流程:
BufferedReader br=new BufferedReader(new FileReader("/Users/rainbow/Desktop/test01.txt"));
br.readLine();
br.close();
字符缓冲流特有方法:
readLine() :读取一行数据,不包括换行符;读到 null 表示结束
newLine() : 写换行
public void zifu(){
String path="/Users/rainbow/Desktop/test01.txt";
//简单字符流写文件
try(
FileOutputStream fos=new FileOutputStream(path);
OutputStreamWriter ost=new OutputStreamWriter(fos, "UTF-8");
){
ost.write("你好");
ost.write("\r"); //mac
ost.write("Java");
ost.flush();
}catch (IOException e){
e.printStackTrace();
}
//字符缓冲流读取文件
try(
BufferedReader br=new BufferedReader(new FileReader(path));
){
String str;
while((str=br.readLine()) != null) {
System.out.println(str);
}
}catch (IOException e){
e.printStackTrace();
}
}
4. 打印
- PrintStream:打印字节
new PrintStream(path) :使用文件名,创建打印流
write :打印会转码
print / println : 原样输出
String path="/Users/rainbow/Desktop/test01.txt";
//字节
try(
PrintStream ps=new PrintStream(path);
){
ps.write(97);//打印:a
ps.print(97); //打印:97
ps.println(97); //打印:97
}catch (IOException e){
e.printStackTrace();
}
- PrintWriter:打印字符
因为是打印字符,所以需要刷新
两种构造方法:new PrintWriter(path);
new PrintWriter(Writer, boolean); //boolean为true,表示自动刷新,不用再写flush方法
//字符
try(
PrintWriter pw=new PrintWriter(path);
){
pw.write("你好");
pw.flush();
}catch (IOException e){
e.printStackTrace();
}
//字符
try(
PrintWriter pw=new PrintWriter(new FileWriter(path),true);//true自动刷新
){
pw.println("你好啊");
}catch (IOException e){
e.printStackTrace();
}
5. 字节流---对象序列化
将对象保存到磁盘,或在网络中传输,需要使用 字节序列 表示对象(对象序列化)
类需要实现接口:Serializable,只是一个标识接口,没有方法需要重写
为每个类关联一个版本号UID,类修改后,UID发生变化
可在类内显示定义一个UID,以保证类修改后,UID不变:serialVersionUID
private static final long serialVersionUID=1L;//数值自己定
类内不想被序列化的成员变量(不想让别人知道的成员):用 transient 修饰
private transient int age;
- ObjectOutputStream:序列化流
- ObjectInputStream:反序列化流
new ObjectOutputStream(OutputStream) 、 new ObjectInputStream(InputStream)
序列化方法:oos.writeObject(Object obj);
反序列化方法:Object o = ois.readObject();
public void funSerial(){
String path="test01.txt";
Student student=new Student(1,"xiaohei",23);
//序列化
try (
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(path));
){
oos.writeObject(student);
} catch (IOException e) {
e.printStackTrace();
}
//反序列化
try (
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(path));
){
Object o = ois.readObject();
System.out.println(o);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
6. 附加:Properties
properties:map体系的集合类,可保存到流中,也可从流中加载
- Properties
key和value的类型都是Object,使用同map
有针对String类型的特有方法:
Properties properties=new Properties();
properties.setProperty("A","apple"); // 同Object类型的:properties.put("A","apple");
properties.getProperty("A"); // 同Object类型的:properties.get("A");
properties.stringPropertyNames();// 同Object类型的:properties.keySet();
- Properties 与 IO 结合
将文件内容写入Properties:load
properties.load(InputStream); //字节
properties.load(Reader); //字符
将Properties内容写入文件:store
properties.store(OutputStream,String comments); //字节;comments说明,没有特殊说明就写 null
properties.store(Writer,String comments); //字符
public void funProperties(){
String path="test01.txt";
Properties properties=new Properties();
//方法测试
properties.setProperty("A","apple"); // 同Object类型的:properties.put("A","apple");
properties.getProperty("A"); // 同Object类型的:properties.get("A");
properties.stringPropertyNames();// 同Object类型的:properties.keySet();
//与 IO 结合
try (
FileWriter fw=new FileWriter(path);
FileReader fr=new FileReader(path);
){
//properties内容写入文件
properties.store(fw,null);
//文件内容写入properties
properties.load(fr);
} catch (IOException e) {
e.printStackTrace();
}
}