字符流、字节流
字节流(输出流)
1.IO
概述
I
:Input
输入
O
:output
输出
顶层父类:
2.字节输出流基本使用
OutputStream
抽象类是表示字节输出流的所有类的超类,因为这个父类是一个抽象类,不能直接创建对象,如果要使用需要借助其子类FileOutputStream
- 如何使用字节输出流?
1)创:创建输出流对象
2)写:借助流对象调用write
方法写出数据
3)关:关闭流资源close
- 构造方法
public FileOutputStream(File file)
public FileOutputStream(String file)
public FileOutputStream(File file,boolean append)
public FileOutputStream(String file,boolean append)
构造方法中都要关联一个文件【不管是文件对象,或者一个字符串文件路径】
- 常用的方法
- public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
- public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
- public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
- public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
- public abstract void write(int b) :将指定的字节输出流。
【代码实践】
public class Demo01 {
public static void main(String[] args) throws IOException {
//1)创:创建输出流对象
//关联文件,用来保存输出的数据
//public FileOutputStream(File file)
//FileOutputStream fos = new FileOutputStream(new File("file10.txt"));
//public FileOutputStream(String file)
FileOutputStream fos = new FileOutputStream("file10.txt");
//2)写:借助流对象调用write方法写出数据
byte[] bytes = "Hello".getBytes();
fos.write(bytes);
//3)关:关闭流资源 close
fos.close();
}
}
3.字节输出流构造方法
FileOutputStream
构造方法:
没有拼接功能:
每次关联文件时:如果文件不存在,会直接创建,如果存在会把内容清空
public FileOutputStream(File file)
public FileOutputStream(String file)
内部原理,就是调用了含有append的构造方法,把append默认为false
有拼接功能:
public FileOutputStream(File file,boolean append): 当第二个参数append为true时,具有拼接功能
public FileOutputStream(String file,boolean append): 当第二个参数append为true时,具有拼接功能
构造方法中都要关联一个文件【不管是文件对象,或者一个字符串文件路径】
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创
//没有拼接功能
// FileOutputStream fos = new FileOutputStream("file11.txt");
//有拼接功能
FileOutputStream fos = new FileOutputStream("file11.txt", true);
//2.写
fos.write("CCCCC".getBytes());
//3.关
fos.close();
}
}
4.字节输出流的写出方法
写出字节数据的方法:
public void write(byte[] bytes):写出所有字节数组中的字节
public void write(byte[] bytes,int off,int len): 写出字节数组的内容,从off索引开始的后面len个
public void write(int i): 写出的是一个字节
/*
public void write(byte[] bytes):写出所有字节数组中的字节
public void write(byte[] bytes,int off,int len): 写出字节数组的内容,从off索引开始的后面len个
public void write(int i): 写出的是一个字节
*/
public class Demo01 {
public static void main(String[] args) throws IOException {
//1:创
OutputStream os = new FileOutputStream("file12.txt", true);
//2:写
byte[] bytes = "abc123".getBytes();
//public void write(byte[] bytes):写出所有字节数组中的字节
//os.write(bytes);
//public void write(byte[] bytes,int off,int len):
// 写出字节数组的内容,从off索引开始的后面len个
//os.write(bytes, 3, 3);
//public void write(int i): 写出的是一个字节
os.write(65);
//3:关
os.close();
}
}
5.字节输出流写出换行
windows: \r\n
linux: \r
可以借助System.lineSeparator()
String ls=System.lineSeparator(); //各种系统通用
public class Demo01 {
public static void main(String[] args) throws IOException {
//windows: \r\n
//linux: \r
//可以借助System.lineSeparator()
//String ls=System.lineSeparator(); //各种系统通用
//1.创
FileOutputStream fos = new FileOutputStream("file13.txt");
//2.写
fos.write("窗前明月光".getBytes());
fos.write("\r\n".getBytes());
fos.write("疑是地上霜".getBytes());
//String ls = System.lineSeparator();//换行符
//fos.write(ls.getBytes());
fos.write(System.lineSeparator().getBytes());
fos.write("举头望明月".getBytes());
//3.关
fos.close();
}
}
字节流(输入流)
1.字节输入流的使用
字节输入流的顶层父类是InputStream
,是一个抽象类,这里定义了所有字节输入流所要使用的方法。
使用时借助其子类FileInputStream
.
入门使用
1)创:创建输入流对象==[需要关联文件]==
public FileInputStream(String file)
public FileInputStream(File file)
2)读:调用read方法读取数据
public int read():一次读取一个字节返回,如果没有返回-1
public int read(byte[] bytes):一次读取多个字节放到数组,返回有效读取的个数,如果没有返回-1
3)关:调用close方法关资源
public void close():关流
【代码实践】
/*
字节输入流的基本使用:
*/
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创
FileInputStream fis = new FileInputStream("file01.txt");
//2.读
//int read()
//传统写法:不会这么去读取
//int r = fis.read();
//System.out.println("r = " + r);
//System.out.println(fis.read());//98
//System.out.println(fis.read());//99
//System.out.println(fis.read());//-1 //表示结束
//优化写法:以后就这么写
int b;
while ((b=fis.read())!=-1) {
System.out.println(b);
}
//3.关
fis.close();
}
}
读取数据的代码优化
字节输入流:
1)创
2)读
3)关
/*
public int read(byte[] bytes):读取多个数据到字节数组,返回有效读取字节个数,如果没有读取到字节返回-1
*/
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创
FileInputStream fis = new FileInputStream("file02.txt");
//2.读
//写法一:
//byte[] bytes = new byte[3];
//int len = fis.read(bytes);
//System.out.println(len+":"+ Arrays.toString(bytes));//3:[97, 98, 99]
//len = fis.read(bytes);
//System.out.println(len+":"+ Arrays.toString(bytes));//1:[49, 98, 99]
//len = fis.read(bytes);
//System.out.println(len+":"+ Arrays.toString(bytes));//-1:[49, 98, 99]
//写法二:高效读取
byte[] bytes = new byte[10];
int len;
while ((len = fis.read(bytes)) != -1) {
//String
System.out.println(new String(bytes,0,len));
//将字节数组中从0开始往后len个字节数据变成字符串
}
//3.关
fis.close();
}
}
2.文件拷贝
需求:
完成 img1/美女.jpg 拷贝到 img2/beauty.jpg
思路:
借助FileInputStream 读取读取数据到内存,然后借助OutputStream写出数据到目标文件
步骤:
1)创:分别创建字节输入和输出流对象
2)读写 : 边读边写
3)关 : 关流
public class Demo01 {
public static void main(String[] args) throws IOException {
//完成 img1/美女.jpg 拷贝到 img2/beauty.jpg
//1)创:分别创建字节输入和输出流对象
FileInputStream fis = new FileInputStream("img1/美女.jpg");
FileOutputStream fos = new FileOutputStream("img2/beauty.jpg");
//2)读写 : 边读边写
//int b;//临时保存读取的字节
//while ((b = fis.read()) != -1) {
// //将读取的字节,写道文件中
// fos.write(b);
//}
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
//3)关 : 关流
fos.close();
fis.close();
}
}
3.字节流读取文本乱码问题
使用字节输入流读取中文:
字节流不适合用来处理文本数据,字符流才适合用来处理文本数据
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创
FileInputStream fis = new FileInputStream("file03.txt");
//2.读
//int b;
//while ((b = fis.read()) != -1) {
// System.out.println((char)b);
//}
byte[] bytes = new byte[2];
int len;
while ((len = fis.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
//3.关
fis.close();
}
}
字符流(输入流)
字符输入流的使用
和字节输入流的操作一样
Reader
是一个抽象类,是字符输入流的超类,定义了字符输入流的相关方法。
实际使用时,用其子类FileReader
基本使用步骤
1)创
构造方法:
public FileReader(String path)
public FileReader(File path)
2)读: 调用read方法读取字符
public int read(): 一次读取一个字符,如果读取到最后没有内容,返回-1
public int read(char[] chars): 一次读取多个字符,返回有效读取的字符个数,如果没有内容了,返 回-1
3)关: 调用close
public void close()
【代码实践】
import java.io.FileReader;
import java.io.IOException;
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创
FileReader fr = new FileReader("file03.txt");
//2.读
//int read():读取一个字符,没有字符返回-1
//System.out.println((char) fr.read());
//System.out.println((char) fr.read());
//System.out.println((char) fr.read());
//System.out.println((char) fr.read());
//System.out.println((char) fr.read());
//System.out.println((char) fr.read());
//System.out.println((char) fr.read());
//System.out.println((char) fr.read());
//System.out.println((char) fr.read());
//System.out.println( fr.read());//-1
//System.out.println( fr.read());//-1
// int c;
// while ((c = fr.read()) != -1) {
// System.out.println((char) c);
// }
//int read(char[] cbuf):读取多个字符到字符数组,返回读取有效个数,如果没有返回-1
char[] cbuf = new char[2];
int len;
while ((len = fr.read(cbuf)) != -1) {
//读取的有效字符变成字符串
System.out.println(new String(cbuf, 0, len));
}
//3.关
fr.close();
}
}
字符流(输出流)
字符输出流的使用
和字节输出流使用极其相似
字符输出流的超类是Writer,是抽象类,里面定义了一些字符输出流通用的方法
public void close(): 关流
public void flush(): 刷新
public void write(int c) :写出一个字符
public void write(char[] chars) :一次写出一个字符数组
public void write(char[] chars,int off, int len) :一次写出一个字符数组中指定的字符
public void write(String str) :一次写出一个字符串
public void write(String str,int off, int len)
真正使用时,使用的是其子类FileWriter
使用步骤
- 创
构造方法:
//没有拼接
public FileWriter(String fileName)
public FileWriter(File file)
//有拼接,但是append要为true
public FileWriter(String fileName , boolean append)
public FileWriter(File file , boolean append)
- 写:调用write方法
public void write(int c) :写出一个字符
public void write(char[] chars) :一次写出一个字符数组
public void write(char[] chars,int off, int len) :一次写出一个字符数组中指定的字符
public void write(String str) :一次写出一个字符串
public void write(String str,int off, int len)
- 关:调用
close
public void close(): 关流
代码实践
/*
字符输出流的基本使用
*/
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创
//没有拼接
// FileWriter fw = new FileWriter("file04.txt");
//拼接
FileWriter fw = new FileWriter("file04.txt",true);
//2.写
//write(int c)
fw.write('A');
//write(char[] chars)
char[] chars = {'a', '1', '我'};
fw.write(chars);
//write(char[] chars,int off,int len)
fw.write(chars,1,2);
fw.write(System.lineSeparator());//换行
//write(String str)
fw.write("静夜思");
fw.write("\r\n");//换行
//write(String str,int off,int len)
fw.write("静夜思",1,2);
//3.关
fw.close();
}
}
关闭和刷新的区别
关闭和刷新
关闭:关流,把缓冲区的数据刷出【关流+刷新】
public void close()
刷新:把缓冲区的数据刷出到硬盘或者其他存储介质【就是刷新】
public void flush()
/*
关闭和刷新的区别
关闭:close 关闭后不能继续写【刷新+关闭资源】
刷新:flush 刷新后可以继续写【刷新】
*/
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创
FileWriter fw = new FileWriter("file05.txt");
//2.写
fw.write("我爱香港!!");//将字符数据临时保存到缓冲区
fw.flush();//将缓存中的数据写出到文件中
fw.write("一国两制");
fw.flush();
//3.关
fw.close();
//fw.write("我爱祖国");
}
}
字符流和字节流的使用区别
字符流的使用场景:当处理纯文本字符数据时,可以使用字符流
字节流的使用场景:常处理字节数据时的复制拷贝,可以使用字节流: 比如,图片,视频,超文本文件的处理
IO
异常的处理
JDK7
之前的处理方式:
try - catch - finnaly进行处理
关流的动作,需要放到finally中,如果存在多个流需要关闭,可以自定义一个专门用来关流的工具类
/*
try - catch - finnaly进行处理
关流的动作,需要放到finally中,如果存在多个流需要关闭,可以自定义一个专门用来关流的工具类
*/
public class Demo01 {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//完成 img1/美女.jpg 拷贝到 img2/beauty.jpg
//1)创:分别创建字节输入和输出流对象
fis = new FileInputStream("img1/美女.jpg");
fos = new FileOutputStream("X:/img2/beauty.jpg");
//2)读写 : 边读边写
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//3)关 : 关流
//CloseUtil.close(fos, fis);
//CloseUtil.close(fos, fis);
CloseUtil.close(fis,fos);
}
}
}
工具类
/*
关流工具类的优化
*/
public class CloseUtil {
//杜绝其他类创建这个工具类的对象
private CloseUtil(){}
public static void close(AutoCloseable... resource) {
for (AutoCloseable r : resource) {
try {
if (r != null)
r.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
JDK7
处理方式
优点就是可以自动关流,可以使用try-with-resource
【格式】
try (创建流对象语句,如果多个,使用';'隔开) {
// 读写数据
} catch (IOException e) {
e.printStackTrace();
}
【代码实践】
/*
try-whit-resource:自动关流
*/
public class Demo02 {
public static void main(String[] args) {
//1)创:分别创建字节输入和输出流对象
try (FileInputStream fis = new FileInputStream("img1/美女.jpg");
FileOutputStream fos = new FileOutputStream("img2/beauty.jpg")
) {
//2)读写 : 边读边写
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
属性集
属性集使用
Properties: 属性集 ,是HashTable的子类 HashTable又是Map接口的实现类,Properties内部存储的数据,就是键值对。
基本方法使用
特有方法:
- public Object setProperty(String key, String value) : 保存一对属性。 【put】
- public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。【get】
- public Set<String> stringPropertyNames() :所有键的名称的集合。 【keySet】
【代码实践】
public class Demo01 {
public static void main(String[] args) {
Properties pro = new Properties();
//Object setProperty(String key, String value) : 保存一对属性。 【put】
pro.setProperty("username", "root");
pro.setProperty("password", "root");
pro.setProperty("driverClass", "com.mysql.jdbc.Driver");
pro.setProperty("url", "jdbc:mysql:///day01");
System.out.println("pro = " + pro);
//String getProperty(String key) :使用此属性列表中指定的键搜索属性值。【get】
//Object username = pro.get("username");
String username = pro.getProperty("username");
System.out.println("username = " + username);
//Set<String> stringPropertyNames() :所有键的名称的集合。 【keySet】
Set<String> names = pro.stringPropertyNames();
System.out.println("names = " + names);
}
}
和流相关的方法
存储属性集中的键值对信息到配置文件
public void store(Writer write,String comments) :
write 是一个字符输出流需要关联一个文件,comments是注释
public void store(OutputStream out,String comments) :
write 是一个字符输出流需要关联一个文件,comments是注释
//将内存中的Properties属性信息保存到文件中
//void store(Writer write,String comments) :write 是一个字符输出流需要关联一个文件,comments是注释
//void store(OutputStream out,String comments) :write 是一个字符输出流需要关联一个文件,comments是注释
try (FileWriter fileWriter = new FileWriter("mysql.properties");) {
pro.store(fileWriter, "This is comments, 这是注释");
} catch (IOException e) {
e.printStackTrace();
}
如果要加载本地文件的键值对信息到Properties中
public void load(InputStream in):传入的流目的就是关联配置文件
public void load(Reader in):传入的流目的就是关联配置文件
public class Demo02 {
public static void main(String[] args) {
Properties pro = new Properties();
System.out.println("pro = " + pro);
//void load(InputStream in):传入的流目的就是关联配置文件
//void load(Reader in):传入的流目的就是关联配置文件
try (FileReader reader = new FileReader("mysql.properties");) {
pro.load(reader);//加载配置文件中的属性信息到pro对象
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("pro = " + pro);
}
}
tore(fileWriter, "This is comments, 这是注释");
} catch (IOException e) {
e.printStackTrace();
}
如果要加载本地文件的键值对信息到Properties中
public void load(InputStream in):传入的流目的就是关联配置文件
public void load(Reader in):传入的流目的就是关联配置文件
public class Demo02 {
public static void main(String[] args) {
Properties pro = new Properties();
System.out.println("pro = " + pro);
//void load(InputStream in):传入的流目的就是关联配置文件
//void load(Reader in):传入的流目的就是关联配置文件
try (FileReader reader = new FileReader("mysql.properties");) {
pro.load(reader);//加载配置文件中的属性信息到pro对象
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("pro = " + pro);
}
}