Java学习日记-IO流

IO流:

储存和读取数据的解决方案

commons-io包可以提高io流的书写效率

(纯文本文件:用txt打开能看的)

io流要用再创建,不用就关闭

字节流:

读取中文会有乱码

FileOutputStream:

操作本地文件的字节输出流,可以把程序中的数据写到本地文件中。

OutputStream的子类。

书写步骤:1.创建字节流对象 2.写数据 3.释放资源

FileOutputStream fos=new FileOutputStream("字符串路径或者File都行");//要抛出异常
fos.write("内容");
fos.close();

如果文件不存在会创建一个新的文件,但是要保证父级路径存在;如果文件存在的话,会先清空文件。

存入数据的时候是Ascall码,也就是说(100)写入的是d,如果要写数字要‘1’+‘0’+‘0’;

每次用完流之后要释放

FileOutputStream fos=new FileOutputStream("字符串路径或者File都行");
byte[] bytes={51,41564,156,15,4};
//byte的存入
String s="46564";
byte[] bytes1=s.getBytes();
fos.write(bytes1);//全部写入
//off起始索引,len个数
fos.write(bytes1,0,3)//51 41564 156

//换行
//写入换行符 windows:\r\n  linux:\n Mac:\r (java中写\r\n其中一个也行,会补全的
String str="\r\n“;
byte[] bytes2=str.getBytes();
fos.write(bytes2);
fos.write(bytes3);

//续写 创建对象的时候第二个参数传入true就行了,不写默认false
FileOutputStream fos=new FileOutputStream("字符串路径或者File都行",true);

FileInputStream:

IutputStream的子类。

书写步骤:1.创建字节输入流对象 2.写数据 3.释放资源

FileInputStream fis=new FileInputStream("路径或者File");
int b=fis.read();//读不到的时候返回-1
fis.close();

如果文件不存在,直接报错;

一次读一个字节,读出来的是数据在ASCI上对应的数字;

while((b=fis.read())!=-1){}//循环读入

文件拷贝:

int b;
while((b=fis.read())!=-1){ fos.read(b); };
fos.close();fis.close();

一次读写一个字节,太慢

FileInputStream fis=new FileInputStream("路径或者File");
byte[] bytes=new byte[2];
fis.read(bytes);//返回值是读到的个数,没有就是-1,相应的bytes数组也不会发生改变

改写文件拷贝:

int len;
byte[] bytes=new byte[1024*1024*5];
while( (len=fis.read(bytes))!=-1){
    fos.write(bytes,0,len);//防止最后一次读不满一个数组存入其他的数据了
}
close;

异常捕获:

ps:要对对象给初始值,同时要判断文件是否为空

改进:实现AutoCloseable接口的类

字符集:

GBK:

windows系统默认使用的就是GBK。系统显示:ANSI。兼容ASCALL码

对于英文还是一个字节存储,不足8位补0;汉字是2个字节存储,高位字节二进制一定以1开头,转成十进制之后是一个负数

Unicode字符集:

国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换。万国码

UTF-16编码规则:用2~4个字节保存

UTF-32编码规则:固定使用四个字节保存

UTF-8编码规则:用1~4个字节保存;不同语言不一样,英文一个字节,中文3个(IDEA默认)

先确定位数,然后按格式填补

乱码出现的原因:

读取数据的时候未读取完整汉字(3个字节)

编码和解码的方式不统一

如何不产生乱码?1,不要用字节流读取文本文件2,编码解码时使用同一个码表,同一个编码方式

编码&解码:

String str="...";
byte[] bytes1=str.getBytes();//参数可以指定编码方式
byte[] bytes2=str.getBytes("GBK");
//解码
String str=new String(bytes1);
String str=new String(bytes2,"GBK");//要是不匹配会是乱码

字符流:

底层还是字节流

输入流:一次读一个字节,遇到中文时,一次读多个字节

输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中

适合纯文本文件

FileReader:

  1. 创建对象

  1. 读取数据

read读完的二进制数据还会解码保存成十进制,返回这个十进制

  1. 释放资源

close

FileReader fr=new FileReader("..");
int ch;
while( (ch=fr.read())!=-1){ //直接输出是十进制
 (char)ch.sout;
 };
f1.close();

带参read:

FileReader fr=new FileReader("..");
char[] chars=new char[2];
int len;
while( (len=fr.read(chars))!=-1){ //把读取数据,解码,强转三步合并了,把强转之后的字符放到数组当中
     sout(new String(chars,0,len));
 };
f1.close();

FileWirter:

字符流底层:

fwriter会清空文件,如果read之后创建fwriter,文件中的读不到,但是还可以读到缓冲区中的文件

字节流是没有缓冲区的

字符流输出的时候也会创建一个类似的缓冲区写入数据:

什么时候保存到本地? 1.缓冲区装满了 2.close 3.flush() 刷新,区别是flush刷新后还可以写入数据,但是close不可以

缓冲流:

字节缓冲流:

原理:底层自带了长度为8192的缓冲区提高性能

BufferedInputStream bis=new BufferedInputStream(new FileInputStream(""));
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(""));
int b=bis.read();//一次读一个
//读多个
byte[] bytes=new byte[1024];
int len;
while( (len=bis.read(bytes))!=-1){}
bis.close();
bos.close();
//俩个基本流在底层关好了

提高效率的原理和之前的字符流相似

字符缓冲流:

BufferedReader br=new BufferedReader(new FileReader(""));
String line=br.readLine();//一次读一整行,遇到回车换行结束,同时也不会读入换行
//多次读入
String line;
while((line=br.readLine)!=null){}//读不到返回null
br.close();

BufferedWriter bw=new BufferedWriter(new FileWriter("",true));//续写是底层的功能,所以要写给FileWriter
bw.read(" 45156");
bw.newLine("");
bw.read(" 156");

转换流:

是字符流和字节流的桥梁

//JDK11以前方案
InputStreamReader isr=new InputStreamReader(new FileInputStream("..."),"GBK");
//参数一是关联的字节流,参数二是编码格式
int ch;
while( (ch=isr.read())!=-1 )
isr.close();
//新方案
FileReader fr=new FileReader("...",Charset.forName("GBK"));
//下面同理,第二个参数是要用charset
//FIleWriter同理

(反)序列化流:

(对象操作输出流)

可以把Java中的对象写到本地文件中

ObjectOutputStream:

//一个对象
Student student=new Student("46",13);
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("...."));
oos.writeObject(student);
oos.close();

使用对象输出流将对象保存到文件时会出现NotSerializableException异常

解决方案:需要让Javabean类实现Serializable接口(不用重写,标记性接口:说明该对象可以被序列化)

反序列流:

对象操作输入流

ObjectInputStream ois=new ObjectInputStream(new FileInputStream("..."));
Object o=ois.readObject();
// Student o=(Student)ois.readObject();
ois.close();

写入文件后,会写入相应对象的序列号;所以如果修改了对象再次读回,就会报错;

也可以固定版本号

private static final long serialVersionUID=1L;//写在对象中
//或者在idea中设置后可以自动生成

或者对变量使用transient关键字:不会把当前属性序列化到本地

private transient String name; 

打印流:

字节打印流:

(没有缓冲区,开不开都会直接写入文件)

write不会自动换行哦

PrintStream ps=new PrintStream(new FileOutputStream(" "),true,Charset.forName("GBK"));//字节流  自动刷新  编码 默认是utf-8
ps.println(97);
ps.close();
ps.printf("%s",str);//C语言 bool %b

字符打印流:

字符流底层有缓冲区,想要自动刷新需要开启

PrintWriter pw=new PrintWriter(new FileWriter(""),true);
pw.println();
pw.close();

System.out底层:

PrintStream ps=System.out;
ps.println();
//标准输出流,唯一且不能关闭

(解)压缩流:

解压本质:把每一个ZipEntry按照层级拷贝到本地另一个文件夹中

本地要有一个zip压缩包

File src;//要解压的压缩包
File dest;//解压的目的地
//创建解压缩流
ZipInputStream zip=new ZipInputStream(new FileInputStream(src));
//获取压缩包中每一个zipentry对象
ZipEntry entry=zip.getNextEntry();//获取不到的时候返回null

ZipEntry entry;
while(entry=zip.getNextEntry()!=null){
    if(entry.isDirectiory()){//判断是否是文件夹
        File file=new File(dest,entry.toString());
        file.mkdirs();//在目的地创建相应的文件夹
    }else{
            FileOutputStream fos=new FileOutputStream(new File(dest,entry.toString()));
            int b;
            while(b=zip.read()!=-1){
                fos.write(b);
            }
            fos.close();
            zip.closeEntry();//压缩包中的一个文件处理完毕

    }
}
zip.close();

压缩流:

把每一个(文件/文件夹)看成ZipEntry对象放到压缩包中

File src//要压缩的文件
File dest//压缩的位置
//创建压缩流关联压缩包
ZipOutputStream zos=new ZipOutputStream(new FileOutputStream(new File(dest,"a.zip")));
ZipEntry entry=new ZipEntry("a.txt");//参数:压缩包里面的路径
zos.putNextEntry(entry);
FileInputStream fis=new FileInputStream(src);
int b;
while( b=fis.read()!=-1) zos.write(b);
zos.closeEntry();
zos.close();

commons-io:

Hutool工具包:

Properties配置文件:

后缀名:properties,内容都是键值对,归属于Map集合

properties是一个双列集合集合,拥有Map集合所有的特点。

重点:有一些特有的方法,可以把集合中的数据,按照键值对的形式写到配置文件当中。也可以把配置文件中的数据,读取到集合中来。

Properties prop=new Properties();//可以添加任意类型,但是一般都是添加字符串
prop.put("aa","bb");//插入键值对
//遍历
Set<Object> keys=prop.keySet();
for(Object key:keys){
    Object value=prop.get(key);
}

Set<Map.Entry<Object,Object>> entries=prop.entrySet();
for(Map.Entry<Object,Object> entry:entries){ key=entry.getKey();}

//与io流结合写入本地文件
FileOutputStream fos;
prop.store(流fos,String注释);
//读取
fis;
prop.load(fis);
fis.close();
//获取  文件中cnt=路径
String s=prop.get("cnt");//s中保存的是路径

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃芒果的蘑菇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值