Java基础系列10:内存操作流,管道流,合并流,压缩流以及回退流

简介:

一 内存操作流 

内存操作流的主要作用是完成内存的输入和输出。比如说在某些情况下需要生成一些临时信息,而将这些临时信息保存在文件中不仅要进行文件的读写而且在功能完成之后还需要删除这个临时文件,因此比较麻烦,这时或许就需要用到内存操作流了。

需要用到的API是:ByteArrayInputStreamByteArrayOutputStream,分别表示输入流和输出流,示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package  javase.io;
 
import  java.io.ByteArrayInputStream;
import  java.io.ByteArrayOutputStream;
import  java.io.IOException;
 
public  class  ByteArrayDemo {
 
     public  static  void  main(String[] args)  throws  IOException{
         String str =  "HTTP://WWW.ZIFANGSKY.CN" ;
         //内存操作输入流
         ByteArrayInputStream bInputStream =  new  ByteArrayInputStream(str.getBytes( "UTF-8" ));
         //内存操作输出流
         ByteArrayOutputStream bOutputStream =  new  ByteArrayOutputStream();
         int  temp =  0 ;
         //一个个字节的读,并且将大写转换为小写
         while ((temp = bInputStream.read()) != - 1 )
             bOutputStream.write(Character.toLowerCase(temp));
         
//      bOutputStream.flush();
         bInputStream.close();
         bOutputStream.close();
         System.out.println(bOutputStream.toString());
     }
 
}

输出:

1
http://www.zifangsky.cn


二 管道流

管道流的主要作用是可以进行两个线程之间的通信,如果要进行管道的输出,则必须把输出流连接到输入流上,需要用到的方法是:connect(PipedInputStream pipedInputStream)

需要用到的API是:PipedInputStreamPipedOutputStream,示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package  javase.io;
 
import  java.io.BufferedReader;
import  java.io.IOException;
import  java.io.InputStreamReader;
import  java.io.PipedInputStream;
import  java.io.PipedOutputStream;
 
class  SendData  implements  Runnable {
     private  PipedOutputStream pipedOutputStream =  null ;
 
     // 获取管道输出流实例
     public  PipedOutputStream getPipedOutputStream() {
         return  pipedOutputStream;
     }
 
     // 在构造方法中实例化
     public  SendData() {
         pipedOutputStream =  new  PipedOutputStream();
     }
 
     public  void  run() {
         String str =  "http://www.zifangsky.cn" ;
         try  {
             pipedOutputStream.write(str.getBytes());
             pipedOutputStream.close();
         catch  (IOException e) {
             e.printStackTrace();
         }
     }
}
 
class  ReceiveData  implements  Runnable {
     private  PipedInputStream pipedInputStream =  null ;
 
     // 获取管道输入流实例
     public  PipedInputStream getPipedInputStream() {
         return  pipedInputStream;
     }
 
     public  ReceiveData() {
         pipedInputStream =  new  PipedInputStream();
     }
 
     public  void  run() {
         BufferedReader reader =  new  BufferedReader( new  InputStreamReader(
                 pipedInputStream));
         String temp =  "" ;
         try  {
             while  ((temp = reader.readLine()) !=  null )
                 System.out.println(temp);
 
             reader.close();
             pipedInputStream.close();
         catch  (IOException e) {
             e.printStackTrace();
         }
 
     }
}
 
public  class  PipedDemo {
 
     public  static  void  main(String[] args) {
         SendData send =  new  SendData();
         ReceiveData receive =  new  ReceiveData();
         try  {
             //连接管道
             send.getPipedOutputStream().connect(receive.getPipedInputStream());
         catch  (IOException e) {
             e.printStackTrace();
         }
 
         new  Thread(send).start();
         new  Thread(receive).start();
     }
 
}

注:上面的示例代码定义了两个线程对象,分别表示管道输出流和管道输入流,在操作的时候只需要使用PipedOutputStream类中提供的connect()connect(PipedInputStream pipedInputStream)方法就可以将两个管道流连接起来,线程启动后就会自动进行管道的输入和输出操作了


三 合并流

合并流的主要功能是将两个流的内容合并到一起

需要用到的API是:SequenceInputStream,实例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package  javase.io;
 
import  java.io.FileInputStream;
import  java.io.FileOutputStream;
import  java.io.IOException;
import  java.io.InputStream;
import  java.io.OutputStream;
import  java.io.SequenceInputStream;
 
public  class  SequenceDmeo {
 
     public  static  void  main(String[] args)  throws  IOException{
         //输入流1
         InputStream iStream1 =  new  FileInputStream( "C:\\Users\\Administrator\\Desktop\\demo.txt" );
         //输入流2
         InputStream iStream2 =  new  FileInputStream( "C:\\Users\\Administrator\\Desktop\\demo2.txt" );
         //输出流
         OutputStream oStream =  new  FileOutputStream( "C:\\Users\\Administrator\\Desktop\\demo3.txt" );
         //合并流
         SequenceInputStream stream =  new  SequenceInputStream(iStream1, iStream2);
         int  temp =  0 ;
         while ((temp = stream.read()) != - 1 )
             oStream.write(temp);
         
         iStream1.close();iStream2.close();oStream.close();stream.close();
     }
 
}

上面代码执行完毕的结果就是demo.txt文件和demo2.txt文件的内容都会合并到一个文件demo3.txt这个文件中去了


四 压缩流

在Java中可以通过压缩流将文件或文件夹压缩成ZIP,JAR或GZIP等格式,当然也可以进行反向解压缩。

有关压缩的常用几个API:

i)JAR:JarOutputStream和JarInputStream

ii)GZIP(比如说在Linux下常见的.gz格式):GZIPOutputStream和GZIPInputStream

iii)ZIP:ZipOutputStreamZipInputStream,ZipFile,ZipEntity等

下面以ZIP格式来举例说明压缩与解压缩

(1)单个文件的ZIP缩:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
      * 压缩文件
     
      * @param filePath
      *            待压缩的文件路径
      * @param zipPath
      *            压缩之后的ZIP文件的路径
      * */
     public  void  compressFile(String filePath, String zipPath)
             throws  IOException {
         // 源文件
         File file1 =  new  File(filePath);
         // 定义压缩后的文件
         File zipFile =  new  File(zipPath);
 
         InputStream inputStream =  new  FileInputStream(file1);
         // 实例化压缩输出流并指定路径
         ZipOutputStream zOutputStream =  new  ZipOutputStream(
                 new  FileOutputStream(zipFile));
 
         zOutputStream.putNextEntry( new  ZipEntry(file1.getName()));
         zOutputStream.setComment( "http://www.zifangsky.cn" ); // 设置注释
         int  temp =  0 ;
         while  ((temp = inputStream.read()) != - 1 )
             zOutputStream.write(temp);
 
         inputStream.close();
         zOutputStream.close();
 
     }

测试:

1
2
3
4
ZipOutputStreamDemo demo =  new  ZipOutputStreamDemo();
         String filePath =  "C:\\Users\\Administrator\\Desktop\\demo.txt" ;
         String zipPath =  "C:\\Users\\Administrator\\Desktop\\demo.zip" ;
         demo.compressFile(filePath, zipPath);

(2)文件夹的级联压缩

在上面的例子中举例说明了单个文件的压缩,但是我们通常可能需要将一个文件夹进行压缩,并且该文件夹中还有文件夹,比如说像这样:

wKiom1cLo7TDZPMOAACOb5aO2bY679.png

这时候我们可以通过递归调用的方式来进行压缩。如果是普通文件则将文件内容压缩输出到ZipOutputStream流中,如果是文件夹则进行递归调用。完整示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/**
      * 压缩文件或目录
     
      * @param directoryPath
      *            待压缩文件或目录的路径
      * @param zipPath
      *            压缩之后的ZIP文件的路径
      * */
     public  void  compressFolder(String directoryPath, String zipPath)
             throws  IOException {
         // 源文件夹
         File dir =  new  File(directoryPath);
         // 定义压缩后的文件
         File zipFile =  new  File(zipPath);
 
         // 实例化压缩输出流并指定路径
         ZipOutputStream zOutputStream =  new  ZipOutputStream(
                 new  FileOutputStream(zipFile));
         zOutputStream.setComment( "http://www.zifangsky.cn" ); // 设置注释
 
         compress(dir, dir.getName(), zOutputStream);
         zOutputStream.close();
     }
 
     /**
      * 循环递归压缩文件
     
      * @param file
      *            待压缩文件或目录
      * @param path
      *            压缩后的文件在压缩包中的起始路径
      * @param zOutputStream
      *            ZIP压缩输出流
     
      * */
     public  void  compress(File file, String path, ZipOutputStream zOutputStream)
             throws  IOException {
         InputStream inputStream =  null ;
         if  (file.isDirectory()) {
             File lists[] = file.listFiles();
             int  length = lists.length;
             // 循环遍历每个文件
             for  ( int  i =  0 ; i < length; i++) {
                 String temp_path = path +  "\\"  + lists[i].getName();  // 相对路径
                 // 如果是目录则继续递归压缩
                 if  (lists[i].isDirectory())
                     compress(lists[i], temp_path, zOutputStream);
                 else  {
                     // 如果是文件则将文件内容压缩输出到ZipOutputStream流中
                     inputStream =  new  FileInputStream(lists[i]);
                     zOutputStream.putNextEntry( new  ZipEntry(temp_path));
                     int  temp =  0 ;
                     while  ((temp = inputStream.read()) != - 1 )
                         zOutputStream.write(temp);
 
                     inputStream.close();
                 }
             }
         else  {
             inputStream =  new  FileInputStream(file);
             zOutputStream.putNextEntry( new  ZipEntry(path));
             int  temp =  0 ;
             while  ((temp = inputStream.read()) != - 1 )
                 zOutputStream.write(temp);
             inputStream.close();
         }
 
     }

在上面的例子的基础上继续进行测试:

1
2
3
String directoryPath =  "C:\\Users\\Administrator\\Desktop\\test" ;
          String zipPath =  "C:\\Users\\Administrator\\Desktop\\dir.zip" ;
          demo.compressFolder(directoryPath,zipPath);

测试效果如下:

wKiom1cLpAHhdEtoAAChqle5mX8648.png

(3)对件进行级联解压缩

这里以上面例子中的dir.zip文件为测试目标进行解压缩,代码不难而且关键地方我已经写了注释,因此这里就不多说了,完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package  javase.io;
 
import  java.io.File;
import  java.io.FileInputStream;
import  java.io.FileOutputStream;
import  java.io.IOException;
import  java.io.InputStream;
import  java.io.OutputStream;
import  java.util.zip.ZipEntry;
import  java.util.zip.ZipFile;
import  java.util.zip.ZipInputStream;
 
public  class  ZipInputStreamDemo {
     /**
      * 压缩文件循环递归解压缩
     
      * @param zipPath
      *            压缩文件路径
      * @param filePath
      *            解压之后的文件的保存路径
      * */
     public  void  decompress(String zipPath, String filePath)  throws  IOException {
         File file =  new  File(zipPath);  // 压缩文件
         File outFile =  null // 解压后的文件
         ZipFile zipFile =  new  ZipFile(file);
         ZipInputStream zInputStream =  new  ZipInputStream( new  FileInputStream(
                 file));
         ZipEntry zipEntry =  null // 定义一个ZipEntry对象,用于接收压缩文件中的每一个实体
         InputStream inputStream =  null ;
         OutputStream outputStream =  null ;
 
         // 获取压缩文件中的每个实体文件
         while  ((zipEntry = zInputStream.getNextEntry()) !=  null ) {
             outFile =  new  File(filePath +  "\\"  + zipEntry.getName());  // 实例化
 
             if  (!outFile.getParentFile().exists()) {
                 outFile.getParentFile().mkdirs();  // 如果文件夹不存在则级联创建文件夹
             }
             if  (!outFile.exists())
                 outFile.createNewFile();  // 如果文件不存在则创建新文件
 
             inputStream = zipFile.getInputStream(zipEntry);
             outputStream =  new  FileOutputStream(outFile);
             int  temp =  0 ;
             while  ((temp = inputStream.read()) != - 1 )
                 outputStream.write(temp);
 
             inputStream.close();
             outputStream.close();
         }
         zInputStream.close();
         zipFile.close();
     }
 
     public  static  void  main(String[] args)  throws  IOException {
         ZipInputStreamDemo demo =  new  ZipInputStreamDemo();
         String filePath =  "C:\\Users\\Administrator\\Desktop\\decompress" ;
         String zipPath =  "C:\\Users\\Administrator\\Desktop\\dir.zip" ;
         demo.decompress(zipPath, filePath);
 
     }
 
}

效果如下:

wKiom1cLpDrgbwPYAACSvaW747Q984.png


五 回退流

回退流,顾名思义,可以把读取出来的某些数据重新退回到输入流的缓冲区中

需要用到的API是:PushbackInputStream,示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package  javase.io;
 
import  java.io.ByteArrayInputStream;
import  java.io.IOException;
import  java.io.PushbackInputStream;
 
public  class  PushInputStreamDemo {
 
     public  static  void  main(String[] args)  throws  IOException {
         String str =  "http://www.zifangsky.cn" ;
         // 内存输入流
         ByteArrayInputStream bArrayInputStream =  new  ByteArrayInputStream(
                 str.getBytes());
         // 回退流
         PushbackInputStream push =  new  PushbackInputStream(bArrayInputStream);
         System.out.println( "读取的数据为:" );
         int  temp =  0 ;
         while  ((temp = push.read()) != - 1 ) {
             if  (temp ==  '.' ) {
                 push.unread(temp);  // 回退到缓冲区
                 push.read();  // 重新读取,不要直接丢弃
                 System.out.print( "(退回"  + ( char ) temp +  ")" );
             else
                 System.out.print(( char ) temp);
         }
         push.close();
         bArrayInputStream.close();
     }
 
}

输出:

1
2
读取的数据为:
http://www(退回.)zifangsky(退回.)cn


本文转自 pangfc 51CTO博客,原文链接:http://blog.51cto.com/983836259/1762769,如需转载请自行联系原作者
相关文章
|
21天前
|
存储 Java 编译器
Java内存模型(JMM)深度解析####
本文深入探讨了Java内存模型(JMM)的工作原理,旨在帮助开发者理解多线程环境下并发编程的挑战与解决方案。通过剖析JVM如何管理线程间的数据可见性、原子性和有序性问题,本文将揭示synchronized关键字背后的机制,并介绍volatile关键字和final关键字在保证变量同步与不可变性方面的作用。同时,文章还将讨论现代Java并发工具类如java.util.concurrent包中的核心组件,以及它们如何简化高效并发程序的设计。无论你是初学者还是有经验的开发者,本文都将为你提供宝贵的见解,助你在Java并发编程领域更进一步。 ####
|
1月前
|
缓存 easyexcel Java
Java EasyExcel 导出报内存溢出如何解决
大家好,我是V哥。使用EasyExcel进行大数据量导出时容易导致内存溢出,特别是在导出百万级别的数据时。以下是V哥整理的解决该问题的一些常见方法,包括分批写入、设置合适的JVM内存、减少数据对象的复杂性、关闭自动列宽设置、使用Stream导出以及选择合适的数据导出工具。此外,还介绍了使用Apache POI的SXSSFWorkbook实现百万级别数据量的导出案例,帮助大家更好地应对大数据导出的挑战。欢迎一起讨论!
164 1
|
1月前
|
缓存 算法 Java
Java中的内存管理:理解与优化
【10月更文挑战第6天】 在Java编程中,内存管理是一个至关重要的主题。本文将深入探讨Java内存模型及其垃圾回收机制,并分享一些优化内存使用的策略和最佳实践。通过掌握这些知识,您可以提高Java应用的性能和稳定性。
48 4
|
1月前
|
存储 监控 算法
Java中的内存管理:理解Garbage Collection机制
本文将深入探讨Java编程语言中的内存管理,着重介绍垃圾回收(Garbage Collection, GC)机制。通过阐述GC的工作原理、常见算法及其在Java中的应用,帮助读者提高程序的性能和稳定性。我们将从基本原理出发,逐步深入到调优实践,为开发者提供一套系统的理解和优化Java应用中内存管理的方法。
|
2天前
|
Java
java内存区域
1)栈内存:保存所有的对象名称 2)堆内存:保存每个对象的具体属性 3)全局数据区:保存static类型的属性 4)全局代码区:保存所有的方法定义
8 1
|
16天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
36 6
|
20天前
|
存储 缓存 安全
Java内存模型(JMM):深入理解并发编程的基石####
【10月更文挑战第29天】 本文作为一篇技术性文章,旨在深入探讨Java内存模型(JMM)的核心概念、工作原理及其在并发编程中的应用。我们将从JMM的基本定义出发,逐步剖析其如何通过happens-before原则、volatile关键字、synchronized关键字等机制,解决多线程环境下的数据可见性、原子性和有序性问题。不同于常规摘要的简述方式,本摘要将直接概述文章的核心内容,为读者提供一个清晰的学习路径。 ####
35 2
|
21天前
|
存储 安全 Java
什么是 Java 的内存模型?
Java内存模型(Java Memory Model, JMM)是Java虚拟机(JVM)规范的一部分,它定义了一套规则,用于指导Java程序中变量的访问和内存交互方式。
50 1
|
1月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
70 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
27天前
|
存储 运维 Java
💻Java零基础:深入了解Java内存机制
【10月更文挑战第18天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
30 1
下一篇
无影云桌面