Java—BIO (Block IO)
来源:互联网 发布:厦门雅迅网络很烂吗 编辑:程序博客网 时间:2024/06/06 03:05
一、IO基础知识
1、byte——字节,是计算机中的实际存储格式;byte[]是字节数组,可以通过指定的编码格式转换成char。
2、char——字符,可根据不同编码格式解析成byte序列。
- java中使用的是unicode中utf-16be编码,其中汉子占用2字节,英文占用2字节;
- utf-8——中文占用3字节,英文占用1字节;
- gbk——中文占用2字节,英文占用1字节。
public static void main(String[] args) throws UnsupportedEncodingException { String s1 ="字符串ABC"; byte[] bytes_utf_8=s1.getBytes();//使用项目默认编码转换成字节序列 byte[] bytes_gbk=s1.getBytes("gbk");//使用指定编码(gbk)转换成字节序列 System.out.println("utf_8:"); for(byte b1:bytes_utf_8){ //把byte转换为16进制的int进行展示 System.out.print(Integer.toHexString(b1 & 0xff)+" "); } System.out.println(); System.out.println("gbk:"); for(byte b1:bytes_gbk){ //把byte转换为16进制的int进行展示 System.out.print(Integer.toHexString(b1 & 0xff)+" "); } }
b1 & 0xff——位与操作 ffffffe5 & 000000ff = 000000e5 即e5
打印结果:
如图,根据不同的编码格式转换,得到的byte也不一样;
utf_8的汉字占用3个byte,gbk的汉字占用2个byte;
字节序列与字符串的相互转换必须采用相同的编码方式,否则会出现乱码。
3、String——字符串,可以理解成char[]。
二、文件操作
1、File
- File类只用于表示文件(目录)的信息(名称、大小等),不能用于文件内容的访问
File类的常用API
File file1=new File(“xxxx”)//构造函数
file1.exists() //判断目录、文件是否存在
file1.isDirectory()//判断是否目录
File[] files=file1.listFiles();//列出该目录下的所有FileFile简单运用——列出指定目录下所有的文件名
/** * 列出指定目录下所有的内容 * @param dir * @author Bdong */ public static void listDirectory(File dir){ //目录不存在 if(!dir.exists()){ throw new IllegalArgumentException("目录:"+dir+"不存在!"); } //不是目录 if(!dir.isDirectory()){ throw new IllegalArgumentException(dir+"不是目录!"); } //列出所有File File[] files=dir.listFiles(); if(files != null && files.length > 0){ for(File file:files){ if(file.isDirectory()){ //如果file是目录,则递归调用该方法 listDirectory(file); }else{ //如果是文件,就打印文件名 System.out.println(file); } } } }
public static void main(String args[]){ File file1=new File("/Users/Bdong/Downloads/coreJava"); FileUtil.listDirectory(file1); }
2、RandomAccessFile
- 提供对文件内容的访问,既可以读文件,也可以写文件。支持随机访问文件,可以访问文件的任意位置。
- RandomAccessFile使用简单流程
打开文件
RandomAccessFile raf = new RandomeAccessFile(file,"rw")//有两种模式"rw"(读写) "r"(只读)文件指针,打开文件时指针在>开头 pointer = 0
写方法
raf.write(int)//只写一个字节(后8位),同时指针指向下一个位置,准备再次写入
int b = raf.read()//读一个字节
raf.close()
三、字节流
1、InputStream&OutputStream接口
InputStream抽象了流读取数据的方式
输出流基本方法
int b = in.read() //读取一个字节到流;-1是 EOF
in.read(byte[] buf) //批量读取
in.read(byte[] buf,int start,int size) //批量读取OutputStream抽象了流写出数据的方式
输出流基本方法
out.write(int b) //从流写出一个byte,b的低8位
out.write(byte[] buf)//将buf字节数组批量写
out.write(byte[] buf,int start,int size)
2、FileInputStream&FileOutputStream
- FileInputStream具体实现从文件中读取byte数据到流
- FileOutputStream具体实现从流向文件中写出byte数据
- 具体实例
/** * 批量方式拷贝文件,大文件时速度最快 * @param srcFile * @param destFile * @throws IOException * @author Bdong */ public static void copyFile(File srcFile, File destFile) throws IOException{ if(!srcFile.exists()){ throw new IllegalArgumentException("文件:"+srcFile+"不存在!"); } if(!srcFile.isFile()){ throw new IllegalArgumentException(srcFile+"不是文件!"); } //输入流 FileInputStream fis =new FileInputStream(srcFile); //输出流 FileOutputStream fos =new FileOutputStream(destFile); //缓冲区 byte[] buf =new byte[8*1024]; int bytes; while((bytes=fis.read(buf, 0, buf.length))!=-1){ fos.write(buf,0,bytes); fos.flush(); } fos.close(); fis.close(); }
批量读取和写出的方式速度最快
3、DataInputStream&DataOutputStream
- 对”流”功能的扩展,可以更加方面的读取int,long,char等类型数据,如readInt/writeInt();readDouble/writeDouble();
FileOutputStream out = new FileOutputStream(file);DataOutputStream dos =new DataOutputStream(out);dos.writeInt(10);
- 通过查看源码可知,实际上writeInt是由write实现的,write只能写八位,那么写一个int需要写4次每次8位
以10为例;
二进制为:0000-0000-0000-0000-0000-0000-0000-1010;
先将10右移24位,再作与运算(& 0xFF),得到最高八位:0000-0000,写入;
……以此类推;
最后将10做与运算(& 0xFF),得到最低八位:0000-1010,写入;
完成int类型写入。
4、BufferedInputStream&BufferedOutputStream
带缓冲区的操作
四、字符流
1、相关概念
- java的文本(char):16位无符号整数,是字符的unicode编码(双字节编码);
- 文件:由byte组成的数据序列;
- 文本文件:是文本(char)序列按照某种编码方案(utf-8,utf-16be,gbk)序列化为byte的存储;
2、Reader&Writer
- Reader——按照编码解析byte流为char流
- Writer——按照编码解析char流到byte流
3、InputStreamReader&OutputStreamWriter
可指定字符编码
4、FileReader&FileWriter
读取文件方便,但不可指定字符编码
5、BufferdReader&BufferdWriter
- readLine 读一行,返回string,不能识别换行
- BufferdReader常与PrintWriter搭配使用
BufferedReader br = new BufferedReader( new InputStreamReader( new FileInputStream("/Users/Bdong/Downloads/test.txt"))); PrintWriter pw = new PrintWriter("/Users/Bdong/Downloads/test1.txt"); String line ; while((line = br.readLine())!=null){ System.out.println(line);//一次读一行,并不能识别换行 pw.println(line); pw.flush(); } br.close(); //bw.close(); pw.close();
五、对象序列化和反序列化
1、概念
- 对象序列化是指将Object转换成byte序列,反之称为反序列化
- 对象序列化和反序列化主要用于对象的保存和网络传输
- 序列化流(ObjectOutputStream)writeObject
- 反序列化 (ObjectInputStream)readObject
2、序列化接口(Serializable)
- 对象必须实现序列化接口(Serializable )才能进行序列化,否则将出现异常!
3、transient关键字
- transient关键字修饰的成员变量不进行jvm默认的序列化,但可以自己完成这个元素的序列化,可以帮我们提高性能
从ArrayList中可以看到,elementData被transient修饰,所以不被jvm默认序列化;
但ArrayList自己重写了自定义序列化/反序列化方法:writeObject、readObject
/** * Save the state of the <tt>ArrayList</tt> instance to a stream (that * is, serialize it). * * @serialData The length of the array backing the <tt>ArrayList</tt> * instance is emitted (int), followed by all of its elements * (each an <tt>Object</tt>) in the proper order. */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ // Write out element count, and any hidden stuff int expectedModCount = modCount; s.defaultWriteObject(); // Write out size as capacity for behavioural compatibility with clone() s.writeInt(size); // Write out all elements in the proper order. for (int i=0; i<size; i++) { s.writeObject(elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } }
/** * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is, * deserialize it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { elementData = EMPTY_ELEMENTDATA; // Read in size, and any hidden stuff s.defaultReadObject(); // Read in capacity s.readInt(); // ignored if (size > 0) { // be like clone(), allocate array based upon size not capacity ensureCapacityInternal(size); Object[] a = elementData; // Read in all elements in the proper order. for (int i=0; i<size; i++) { a[i] = s.readObject(); } } }
我们也可以在必要的时候按照如上方法自定义序列化
4、关于子父类构造函数的序列化的一些结论
- 一个类实现了序列化接口,其子类不用实现序列化接口了;
- 序列化会递归调用父类构造函数;
- 反序列化不会调用构造函数,因为是从序列中读取;
- 对子类进行反序列化,如果父类没有实现序列化,父类构造函数会被调用;
- Java—BIO (Block IO)
- java-IO-BIO-工具类
- Java IO: BIO, NIO, AIO
- 【java】IO详解之BIO
- 【基础-java-BIO流】BIO(1)常用IO流引索
- java io bio nio aio 详解
- java io bio nio aio 详解
- Java的IO:BIO | NIO | AIO
- java io bio nio aio 详解
- JAVA-IO模型(BIO,NIO,AIO)
- java之阻塞IO(BIO)
- Java之IO,BIO,NIO,AIO
- Java IO知识:NIO,BIO,AIO
- Java IO:面向流、同步、阻塞式IO(BIO)
- 【Java IO模式】Java BIO NIO AIO总结
- 关于JAVA IO操作中的AIO、NIO、BIO
- Java IO:BIO和NIO区别及各自应用场景
- Java 学习系列: IO相关的BIO,NIO与AIO
- 【LeetCode】Container With Most Water 解题报告
- GPU开发环境
- Storm JAVA_HOME is incorrectly set
- Android 任务管理器分析小结
- 面试需要问到的11点
- Java—BIO (Block IO)
- Linux 技巧:让进程在后台可靠运行的几种方法
- 常见验证码的弱点与验证码识别
- Error:Execution failed for task ':app:transformClassesWithDexForRelease'. > 解决
- NYOJ-背包问题
- Java文件操作(二)
- JQhover实现鼠标悬停操作
- 浅谈 MySQL 的存储引擎(表类型)
- 归并排序