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,如需转载请自行联系原作者
相关文章
|
1天前
|
存储 Java 测试技术
滚雪球学Java(18):解密JavaSE中的堆栈:你真的了解Java内存吗?
【4月更文挑战第7天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
43 1
滚雪球学Java(18):解密JavaSE中的堆栈:你真的了解Java内存吗?
|
1天前
|
存储 Java 编译器
Java内存区域详解
Java内存区域详解
31 0
Java内存区域详解
|
1天前
|
存储 缓存 Java
优化Java代码中的内存使用:使用WeakHashMap解决内存泄漏问题
在Java应用程序中,内存泄漏是一个常见的问题,尤其是在处理大量对象时。本文将介绍如何使用WeakHashMap数据结构来解决内存泄漏问题,通过示例代码演示其在实际项目中的应用,从而提高Java代码的性能和可靠性。
|
1天前
|
存储 Java
深入理解Java虚拟机:JVM内存模型
【4月更文挑战第30天】本文将详细解析Java虚拟机(JVM)的内存模型,包括堆、栈、方法区等部分,并探讨它们在Java程序运行过程中的作用。通过对JVM内存模型的深入理解,可以帮助我们更好地编写高效的Java代码,避免内存溢出等问题。
|
1天前
|
算法 Java Go
Go vs Java:内存管理与垃圾回收机制对比
对比了Go和Java的内存管理与垃圾回收机制。Java依赖JVM自动管理内存,使用堆栈内存并采用多种垃圾回收算法,如标记-清除和分代收集。Go则提供更多的手动控制,内存分配与释放由分配器和垃圾回收器协同完成,使用三色标记算法并发回收。示例展示了Java中对象自动创建和销毁,而Go中开发者需注意内存泄漏。选择语言应根据项目需求和技术栈来决定。
|
1天前
|
缓存 Java
Java中循环创建String对象的内存管理分析
Java中循环创建String对象的内存管理分析
29 2
|
1天前
|
存储 算法 Java
了解Java内存管理与垃圾回收机制
了解Java内存管理与垃圾回收机制
8 0
|
1天前
|
存储 机器学习/深度学习 Java
【Java探索之旅】数组使用 初探JVM内存布局
【Java探索之旅】数组使用 初探JVM内存布局
27 0
|
1天前
|
Java 开发者
【JAVA】Java内存模型中的happen-before
Happen-before关系帮助开发者理解多线程程序中操作的执行顺序和可见性,从而避免竞态条件和数据不一致性问题。它提供了一种可预测的规则来确保线程之间的正确交互。
26 0
|
1天前
|
存储 缓存 安全
深入理解Java内存模型及其作用
深入理解Java内存模型及其作用