1.IO流是什么
① 可以将数据从本地文件中读取出来
② 可以将数据从内存保存到本地文件
2.IO流分类
① 按照流向分:输入流、输出流
② 按照数据类型分:字节流、字符流
字节流:操作所有类型的文件(包括音频、视频、图片等)
字符流:只能操作纯文本文件(包括java文件、txt文件等)
一般来说,我们说IO流的分类是按照数据类型来分的
什么是纯文本文件:用windows记事本打开能读的懂,那么这样的文件就是纯文本文件
1.字节流写数据的步骤:
① 创建字节输出流对象
② 写数据
③ 释放资源
2.字节流写数据的三种方式
字节流写数据如何实现换行
写完数据后加换行符号:
windowns:\r\n
linux:\n
mac:\r
public class OutputDemo3 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("F:\\a.txt");
fos.write(97);
fos.write("\r\n".getBytes());
fos.write(98);
fos.write("\r\n".getBytes());
fos.write(99);
fos.write("\r\n".getBytes());
fos.write(100);
fos.write("\r\n".getBytes());
fos.write(101);
fos.write("\r\n".getBytes());
fos.write(102);
fos.close();
}
}
3.字节流写数据如何实现追加写入
public FileOutputStream(String,booleanappend)
创建文件输出流以指定的名称写入文件,如果第二个参数为true,不会清空文件里面的内容
//第二个参数就是续写开关,如果没有传递,默认就是false,
//表示不打开续写功能,那么创建对象的这行代码会清空文件
//如果第二个参数为true,表示打开续写功能
//那么创建对象的这行代码不会清空
FileOutputStream fos = new FileOutputStream("F:\\a.txt",true);
4.字节流写数据加try…catch异常处理
上述代码存在问题,当写数据出现问题,不能释放资源。
finally:在异常处理时提供finally块来执行所有清除操作。比如说IO流中的释放资源。
finally特点:被finally控制的语句一定会执行,除非JVM退出
异常处理标准格式:try…catch…finally
public class OutputDemo6 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
// System.out.println(2/0);
fos = new FileOutputStream("F:\\a.txt");
fos.write(97);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
① 创建字节输入流对象
② 读数据
③ 释放资源
int b;
while ((b = fis.read())!= -1){
System.out.println((char) b);
}
public class OutputDemo8 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("filemodule\\a.txt");
int b;
while ((b = fis.read())!= -1){
System.out.println((char) b);
}
fis.close();
}
}
复制文件
public class OutputDemo9 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("F:itheima\\a.avi");
FileOutputStream fos = new FileOutputStream("filemodule\\a.avi");
int b;
while ((b = fis.read())!= -1){
fos.write(b);
}
fis.close();
fos.close();
}
}
为了解决速度问题,字节流通过创建字节数组,可以一次读写多个数据
一次读一个字节的方法:
public int read(byte[b]):从输入流读取最多b.lenth个字节的数据
返回的是读入缓冲区的总字节数,也就是实际的读取字节个数
byte[] bytes = new byte[2];
int len;//本次读到的有效的字节个数 ---这次读了几个字节
while (( len = fis.read())!= -1){
fos.write(bytes,0,len);
}
public class OutputDemo10 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("F:itheima\\a.avi");
FileOutputStream fos = new FileOutputStream("filemodule\\a.avi");
byte[] bytes = new byte[1024];
int len;//本次读到的有效的字节个数 ---这次读了几个字节
while (( len = fis.read())!= -1){
fos.write(bytes,0,len);
}
fis.close();
fos.close();
}
}
1.字节缓冲流:
BufferOutputStream:字节缓冲输出流
BufferInputStream:字节缓冲输入流
2.构造方法:
字节缓冲输出流:BufferOutputStream(OutputStream out)
字节缓冲输入流:BufferInputStream(InputStream in)
为什么构造方法需要的是字节流,而不是具体的文件或路径呢?
public class OutputDemo11 {
public static void main(String[] args) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("filemodule\\a.avi"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("filemodule\\copy.avi"));
int b;//本次读到的有效的字节个数 ---这次读了几个字节
while ((b = bis.read()) != -1) {
bos.write(b);
}
bis.close();
bos.close();
}
}
public class OutputDemo12 {
public static void main(String[] args) throws IOException {
//创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("filemodule\\a.avi"));
//创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("filemodule\\b.avi"));
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bis.close();
bos.close();
}
}
3.字节缓冲流作用
字节缓冲流可以提高效率
不能直接操作文件,需要传递字节流
4.拷贝文件的四种方式
字节流一次读写一个字节
字节流一次读写一个字节数组
字节缓冲流一次操作一个字节
字节缓冲流一次操作一个字节数组
1.基础知识
计算机中的存储的信息都是用二进制数表示的
按照某种规则,将字符变成二进制,再存储到计算机中,称为编码
按照同样的规则,将存储在计算机中的二进制数解析出来,称为解码
编码和解码的方式必须一致,否则会导致乱码
简单理解:
存储一个字符a,首先需要在码表中查到对应的数字是97,然后转换成
二进制进行存储,读取的时候,先把二进制解析出来,再转成97,通过97查找到对应的字符是a
重点:
windows默认使用码表为:GBK,一个字符两个字节,idea和以后工作默认使用Unicode的UTF-8的解码格式,一个中文三个字节
2.字符串中的编解码问题
编码:
byte[] getBytes():使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中
byte[] getBytes(String charsetName):使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中
解码:
String(byte[] bytes):通过使用平台的默认字符集解码指定的字节数组来构造新的String
string(byte[]bytes,String charsetName):通过指定的字符集解码指定的字节数组来构造新的String
public class CharStreamDemo2 {
public static void main(String[] args) throws UnsupportedEncodingException {
method1();
method2();
}
public static void method2() throws UnsupportedEncodingException {
byte[] bytes1 = {-27, -80, -113, -25, -103, -67, -27, -83, -90, -25, -68, -106, -25, -88, -117};
byte[] bytes2 = {-48, -95, -80, -41, -47, -89, -79, -32, -77, -52};
String s1 = new String(bytes1);
System.out.println(s1);
String s2 = new String(bytes2, "gbk");
System.out.printf(s2);
}
public static void method1() throws UnsupportedEncodingException {
String s = "小白学编程";
//利用idea默认的UTF-8将中文编码为一系列字节
byte[] bytes1 = s.getBytes();
System.out.println(Arrays.toString(bytes1));
byte[] bytes2 = s.getBytes("GBK");
System.out.println(Arrays.toString(bytes2));
}
}
3.字符流写数据的步骤
① 创建字符输出流对象
② 写数据
写出int类型的整数,实际写出的是整数在码表上的对应的字母
写出字符串数据,是把字符串本身原样写出
③ 释放资源
4.写数据的5种格式
public class CharStreamDemo3 {
public static void main(String[] args) throws IOException {
//创建字符输出流对象
FileWriter fw1 = new FileWriter("filemodule\\a.txt");
//void write(int c) 写一个字符
/* fw1.write(97);
fw1.write(98);
fw1.write(99);*/
//void write(char[] cbuf) 写出一个字符数组
/*char[] chars = {97,98,99,100,101};
fw1.write(chars);*/
//void write(char[] cbuf,int off,int len) 一次写出字符数组的一部分
/*char[] chars = {97,98,99,100,101};
fw1.write(chars,0,3);*/
//void write(String str) 写一个字符串
/*String line = "小白学编程abc";
fw1.write(line);*/
//void write(String str) 写一个字符串的一部分
String line = "小白学编程abc";
fw1.write(line,0,2);
// 释放资源
fw1.close();
}
}
5.flush和close方法
public class CharStreamDemo4 {
public static void main(String[] args) throws IOException {
FileWriter fw1 = new FileWriter("filemodule\\a.txt");
fw1.write("小白学编程");
fw1.flush();
fw1.write("666");
fw1.flush();
fw1.close();
fw1.write("666");//Exception in thread "main" java.io.IOException: Stream closed
}
}
6.读取数据
一次读取一个字符
public class CharStreamDemo6 {
public static void main(String[] args) throws IOException {
FileReader fr1 = new FileReader("filemodule\\a.txt");
//一次读取一个字符
int c ;
while ((c=fr1.read())!=-1){
System.out.println((char) c);
}
fr1.close();
}
}
一次读取一个字符数组
public class CharStreamDemo7 {
public static void main(String[] args) throws IOException {
FileReader fr1 = new FileReader("filemodule\\a.txt");
char[] chars = new char[1024];
int len;
//一次读取一个字符数组
//把读到的字符都存入到chars数组
//返回值:表示本次读到了多少个字符
while ((len=fr1.read(chars))!=-1){
System.out.println(new String(chars,0,len));
}
fr1.close();
}
}
7.保存键盘录入的数据
需求:将用户键盘录入的用户名和密码保存到本地实现永久化存储,要求用户名独占一行,密码独占一行
步骤:
用户键盘录入用户名和密码
将用户名和密码写到本地文件中
public class CharStreamDemo8 {
public static void main(String[] args) throws IOException {
//键盘录入用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String username = sc.next();
System.out.println("请录入密码");
String password = sc.next();
FileWriter fw1 = new FileWriter("filemodule\\a.txt");
fw1.write(username);
fw1.write("\r\n");
fw1.write(password);
fw1.flush();
fw1.close();
}
}
1.字符缓冲流
BufferWriter:可以将数据高效的写出
BufferReder:可以将数据高效的读取到内存
2.构造方法:
BufferedWriter(Writer out)
BufferedReader(Reader in)
3.字符缓冲流特有功能
BufferedWriter:
BufferedReder:
public class CharStreamDemo13 {
public static void main(String[] args) throws IOException {
//创建对象
BufferedReader br = new BufferedReader(new FileReader("filemodule\\a.txt"));
//使用循环改进
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
}
4.读取文件中的数据排序后再次写到本地文件
需求:读取文件中的数据排序后再次写到本地文件
步骤:
① 读取数据
② 将数据排序
③ 写回本地
public class CharStreamDemo15 {
public static void main(String[] args) throws IOException {
//把文件中的数据读取出来,排序后再再次写到本地文件
BufferedReader fr = new BufferedReader(new FileReader("filemodule\\sort.txt"));
String line = fr.readLine();
System.out.println(line);
String[] split = line.split(" ");
int arr[] = new int[split.length];
for (int i = 0; i < split.length; i++) {
String str = split[i];
int number = Integer.parseInt(str);
arr[i] = number;
}
//2.排序
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
//3.把排序之后的结果写回到本地1,2,3,4....
BufferedWriter bw = new BufferedWriter(new FileWriter("filemodule\\sort.txt"));
for (int i = 0; i < arr.length; i++) {
bw.write(arr[i]+" ");
bw.flush();
}
bw.close();
}
}
InputStreamReader是从字节流到字符流的桥梁
OutputStreamWriter是从字符流到字节流的桥梁
public class ConvertStreamDemo1 {
public static void main(String[] args) throws IOException {
//method1();
//method2();
//jdk11之后,指定码表
FileReader fr = new FileReader("C:\\Users\\86150\\Desktop\\a.txt", Charset.forName("GBK"));
int ch;
while ((ch = fr.read()) != -1) {
System.out.println((char) ch);
}
fr.close();
}
public static void method2() throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\Users\\86150\\Desktop\\a.txt"), "gbk");
int ch;
while ((ch = isr.read()) != -1) {
System.out.println((char) ch);
}
isr.close();
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C:\\Users\\86150\\Desktop\\b.txt"), "UTF-8");
osw.write("小白学java666");
osw.close();
}
public static void method1() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\86150\\Desktop\\a.txt"));
int ch;
while ((ch = br.read()) != -1) {
System.out.println((char) ch);
}
br.close();
}
}
1.特点:
可以把对象以字节的形式写到本地文件中,直接打开文件,是都不懂的,需要再次用对象操作流读到内存中
2.对象操作流分为两类:
对象操作输入流(对象序列化流):就是将对象写到本地文件中,或者在网络中传输对象
对象操作输出流(对象反序列化流):把写到本地文件中的对象读到内存中,或者接收网络中传输的对象
public class ConvertStreamDemo3 {
public static void main(String[] args) throws IOException {
User user = new User("zhangsan", "pwer");
ObjectOutputStream bw = new ObjectOutputStream(new FileOutputStream("filemodule\\a.txt"));
bw.writeObject(user);
bw.close();
}
}
3.思考:
用对象序列化流序列化了一个对象后,加入我们修改了对象所属的JavaBean类,读取数据会不会出问题呢?
如果出问题了,如何解决?
如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
public class User implements Serializable {
//serialVersionUID 序列号
//如果我们自己的类中没有定义,那么虚拟机会根据类中的信息自动的计算出一个序列号
//问题:如果我们修改了类中的信息,那么虚拟机会再次计算出一个序列号
//第一步;把User对象序列化到本地, ---- -525007202342107847
//第一步;修改了javaBean类,导致------类中的序列号 8783942662371640610
//第三步:把文件中的序列号读到内存,本地中的序列号和类中的序列号不一致
//解决?
//不让虚拟机帮我们自动计算,我们自己手动给出,而且这个值不要变
private static final long serialVersionUID = 1L;
private String userName;
public String password;
public User() {
}
public User(String userName, String password) {
this.userName = userName;
this.password = password;
}
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() {
return "User{" +
"userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}
}
4.用对象操作流读写多个对象
需求:创建多个Javabean类对象写到文件中,再次读到内存中
思路:
① 创建学生对象
② 利用对象操作输出流写到本地
③ 利用对象操作输入流读到内存
public class ConvertStreamDemo6 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student student1 = new Student("张三", 16);
Student student2 = new Student("李四", 13);
Student student3 = new Student("王五", 18);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("filemodule\\a.txt"));
List<Student> students = new ArrayList<>();
students.add(student1);
students.add(student2);
students.add(student3);
oos.writeObject(students);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("filemodule\\a.txt"));
List<Student> list2 = (List<Student>) ois.readObject();
for (Student student : list2) {
System.out.printf(String.valueOf(student));
}
ois.close();
}
}
1.properties概述
① 是一个Map体系的集合类
② Properties有跟IO相关的方法
③ 键值对的数据类型基本都定义为字符串
2.properties作为Map集合的使用
public class PropertiesDemo {
public static void main(String[] args) {
Properties pro = new Properties();
//增
pro.put("小龙女", "尹志平");
pro.put("郭襄", "杨过");
pro.put("黄蓉", "欧阳克");
System.out.println(pro);
//删
pro.remove("郭襄");
System.out.println(pro);
//改
//put --如果键不存在就增加,如果键存在,那么就覆盖
pro.put("小龙女", "杨过");
System.out.println(pro);
//查
Object value1 = pro.get("黄蓉");
System.out.println(value1);
System.out.println("=========================");
//遍历1
Set<Object> keys = pro.keySet();
for (Object key : keys) {
Object o = pro.get(key);
System.out.println(key + "=" + o);
}
//遍历2
Set<Map.Entry<Object, Object>> entries = pro.entrySet();
for (Map.Entry<Object, Object> entry : entries) {
Object key = entry.getKey();
Object value = entry.getValue();
System.out.println(key + "=" + value);
}
}
}
3.properties作为集合的特有的方法
public class PropertiesDemo1 {
public static void main(String[] args) {
Properties properties = new Properties();
properties.setProperty("张三","18");
properties.setProperty("李四","23");
properties.setProperty("王五","12");
System.out.println(properties);
Object value = properties.get("张三");
System.out.println(value);
Set<String> keys = properties.stringPropertyNames();
for (String key : keys) {
String property = properties.getProperty(key);
System.out.println(key+"="+value);
}
}
}
4.Properties和IO结合的方法
void load(Reader reader)
public class PropertiesDemo2 {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
FileReader fr = new FileReader("filemodule\\pro.properties");
properties.load(fr);
fr.close();
System.out.println(properties);
}
}
void store(Writer writer, String comments)
public class PropertiesDemo3 {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
properties.put("zhansan","23");
properties.put("lisi","24");
properties.put("wangwu","33");
FileWriter fw = new FileWriter("filemodule\\pro.properties");
properties.store(fw,null);
fw.close();
}
}