Java拾遗系列- io知识
来源:互联网 发布:身份证复制软件3.7 编辑:程序博客网 时间:2024/06/07 21:11
Java拾遗系列- io知识
最近看tomcat源码,发现socket的输入输出流处理起来坑挺多的。莫名其妙的就阻塞了。最后决定回来先看看io知识。
- 简介
- io分类及相关实例
3.总结
1.简介
Java IO流对我们来说既熟悉有陌生,首先做Java没有不知道IO流的,但是在工作中经常用的场景不是很多。最常用的是上传图片,操作xlsx文件等功能,自己写Socket通信的很少。Java程序与外界进行信息交互。都需要用到io流。如文件的操作,控制台的输入输出等,io流可以理解为数据的传输。数据在两设备间的传输称为流,流的本质是数据传输。
2.io分类及相关应用
2.1 io流的分类
io流的分类可以从三方面进行分类,从流向分类:输入流 输出流从单位分类:字节流 字符流从功能分类:节点流 处理流
在Java这么多IO流中,真正操作资源的只有FileInputStream,FileOutputStream两个流,FileReader,FileWriter是基于FileInputStream,FileOutputStream实现的。而其他的流都是基于内存实现的。像ByteArray,CharArray,Piped下面会详细介绍
2.2 File**流
/** * FileInputStream FileOutputStream 文件字节输入输出流 * 查看源码可知 * FileInputStream FileOutputStream 的close() 实现了管理资源方法 * FileOutputStream 的flush()方法为空。说明FileOutputStream 没有缓冲区 * */ public static void testFileInputStream() { File file = new File("testFile.txt"); try { //写入 FileOutputStream fileOutputStream = new FileOutputStream(file); byte[] outbytes = "testFileInputStream 测试".getBytes("utf-8"); fileOutputStream.write(outbytes); //fileOutputStream.flush(); fileOutputStream.close(); //读取 FileInputStream fileInputStream = new FileInputStream(file); byte[] inbytes = new byte[(int) file.length()]; int len = fileInputStream.read(inbytes); System.out.println(len); System.out.println(new String(inbytes, "utf-8")); fileInputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * FileReader FileWriter 文件字符输入输出流 * FileReader FileWriter 的本质是通过StreamDecoder StreamEncoder 字符流字节流编码解码转换器实现的。 * 其实本质还是操作FileInputStream FileOutputStream 只不过是通过StreamDecoder StreamEncoder 在中间处理下数据。将字节变成字符 * 从源码可以看出 * FileReader 继承InputStreamReader 而 InputStreamReader 继承 Reader * FileWriter 继承OutputStreamWriter 而 OutputStreamWriter 继承 Writer * FileReader FileWriter 类没有实现read(),writer()等方法 只有构造函数 * 1,FileReader的构造函数是将传入的文件new FileInputStream() 并将文件字节流作为参数调用父类InputStreamReader的构造函数 * 2,InputStreamReader的构造函数 将文件字节流 传递给StreamDecoder.forInputStreamReader()方法构建 字节流解码转换器 *,3,而我们调用read()方法实际是调用的StreamDecoder.read()方法。 */ public static void testFileReader() { File file = new File("testFile.txt"); try { //写入 FileWriter fileWriter = new FileWriter(file); fileWriter.write("testFileReader 测试"); fileWriter.flush(); fileWriter.close(); //读取 FileReader fileReader = new FileReader(file); char[] chars = new char[(int) file.length()]; int len = fileReader.read(chars); System.out.println(len); System.out.println(new String(chars)); fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } }
2.3内存流
内存流,其实就是将数据存入到内存中,像 ByteArrayInputStream,ByteArrayOutputStream,CharArrayReader,CharArrayWriter,StringReader,StringWriter其实实现都是将数据已数组形式存入到内存中。使用是注意不要将大的数据存入内存中。否则内存溢出。注意内存泄漏问题。
/** * 实现类似内存虚拟文件的功能 * ByteArrayInputStream本身操作的是一个数组,并没有打开文件描述之类的,所有不需要关闭流 */ public static void testByteArrayInputStream() { try { //写入 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024); byteArrayOutputStream.write("testByteArrayInputStream 测试".getBytes("utf-8")); //byteArrayOutputStream.flush(); //不用书写这个因为就没有调用底层资源,所以也就不用释放资源 byteArrayOutputStream.close(); //但使用ByteArrayInputStream的好处是关掉流之后它的数据仍然存在。 byte[] outbytes = byteArrayOutputStream.toByteArray(); //读取 byte[] inbytes = new byte[outbytes.length]; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outbytes); int len = byteArrayInputStream.read(inbytes); System.out.println(len); System.out.println(new String(inbytes, "utf-8")); ////不用书写这个因为就没有调用底层资源,所以也就不用释放资源 byteArrayInputStream.close(); //使用完毕设置为NULL 让GC回收 byteArrayOutputStream = null; byteArrayInputStream = null; } catch (IOException e) { e.printStackTrace(); } } /** * CharArrayReader 本身操作的是char buf[];数组 并没有打开文件描述之类的,所有不需要关闭流 * 用法与ByteArrayInputStream相同 */ public static void testCharArrayReader() { try { CharArrayWriter charArrayWriter = new CharArrayWriter(); charArrayWriter.write("testCharArrayReader 测试!"); char[] outchars = charArrayWriter.toCharArray(); CharArrayReader charArrayReader = new CharArrayReader(outchars); char[] inchars = new char[1024]; charArrayReader.read(inchars); System.out.println(new String(inchars)); charArrayWriter = null; charArrayReader = null; } catch (IOException e) { e.printStackTrace(); } } /** * 字符串流 与CharArray 相同 存入内存,不涉及到资源,close()方法 为空实现 * StringWriter 内部是基于StringBufffer实现的 * * StringReader 内部是基于String 实现的 */ public static void testStringReader(){ try { StringWriter stringWriter = new StringWriter(); stringWriter.write("testStringReader 测试"); //空方法 stringWriter.flush(); //空方法 stringWriter.close(); //StringWriter 重写toString方法 StringReader stringReader = new StringReader(stringWriter.toString()); char[] chars = new char[200]; stringReader.read(chars); System.out.println(new String(chars)); //close() 方法 实现str = null; reader 方法清除内部的str 没有内存泄漏问题 stringReader.close(); } catch (IOException e) { e.printStackTrace(); } }
2.4管道流
管道流其实也是操作内存中的数组实现的。具体可查看源码。多用于线程之间的通信。
public static void main(String[] args) throws IOException { //管道流可以实现两个线程之间,二进制数据的传输。 TestPipedInputStream testPipedInputStream = new TestPipedInputStream(); TestPipedOutputStream testPipedOutputStream = new TestPipedOutputStream(); //将管道连接 testPipedOutputStream.getPipedOutputStream().connect(testPipedInputStream.getPipedInputStream()); Thread th1 = new Thread(testPipedInputStream); Thread th2 = new Thread(testPipedOutputStream); th1.start(); th2.start(); } class TestPipedInputStream implements Runnable { private PipedInputStream pipedInputStream; public TestPipedInputStream() { pipedInputStream = new PipedInputStream(); } public PipedInputStream getPipedInputStream() { return pipedInputStream; } @Override public void run() { try { byte[] bytes = new byte[1024]; int len = pipedInputStream.read(bytes); System.out.println(len); System.out.println(new String(bytes, "utf-8")); pipedInputStream.close(); } catch (IOException e) { e.printStackTrace(); } }} class TestPipedOutputStream implements Runnable { private PipedOutputStream pipedOutputStream; public TestPipedOutputStream() { pipedOutputStream = new PipedOutputStream(); } public PipedOutputStream getPipedOutputStream() { return pipedOutputStream; } @Override public void run() { try { pipedOutputStream.write("testPipedOutputStream 管道测试".getBytes("utf-8")); pipedOutputStream.flush(); pipedOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } }}
2.5缓冲流
/** * 用了BufferedInputStream后你每次读取都是从缓冲区里拷贝数据,在后你再读,缓冲区没东西了就调IO从数据源读到缓冲区,然后你再从缓冲区读。 * 如果你自己建立的数组大小和缓冲区大小一样,根本就没起到缓冲作用。 * 当你程序的数组小于缓冲区的大小的时候才会起到缓冲作用。比如是byte[] b=new byte[2048];, * 你要读的数据是1G,那么你要调512次IO,假设一次1s,就512s,但如果用BufferedInputStream, * 你每从缓冲区读取4(8192/2048=4)次才调用一次IO(假设访问内存一次0.1s),总共要128次 * ,就128s,加上总的从缓冲区拷贝数据的时间(512*0.1=51.2s),128+51.2=179.2。 * 这里用0.1s和1s来体现IO很耗时 */ public static void testBufferedInputStream(){ try { File file = new File("testfile.txt"); FileInputStream fileInputStream = new FileInputStream(file); BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); //每次读取时1024 而默认缓冲区的大小是1024*8 缓冲起到作用 byte[] inbytes = new byte[1024]; System.out.println(file.length()); int count = 1; while(true){ System.out.println("count====================================="+count); int len=bufferedInputStream.read(inbytes); System.out.println("len = ======================================================="+len); System.out.println(new String(inbytes,"utf-8")); ++count; if(len==-1) break; } fileInputStream.close(); bufferedInputStream.close(); FileOutputStream fileOutputStream = new FileOutputStream(file); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); bufferedOutputStream.write("testBufferedInputStream 测试".getBytes("utf-8")); bufferedOutputStream.flush(); bufferedOutputStream.close(); fileOutputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
2.6 ObjectInputStream
ObjectInputStream,OjbectOutputStream 通常用做序列化反序列化应用。它是处理流。
public static void testObjectInputStream(){ try { Cat cat = new Cat("12","波斯猫"); File file = new File("object.txt"); ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file)); objectOutputStream.writeObject(cat); objectOutputStream.flush(); objectOutputStream.close(); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file)); Object object= objectInputStream.readObject(); Cat inCat = (Cat)object; System.out.println(inCat.getId()+"=="+inCat.getName()); objectInputStream.close(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } class Cat implements Serializable{ // 可序列化对象的版本 private static final long serialVersionUID = 1L; private String id; private String name; public Cat(String id, String name) { this.id = id; this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
3.总结
Java IO流有很多类,学习起来很费时间。但是抓住几个常用的类学习,看看源码,把源码理解清楚,思路还是挺清晰的。
阅读全文
0 0
- Java拾遗系列- io知识
- Java拾遗------IO流
- java零碎知识拾遗
- Java线程知识拾遗
- java拾遗------面向对象知识
- JAVA IO及文件操作拾遗
- 知识拾遗
- 计算机底层知识拾遗(五)理解块IO层
- 计算机底层知识拾遗(五)理解块IO层
- Java IO 知识
- Java IO相关知识
- 知识链-Java IO
- java IO相关知识
- Java知识:IO流
- Java拾遗2:文件传输基础——Java IO流
- Java知识拾遗:三大框架的技术起源
- Java知识拾遗:三大框架的技术起源
- Java知识拾遗:三大框架的技术起源
- Lintcode 612. K个最近的点
- 装饰模式
- 第十三周java作业--集合框架
- Mysql基本命令之事务处理
- sql的基本语句
- Java拾遗系列- io知识
- Linux基础:日志管理
- DNS错误不能上网怎么办 电脑dns错误修复方法
- ZC702开发板-上电测试
- ASC1 E-Nice Patterns Strike Back
- python学习——random模块
- perl中system函数和反引号` `使用区别
- [MVVM]01-MVVMLight安装
- 左神指南第一章_栈和队列