本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/868043
由于不想让博客太难看,所以写到二.这里也会循序渐进,一步步走入所谓的高效和安全.
上一篇,介绍了思路、设计。博客地址:http://guoyunsky.iteye.com/blog/867469 同时写了个MyOutputStream,用于读取输入流(如IO、网络),但恐怕输入流过大,或者多线程并发读取的时候导致总的内存占用过大.所以采用缓存+文件存放形式。缓存固定一个大小,这样可以控制内存,同时可以重复利用.超过缓存的数据写入到磁盘,避免内存溢出。但如此保存的数据又要读取出来处理,那就又需要一个读取类.将缓存和硬盘中的数据都读出。有人可能会说,怎么会这么麻烦?有这种需求吗?就比如发表博客,网站需要过滤敏感词.那么就需要多个线程读取博客,然后过滤关键字后输出到MyOuputStream.之后还需要什么处理,但就要获取这些数据.于是有了下面一个类,可以以流的形式读取缓存和磁盘中的数据.先贴上代码:
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; public class ReuseInputStream extends InputStream { private InputStream diskStream; // 硬盘数据 private long position; // 当前位置 private long size; // 数据大小 private byte[] buffer; // 缓存 public ReuseInputStream(long size, byte[] buffer,String backedFileName) throws FileNotFoundException { super(); this.size = size; this.buffer = buffer; if(size>buffer.length){ File backedFile=new File(backedFileName); //RandomAccessFile raf=new RandomAccessFile(backedFile,"r"); // 先埋个伏笔,还有改进之处 diskStream=new FileInputStream(backedFile); } } @Override public int read() throws IOException { if(position==size){ // 已经满了 return -1; } if(position<buffer.length){ // 先从缓存中读 int c=buffer[(int)position]& 0xFF; position++; return c; } // 缓存中已经读取完毕,从文件中读取 int c=diskStream.read(); if(c>=0){ // 确保文件中也还有数据 position++; } return c; } @Override public int read(byte[] b, int off, int len) throws IOException { if(position==size){ // 已经满了 return -1; } if(position<buffer.length){ // 先从缓存中读取,但缓存读完了,不会从硬盘中读取,而是直接返回 int toCopy=(int)Math.max(size-position, Math.min(len, buffer.length-position)); // 计算要从缓存中读取的字节数 if(toCopy>0){ System.arraycopy(buffer, (int)position, b, off, len); position+=toCopy; } return toCopy; } int c=diskStream.read(b, off, len); // 从磁盘中读取 if(c>0){ position+=c; } return c; } @Override public void close() throws IOException { super.close(); if(diskStream!=null){ diskStream.close(); } } // 获得数据大小 public long getSize() { return size; } // 剩下的数据长度 public long getRemain(){ return size-position; } // 获得当前位置 public long getPosition() { return position; } // 获得缓存数据 public byte[] getBuffer() { return buffer; } }
这个类得提供给MyOutputStream,让它可以返回它里面的数据,于是修改MyOutputStream。这里省略前面的代码,同时可以看测试:
package streamUnderThreads; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; public class MyOutputStream extends OutputStream { private boolean isOpen; // 是否已经打开 private long size; // 数据总大小 private String backedFileName; // 超出缓存,要写入到的文件名 private OutputStream diskStream;// 超出缓存,写入到文件的OutputStream private byte[] buffer; // 缓存 private long position; // 当前位置 private boolean recording; // 是否记录数据中 //省略... // 获得数据流 public ReuseInputStream getReuseInputStream() throws IOException{ return new ReuseInputStream(size,buffer,backedFileName); } public static void main(String[] args) { String dir=new File("").getAbsolutePath().concat(File.separator); String fileMemory=dir.concat("fileMemory.txt"); String fileDisk=dir.concat("fileDisk.txt"); int bufferSize=5; MyOutputStream mosMemory=null; MyOutputStream mosDisk=null; try { mosMemory=new MyOutputStream(bufferSize,fileMemory); mosMemory.open(); mosDisk=new MyOutputStream(bufferSize,fileDisk); mosDisk.open(); for(int i=0;i<100;i++){ if(i<bufferSize){ mosMemory.write(i); } mosDisk.write(i); } mosMemory.close(); mosDisk.close(); System.out.println("mosMemory length:"+mosMemory.getSize()); System.out.println("mosDisk length:"+mosDisk.getSize()); // 返回数据流 ReuseInputStream ris=mosDisk.getReuseInputStream(); StringBuilder sb=new StringBuilder(); int c; while((c=ris.read())!=-1){ sb.append(c); } System.out.println(sb.toString()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ } } }
以上只是以流的形式返回,但有时就是有需求,要将整个内容都返回放入内存中,如此内存还是有要爆的风险.那又该怎么处理?再开篇博客,请看三...
更多技术文章、感悟、分享、勾搭,请用微信扫描:
相关推荐
Java输入输出流(I/O流)是Java编程中不可或缺的一部分,它允许程序处理数据的读取、写入和传输。Java I/O系统基于流的概念,流可以被视为数据的有序序列,既可以是从源(如文件、网络连接)读取数据的输入流,也...
输入/输出处理数据的传输,而多线程则涉及程序的并发执行。 首先,让我们深入理解Java的IO系统。Java.IO包包含了大量用于处理输入和输出操作的类和接口。输入流(InputStream)和输出流(OutputStream)是这个包的...
Java中的输入输出流是程序与外部数据...总之,Java的输入输出流是其强大的特性之一,为开发者提供了灵活且高效的处理数据输入输出的能力。通过不断的实践和学习,我们可以掌握更多的IO技巧,更好地应对各种实际问题。
Java输入输出流是Java编程中不可或缺的部分,它用于应用程序与外部设备之间进行数据交换,比如磁盘、网络、键盘和显示器。I/O流是Java中处理输入和输出的基础框架,它提供了一种抽象的方式来处理不同类型的输入源和...
5. **I/O流**:在Java中,`InputStream`和`OutputStream`是用于读写文件的基础类,多线程传输时,每个线程可以拥有自己的输入/输出流实例,分别处理文件的一部分。 6. **异常处理**:多线程环境下,需要确保每个...
Java提供了丰富的I/O处理机制,包括标准输入输出流、字节流、字符流等多种方式来处理数据的读取和写入。标准输入输出流是Java中非常基础且重要的组成部分。 **1.1 标准输入输出流简介** - **System.out**: 是一个`...
"文件管理和输入输出流"这个主题涵盖了Java、C语言、C++、C#以及JSP等多种编程语言中的相关技术,这些技术使得程序员能够有效地读取、写入和处理文件数据。 首先,我们来探讨文件管理。文件管理主要包括创建、打开...
然后,我们引入`java.nio`包,这个包提供了非阻塞I/O操作,使得在多线程环境下处理数据更高效。特别是`java.nio.channels.Channels`和`java.nio.file.Files`类,它们可以帮助我们将输入流转换为通道,并将数据写入到...
Java多线程文件传输是一个复杂而实用的编程概念,它结合了Java的Socket编程和Swing GUI库,用于实现高效的数据交换。在这个项目中,开发者创建了一个基于Socket的多线程文件传输系统,允许用户通过图形化用户界面...
在Java中,输入输出流是一组类和接口,用于读取和写入数据到不同的源和目标,如文件、网络连接或内存。Java的IO流分为字节流和字符流两大类,字节流处理原始的8位字节数据,而字符流则处理Unicode字符。基本的输入流...
Java 输入输出流是Java编程语言中处理数据传输的基础机制,主要负责程序与外部资源(如文件、网络连接等)之间的数据交互。Java 提供了多种类型的流,它们分为两大类:字节流(处理单个字节的数据)和字符流(处理...
总的来说,Java的异常处理、多线程和流式输入输出与文件处理是编程中重要的概念,理解并熟练运用它们能帮助开发者编写更健壮、安全和高效的代码。对于初学者而言,通过阅读详细的教程和实践练习,可以逐步掌握这些...
Java输入输出流是Java编程语言中的核心概念,用于在程序之间、程序与文件系统、网络连接等不同数据源之间传输数据。在这个主题中,我们将深入探讨Java输入输出流的使用,通过具体的代码示例帮助你理解和掌握这个关键...
3. **输入/输出流**:Java的IO流是处理数据输入和输出的基础,下载工具中通常会用到`InputStream`(用于读取服务器的数据)和`OutputStream`(用于将数据写入本地文件)。例如,我们可以使用`BufferedInputStream`和...
### Java多线程网络传输文件(非同步) #### 概述 在现代软件开发中,尤其是在涉及大量数据传输的应用场景下,高效的文件传输方案尤为重要。Java作为一种广泛应用的编程语言,提供了丰富的工具和技术来实现高性能...
综上所述,这份Java学习资料涵盖了从基础到高级的多个主题,包括基本语法、面向对象编程、异常处理、Applet、GUI设计、多线程以及输入输出流。对于想要系统学习Java的初学者,这是一份非常全面且深入的学习资源。...
总的来说,这个实验将教会你如何在Java多线程环境中实现高效、稳定的文件上传和下载功能,这是一项对任何开发人员来说都非常实用的技能,尤其是在构建高性能的Web应用或后台服务时。通过实践和理解这些概念,你将...
### Java输入输出流详解 #### 一、Java IO 概述 在计算机程序设计中,输入输出(Input/Output,简称IO)是非常重要的一个概念。它涉及到程序如何与外部世界进行数据交换,最常见的外部设备包括磁盘存储和网络通信等...
综上所述,Java多线程下载涉及到多线程编程、网络通信、文件操作、并发控制等多个核心Java技术,通过合理设计和优化,可以显著提升下载大文件的效率。在实际开发中,还需要考虑如何将这些概念应用于具体的项目需求,...
在Java编程语言中,输入输出流(Input/Output Stream)是处理数据传输的核心概念,而线程则是实现并发处理和程序高效运行的关键机制。这两者在构建高效、响应迅速的应用程序时都扮演着至关重要的角色。 输入输出流...