一。字节流
1.读写字节数组
public void copy1() throws IOException {
InputStream in=new FileInputStream("a.txt");
OutputStream ot=new FileOutputStream("a.txt");
OutputStream ot1=new FileOutputStream("d.txt");
//创建字符串写入
String str="你好,世界";
byte[] bs=str.getBytes();//将字符串编码为字节数组
System.out.println("写入的字符长度:"+bs.length);
int len;
ot.write(bs,0,bs.length);//写入全部
ot.write(bs,3,3);//写入index2开始,2字节长度。写入‘好’
//读取
byte[] b=new byte[4];//定义单次读取字节的长度为4
// while ((len=in.read(b))!=-1){//in.read(b)返回的是in从ot读来的长度
// //System.out.println(new String(b));
// /*这样打印读取若bs.length和b.length不是倍数关系,最后一次读取会出现问题
// 因为byte[] b每次传入相当于都被重写,最后一次重写两个数组长度不一样,不能实现全部的字节覆盖
// */
// System.out.println("len"+len);
// System.out.println(Arrays.toString(b));
// ot1.write(b);//写入结果:你好,世界好��。最后一次没完全覆盖b,所以有乱码
// }
System.out.println("______________________-");
//读取2
while ((len=in.read(b))!=-1){
System.out.println("len"+len);
//System.out.println(new String(b,0,len));
System.out.println(Arrays.toString(b));
ot1.write(b,0,len);//写入结果:你好,世界好
}
}
2.包装 -> 高级流: BufferedInputStream/BufferedOutputStream
Buffered: 缓冲/缓存
①缓冲流读取大文件
public class copy2 {
@Test
public void copy() throws IOException {
//缓冲流读写大文件快
// 缓冲流是用字节流来包装的
BufferedInputStream buin = new BufferedInputStream(new FileInputStream("dx.png"));
BufferedOutputStream buot = new BufferedOutputStream(new FileOutputStream("dx_副本.png"));
byte[] a = new byte[1024];
int len;
while ((len = buin.read(a)) != -1) {
buot.write(a, 0, len);
}
//手动刷新缓冲区(当度的文件太小,导致缓冲区不能填满时会造成写入的不显示问题,要手动将缓冲区剩余内容写入)
//buot.flush();
buin.close();//关闭流的时候也会自动刷新缓冲区内容
buot.close();
}
②用异或加密
@Test
public void copy1() throws IOException {
/*异或:相同为0,不同为1
0001 1101
^0011 1011
等于:0010 0110
^0011 1011
等于:0001 1101
*/
//文件赋值过程加密和解密
BufferedInputStream buin = new BufferedInputStream(new FileInputStream("a.txt"));
BufferedOutputStream buot = new BufferedOutputStream(new FileOutputStream("d.txt"));
BufferedInputStream buin1 = new BufferedInputStream(new FileInputStream("d.txt"));
BufferedOutputStream buot1 = new BufferedOutputStream(new FileOutputStream("c.txt"));
int i;
while ((i = buin.read()) != -1) {
//加密
buot.write(i ^ 1);
}
buin.close();//关闭流的时候也会自动刷新缓冲区内容
buot.close();
int c;
while ((c = buin1.read()) != -1) {
//解密
buot1.write(c ^ 1);
}
buin1.close();
buot1.close();
}
③ try catch抓取
需要将关闭流放在finally里
方式一
@Test
public void trycatch() {
BufferedInputStream buin = null;
BufferedOutputStream buot = null;
try {
buin=new BufferedInputStream(new FileInputStream("a.txt"));
buot=new BufferedOutputStream(new FileOutputStream("d.txt"));
int i;
while ((i = buin.read()) != -1){
buot.write(i);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {//在finall中关闭流
if(buin!=null){
try {
buin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(buot!=null){
try {
buot.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
--------------------------------------------------------
方式二
@Test
public void tryCatchTest() {
// try(resource) {} 不管有没有异常, resource都会自动关闭, 不需要finally
try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a_bak.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("a_bak_back.txt"))) {
int a ;
while ((a = bis.read()) != -1) {
bos.write(a ^ 1);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
二。字符流
1.字符流
Reader/Writer
InputStreamReader(InputStream in, String charsetName) - 指定字符集
InputStreamReader(InputStream in) - 默认字符集
int read() 读一个字符
int read(char[] cbuf) 将字符读入数组。
int read(char[] cbuf, int off, int len) 将字符读入数组的一部分。- 了解
注: 以上三个方法, 返回 -1 都标记着读到文件末尾
OutputStreamWriter(OutputStream out, String charsetName)
OutputStreamWriter(OutputStream out)
void write(char[] cbuf) 写入一个字符数组。
void write(char[] cbuf, int off, int len) 写入字符数组的一部分。
void write(int c) 写入单个字符
@Test
public void zifu1() throws IOException {
Writer w=new OutputStreamWriter(new FileOutputStream("a.txt"));
Reader r=new InputStreamReader(new FileInputStream("a.txt"));
Writer w1=new OutputStreamWriter(new FileOutputStream("d.txt"));
//写字符
w.write('c');
w.write(97);
w.write("dcc");
w.write("你好");
w.write('\n');
char[] ch={'h','i','o','k','尼'};
w.write(ch,1,4);
w.write('\n');
String str="我是好人";
w.write(str,1,3);
w.close();
//读字符
char[] m=new char[20];
int len;
//①
while ((len=r.read(m))!=-1){
w1.write(m);//字符写,m最后一次重写有多余的没事,因为空白字符写进去也是空白字符
System.out.println(Arrays.toString(m));
}
//②
while ((len=r.read(m))!=-1){
w1.write(m,0,len);
System.out.println(Arrays.toString(m));
}
//③
int i;
while ((i=r.read())!=-1){
w1.write(i);
System.out.println(i);
}
w1.write("\n换行");
w1.close();
}
@Test
public void zifu2() throws IOException {
Writer w=new OutputStreamWriter(new FileOutputStream("a.txt"));
Reader r=new InputStreamReader(new FileInputStream("a.txt"));
Writer w1=new OutputStreamWriter(new FileOutputStream("d.txt"));
//文件复制
w.write("火云邪神差点杀了我QAQ");
w.close();
int i;
while((i=r.read())!=-1){
w1.write(i);
}
w1.close();
}
2.包装字符流 -> 缓冲字符流
通常用来读写文件内容
BufferedReader(Reader)
String readLine(): 读取一整行, 返回null 标记读到文件末尾
PrintWriter
1.只能清空原文件内容, 但是可以指定字符集
PrintWriter(String fileName, String csn)
2.可以在原文件上追加内容, 但是不可以指定字符集, 可以自动刷新缓冲区
PrintWriter(OutputStream out, boolean autoFlush)
3.可以在原文件上追加内容, 可以指定字符集, 可以自动刷新缓冲区
PrintWriter(Writer out, boolean autoFlush)
void print(Object): 写出内容, 不加换行
void println(): 写出内容, 并且换行
注意: 自动刷新的功能, 只有println方法具有
print方法 必须手动刷新
@Test
public void buff() throws IOException {
//字符缓冲流读
BufferedReader red = new BufferedReader(
new InputStreamReader(
new FileInputStream("a.txt")));
String str;
while ((str = red.readLine()) != null) {//读一整行。
System.out.println(str);
}
red.close();
}
@Test
public void print() throws FileNotFoundException {
//字符缓冲流写打印
PrintWriter pt = new PrintWriter(
new OutputStreamWriter(//字节流后true可接着写;字符流true,自动缓冲flash;
new FileOutputStream("d.txt",true)),true);
pt.print("我是太阳");
pt.print("喜喜");
pt.print("\n");
pt.write("ddd");
pt.println("fffff");//只有以pt.println结尾才会触发自动缓冲flash的true。否则需要手动flash
}
@Test
public void copy() throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("d.txt")));
PrintWriter pw=new PrintWriter(new OutputStreamWriter(new FileOutputStream("d.txt",true)),true);
PrintWriter pw1=new PrintWriter(new OutputStreamWriter(new FileOutputStream("a.txt",true)),true);
pw.write("一闪一闪亮晶晶");
pw.print("满天都是小行星");
pw.println("看星星");
pw.println("跑商跑商跑商跑商跑商视频");
String i;
while ((i=br.readLine())!=null){
pw1.println(i);
}
}
三。对象输入输出流:
对象 -> 文件[字节] : 序列化
文件[字节] -> 对象 : 反序列化
ObjectInputStream(InputStream)
Object readObject()
ObjectOutputStream(OutputStream)
void writeObject(Object)
Serializable: 可序列化的
接口中没有常量, 也没有抽象方法, 空接口
序列化接口没有方法或字段,仅用于标识可串行化的语义。
serialVersionUID: 给类添加固定的序列版本号
transient: 修饰的变量, 在序列化的时候, 会被忽略掉
public class Studeng implements Serializable {//Serializable接口,有序化的
//类会自己生成一个版号,但内容改变也会改变
//所以手动生成一个序列版号
public static final long serialVersionUID =1234l;
int age;
String name;
transient char sex;//transient 修饰的在序列化时他的只会被忽视.
public Studeng(String name, char sex, int age){
this.name=name;
this.age=age;
this.sex=sex;
}
@Override
public String toString() {
return
age +
"," + name +
"," + sex ;
}
//get/set
...
}
------------------------------------------
@Test
public void stu() throws IOException, ClassNotFoundException {
//创建序列化流
ObjectOutput ot=new ObjectOutputStream(new FileOutputStream("a.txt"));
//创建反序列化流
ObjectInput in=new ObjectInputStream(new FileInputStream("a.txt"));
//写出对象
Studeng m=new Studeng("王贵",'男',13);
ot.writeObject(m);
ot.close();
//读取对象
Studeng x=(Studeng) in.readObject();
System.out.println(x);
}
四。JavaBean规范:
1.所有成员变量私有化, 并且提供get/set方法
2.必须要有空参构造方法
3.基本数据类型建议使用包装类
4.实现 Serializable 接口
5.重写 equals, hashCode, toString 方法