小梁同学 の
Java学习旅途
你好! 这是小梁同学使用 博客 所记录的文章笔记,作为一个初学者的从基础到未来的记录,如果你想和我一起在Java学习路程上坚持下去,欢迎你的关注与指正。
以下所有有关代码,都是个人在上完课后自己重新敲代码之后所做笔记后上传,并非原搬直接上传,谢谢理解
三.IO流
1.IO流分类
1.概念
I/O: input(输入) /Output(输出)
流: 抽象概念,数据传输的总称,就是说数据在设备之间的传输称之为流,本质就是传输
常见的数据传输形式: 文件的Copy、上传、下载
2.根据数据流向分类
输入流: 读数据
输出流: 写数据
解释: 站在内存的角度考虑
3.根据数据类型分类
字节流(万能流): 字节输入流 / 字节输出流
字符流 : 字符输入流 / 字符输出流
2.字节流
1.字节流写数据
字节输出流–OutputStream
方法名 | 说明 |
---|---|
FileOutputStream(String name) | 根据参数指定的路径名来构造对象并关联起来。 |
FileOutputStream(String name,boolean append) | 以追加的方式构造对象 |
void write(int b) | 用于将参数指定的单个字节写入输出流 |
void write(byte[] b) | 用于将参数指定的字节数组内容全部写入到输出流中 |
void write(byte[] b,int off,int len) | 用于将数组中的一部分内容写入到输出流中 |
void close() | 关闭输出流并释放资源 |
直接创建的话会显示OutputStream抽象类不能够实例化对象,故选择它的子类FileOutputStream创建字节输出流对象,代码如下:
import java.io.FileOutputStream;
import java.io.IOException;
public class Test1 {
public static void main(String[] args) throws IOException {
//抽象类不能够实例化对象
// OutputStreamtream outputStream = new OutputStream();
// 1.创建字节输出流对象
//(1)覆盖写,每次重新运行程序都会在创建的文本中重新写入数据
FileOutputStream fops = new FileOutputStream("./myBook.txt");
//(2)追加写,通过构造方法中的第二个参数来决定
//true,则在原文本后面加上新写入的
//false,则表示不追加写,与覆盖写异曲同工
FileOutputStream fops = new FileOutputStream("./myBook.txt",true);
//2.数据的传输操作
//(1)正常一个一个写入
fops.write(68);//'D'
fops.write(69);//'E'
//(2)向文件中写入26个英文字母
for (int i = 0; i < 26; i++) {
fops.write(65 + i);
}
//(3)写一个byte数组
byte[] bytes = {97,98,99,100,101,102};
fops.write(bytes);//'abcdef'
//(4)将一个字符串转换未byte类型数组,getBytes()
byte[] bytes = "187288837298你好,小白".getBytes();
//第一个参数为起始点,后一个为截止长度
fops.write(bytes,0,16);
//3.关闭流,释放资源
fops.close();
}
}
2.字节流读数据
字节输入流-- InputStream
方法名 | 说明 |
---|---|
FileInputStream(File file) | 根据参数指定File类对象创建字节输入流对象 |
FileInputStream(String name) | 根据参数指定的路径名来构造对象并关联起来 |
int read() | 用于从输入流中读取单个字节的数据 |
int read(byte[] b) | 用于从输入流中读取数组长度个字节的数据 |
int read(byte[]b,int off, int len) | 用于从输入流读取数组中一部分内容 |
void close() | 关闭输入流并释放资源 |
与字节输出流一样,直接创建的话会显示InputStream抽象类不能够实例化对象,故选择它的子类FileInputStream创建字节输出流对象,代码如下:
import java.io.FileInputStream;
import java.io.IOException;
public class Test2 {
public static void main(String[] args) throws IOException {
//1.创建字节输入流对象
FileInputStream fips = new FileInputStream("./myBook.txt");
//2.操作输入流数据
//(1)一次读一个字节
// int by = fips.read();
// by = fips.read();
// by = fips.read();
// System.out.println(by);//当没有数字时,by会输出-1.
//(2)单个字节循环读取
// int by;
// while ((by = fips.read())!=-1){
// System.out.println((char)by);
// }
//(3)一次读取一个数组
byte[] bytes = new byte[10];//用来读取数据的缓冲区
int len = fips.read(bytes);//返回的是数组中实际数据的长度
System.out.println(new String(bytes));
System.out.println(new String(bytes,0,len));
//(4)通过数组循环的方式读取数据
//将数据读取到byte数组中时,如果有数据则返回实际数据的长度,如果没有数据,则返回-1
while ((len=fips.read(bytes))!=-1) {
System.out.println(new String(bytes));
System.out.println(new String(bytes, 0, len));
}
//3.关闭连接并释放资源
fips.close();
}
}
3.字节流异常处理
- 抛出 或者 捕获
- 通过finally来释放资源close
字节流中异常处理可以通过抛出或捕获的方式进行处理,但不推荐捕获,因为相对于抛出而言,捕获的代码不易规整,以下代码为捕获处理异常,仅供参考:
import java.io.FileOutputStream;
import java.io.IOException;
public class Test1 {
public static void main(String[] args) {
//1、创建字节输出流对象
FileOutputStream fops = null; //覆盖写
try {
fops = new FileOutputStream("./myBook.txt");
// 2、数据的传输操作
byte[] bytes = "1872367882你好小白".getBytes();//将字符串转换成byte类型数组
fops.write(bytes,0,22);
} catch (IOException e) {
e.printStackTrace();
}finally {
// 3、关闭流,释放资源
try {
fops.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.字节流(边读边写)
读一个字节,写一个字节
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class test3 {
public static void main(String[] args) throws IOException {
//创建字节输入流对象
FileInputStream fips = new FileInputStream("./myTest.txt");
//创建字节输出流对象
FileOutputStream fops = new FileOutputStream("./newMyTest.txt");
int by;
while ((by = fips.read())!=-1){//读一个字节同时写一个字节
fops.write(by);
}
//关闭流,释放资源
fips.close();
fops.close();
}
}
5.字节流缓冲区
- BufferedOutputStream
- BufferedInputStream
分别定义四个方法来进行对比看所复制文件的时间:
基本字节流一次读写一个字节
基本字节流一次读写一个数组
缓冲区字节流一次读写一个字节
缓冲区字节流一次读写一个数组
import java.io.*;
public class Test3 {
public static void main(String[] args) throws IOException{
final String VCR = "./video.mp4";
final String TO = "./newVideo.mp4";
long startTime = System.currentTimeMillis();//开始时的毫秒数
method1(VCR,TO);
//method2(VCR,TO);
//method3(VCR,TO);
//method4(VCR,TO);
long endTime = System.currentTimeMillis();//结束时的毫秒数
System.out.println("复制该文件共耗时:"+(endTime - startTime)+"毫秒");
}
//定义method1方法:基本字节流一次读写一个字节,实现文件Copy
private static void method1(String vcr, String to) throws IOException {
//1.创建字节流对象
FileInputStream fips = new FileInputStream(vcr);
FileOutputStream fops = new FileOutputStream(to);
//2.操作字节流数据
int by;
while ((by = fips.read())!=-1){
fops.write(by);
}
//3.关闭连接并释放资源
fips.close();
fops.close();
}
//定义method2方法:基本字节流一次读写一个数组,实现文件Copy
private static void method2(String vcr, String to) throws IOException {
//1.创建字节流对象
FileInputStream fips = new FileInputStream(vcr);
FileOutputStream fops = new FileOutputStream(to);
//2.操作字节流数据
byte[] bytes = new byte[1024];
int len;
while ((len = fips.read(bytes))!=-1){
fops.write(bytes,0,len);
}
//3.关闭连接并释放资源
fips.close();
fops.close();
}
//定义method3方法:缓冲区字节流一次读写一个字节,实现文件Copy
private static void method3(String vcr, String to) throws IOException {
//1.创建字节流对象
BufferedInputStream bips = new BufferedInputStream(new FileInputStream(vcr));
BufferedOutputStream bops = new BufferedOutputStream(new FileOutputStream(to));
//2.操作字节流数据
int by;
while ((by = bips.read())!=-1){
bops.write(by);
}
//3.关闭连接并释放资源
bips.close();
bops.close();
}
//定义method4方法:缓冲区字节流一次读写一个数组,实现文件Copy
private static void method4(String vcr, String to) throws IOException {
//1.创建字节流对象
BufferedInputStream bips = new BufferedInputStream(new FileInputStream(vcr));
BufferedOutputStream bops = new BufferedOutputStream(new FileOutputStream(to));
//2.操作字节流数据
byte[] bytes = new byte[1024];
int len;
while ((len = bips.read(bytes))!=-1){
bops.write(bytes,0,len);
}
//3.关闭连接并释放资源
bips.close();
bops.close();
}
}
3.字符流
1.概述
存储形式: 一个英文、汉字以及标点符号的存储就是其对应的简单字符
字符流 = 字节流 + 编码表
常见的字符编码:
①ASCll
②GBK
③Unicode
④UTF-8/16/32
2.编码与解码
- 编码
- getBytes():使用平台默认的编码格式(字符集)
- getBytes(Stirng chatSetName) : 使用的是指定的编码格式(字符集)
- 解码
- String(byte[] bytes) : 使用平台默认的编码格式解码(字符集)
- String(byte[] bytes,String charSetName) : 使用指定的编码格式解码(字符集)
package com.liang.IO03;
import java.util.Arrays;
import java.io.UnsupportedEncodingException;
public class Test04 {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "Jack梁";
//使用UTF-8字符集进行编码
byte[] byte1 = str.getBytes("UTF-8");
//使用GBK字符集进行编码
byte[] byte2 = str.getBytes("GBK");
//不规定的情况下使用的是平台默认的编码格式
byte[] byte3 = str.getBytes();
System.out.println(Arrays.toString(byte1));
System.out.println(Arrays.toString(byte2));
System.out.println(Arrays.toString(byte3));
//平台默认的编码格式解码
System.out.println(new String(byte3));
//指定的编码格式解码
//因为字符集不同,所以中文出现乱码
System.out.println(new String(byte3,"GBK"));
}
}
===========================
[74, 97, 99, 107, -26, -94, -127]
[74, 97, 99, 107, -63, -70]
[74, 97, 99, 107, -26, -94, -127]
Jack梁
Jack姊�
3.字符流写数据
OutputStreamWriter
package com.liang.IO03;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class Test05 {
public static void main(String[] args) throws IOException {
//将字节输出流对象包装成字符输出流对象
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("./muTest.txt",false));
//写一个字符
osw.write(66);
osw.write('d');
//写一个字符串
osw.write("你好,李焕英!");
osw.write("987654321",4,3);
//写一个字符数组
char[] chars={'a','s','d','f','g'};
osw.write(chars);
osw.write(chars,3,2);
//关闭流
osw.close();
}
}
4.字符流读数据
InputStreamReader
package com.liang.IO03;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test06 {
public static void main(String[] args) throws IOException {
//将字节输入流对象包装成字符输入流对象
InputStreamReader isr = new InputStreamReader(
new FileInputStream("./muTest.txt"));
//一次读取一个字符
// int is;
// while ((is = isr.read()) != -1){
// System.out.println((char)is);
// }
//一次读一个字符数组
char[] chars = new char[1024];
int len;
while ((len =isr.read(chars)) != -1){
System.out.println(chars);
}
//关闭流
isr.close();
}
}
5.字符流的文本拷贝
package com.liang.IO03;
import java.io.*;
public class Test07 {
public static void main(String[] args) throws IOException {
将字节输出、输入流对象包装成字符输出、输入流对象
//字符流构造方法中的第二个参数用来设置字符集(编码格式)
InputStreamReader isr = new InputStreamReader(
new FileInputStream("./muTest.txt"), "GBK");
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("./myTest.txt"),"GBK");
//单个字符形式
int is ;
while ((is = isr.read()) != -1){
osw.write(is);
}
//单个字符数组形式
char[] chars = new char[1024];
int len;
while ((len = isr.read(chars)) != -1){
osw.write(chars,0,len);
}
//关闭流
isr.close();
osw.close();
}
}
6.字符流的简化写法
- FileReader
- FileWriter
package com.liang.IO03;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test08 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("./muTest.txt");
FileWriter fw = new FileWriter("./newMuTest.test");
//一次读写一个字符
int is;
while ((is = fr.read()) != -1){
fw.write(is);
}
//一次读写一个字符数组
char[] chars = new char[1024];
int len;
while ((len = fr.read(chars)) != -1){
fw.write(chars,0,len);
}
fr.close();
fw.close();
}
}
7.字符流缓冲区
1.高效读写
- BufferedReader
- BufferedWriter
public class Test09 {
public static void main(String[] args) throws IOException {
//创建缓冲区字符流对象
// BufferedReader br = new BufferedReader(
// new InputStreamReader(new FileInputStream("./muTest.txt")));
// BufferedWriter bw = new BufferedWriter(
// new OutputStreamWriter(new FileOutputStream("./myNewTest.txt")));
//简写创建缓冲区字符流对象
BufferedReader br = new BufferedReader(
new FileReader("./muTest.txt"));
BufferedWriter bw = new BufferedWriter(
new FileWriter("./myNewTest.txt"));
//实现文本文件复制
char[] chars = new char[1024];
int len;
while ((len = br.read(chars)) != -1){
bw.write(chars,0,len);
}
//关闭流
br.close();
bw.close();
}
}
2.特有方法
数据流向 | 方法 | 含义 |
---|---|---|
BufferedWriter | void newLine() | 插入新的换行符 |
BufferedWriter | void flush() | 刷新输出流 |
BufferedReader | String readLine() | 读取一行,读到没有则返回null |
public class Test10 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("./muTest.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("./muNewTest.txt"));
//将读出来的一行字符串存入到line中
String line;
//判断行是否为空
while ((line = br.readLine()) != null){
//写一行
bw.write(line);
//换一行,插入一个换行符
bw.newLine();
//手动刷新
bw.flush();
}
br.close();
bw.close();
}
}
4.标准流
1.System.in标准输入流
获取标准设备输入的流
public class Test11 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new FileWriter("./myNewTest.txt"));
//向程序中输入内容,直到over出现程序终止
String str;
System.out.println("请输入一行字符串:");
while (true){
//判断输入的内容是不是over
if ((str = br.readLine()).equals("over")){
//出现over 则结束后跳出循环
System.out.println("聊天结束!");
break;
}
//程序没有结束时写入一行
bw.write(str);
//进行换行继续写入
bw.newLine();
//实时刷新
bw.flush();
}
br.close();
bw.close();
}
}
=========================
请输入一行字符串:
sdfbgb265
5451516
edrg516656415
454
rgrfgwef
over
聊天结束!
2.System.out标准输出流
将数据显示到标准输出设备中
public class Test12 {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(System.out));
bw.write("标准输出流");
System.out.println("正常打印");
bw.close();
}
}
3.System.err 标准错误流
public class Test13 {
public static void main(String[] args) throws IOException {
System.out.println("正常输出");
//标准错误流:显示颜色红色,不建议与自己封装的错误流同时使用
//System.err.println("我是标准错误流");
//自己封装的错误流
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(System.err));
bw.write("自定义封装的错误流");
bw.close();
}
}
5.对象的持久化存储
1.单个学生对象存储到文件
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo01 {
public static void main(String[] args) throws IOException {
Student stu = new Student("Jack", 18);
// mySave(stu);
Student resStu = myLoad();
System.out.println(resStu);
}
private static Student myLoad() throws IOException {
//读文件
BufferedReader br = new BufferedReader(new FileReader("./myTest.txt"));
String str = br.readLine();
String[] split = str.split("##");
Student stu = new Student(split[0], Integer.parseInt(split[1]));
br.close();
return stu;
}
private static void mySave(Student stu) throws IOException {
//将其写到文件中
BufferedWriter bw = new BufferedWriter(new FileWriter("./myTest.txt"));
bw.write(stu.getName() + "##" + stu.getAge());
bw.close();
}
}
2.多个学生对象存储到文件
public class Demo02 {
public static void main(String[] args) throws IOException {
Student[] students = new Student[8];
students[0] = new Student("张三", 28);
students[1] = new Student("李四", 26);
students[2] = new Student("王五", 22);
students[3] = new Student("赵六", 27);
students[4] = new Student("贾七", 24);
students[5] = new Student("魏八", 25);
students[6] = new Student("孙九", 29);
students[7] = new Student("老大", 30);
//将多个对象存储到文件中
//saveStu(students);
//读取文件内容
Student[] stud = loadStu();
for (Student stu :stud) {
System.out.println(stu);
}
}
private static Student[] loadStu() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("./myTest.txt"));
//获取每一条学生信息
String[] stuArr = br.readLine().split("@@");
//存储从文件中取出来的学生信息对象
Student[] students = new Student[8];
for (int i = 0;i<students.length;i++){
String[] stus = stuArr[i].split("##");
students[i] = new Student(stus[0],Integer.parseInt(stus[1]));
}
br.close();
return students;
}
private static void saveStu(Student[] students) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("./myTest.txt"));
//遍历数组拿到对象
for (Student stu:students) {
bw.write(stu.getName() + "##" + stu.getAge() + "@@");
}
bw.close();
}
}
3.对象的串行化(序列化)操作
- ObjectOutputStream
- ObjectInputStream
public class Student implements Serializable {
private String name;
private int age;
private static final long serialVersionUID = -5281125824123725016L;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void show(){
System.out.println("zhanshi ");
}
}
public class Demo03 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//序列化存单个对象
// Student stu = new Student("Jack", 50);
// ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myTest.txt"));
// oos.writeObject(stu);
// oos.close();
//序列化取单个对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myTest.txt"));
Student student = (Student) ois.readObject();
System.out.println(student);
ois.close();
}
}
注:
1.实体类序列化(串行化)后,不可以改变类中方法,否则报错
解决方式:找到序列化编号,在实体中定义常量
private static final long serialVersionUID = -5281125824123725016L;
2.屏蔽序列化:transient
java进阶基础—2.2----上一章节: File类
java进阶基础—课后习题: 跳转