上一篇《Java中的IO流(四)》记录了一下Properties类,此类不属于IO流,它属于集合框架。接下来说一下IO流中的其它流

一,打印流PrintStream

  PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。并且此注永远不会抛出IOException。

  此流的构造函数大致分三类

    1,接收File文件类型的

    2,接收OutputStream类型的

    3,接收文件名形式的

  下演示一下此流的两个方法

     private static void function_demo1() throws IOException {
PrintStream ps = new PrintStream("print.txt");
ps.write(97);
ps.println();
ps.print(97);
}

  运行结果 :

    a

    97

  注:PrintStream的write方法继承自父类,此方法的说明是向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。所以我们看到的第一行输出转为了”a“;而print方法是直接把参数调用String的ValueOf方法转为字符串直接输出的,所以若想把一个数据的直接表现形式则用print方法。

二,打印流PrintWriter

  向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream 中的所有 print 方法。

  此类的构造函数大致分为四类

    1,接收File文件类型

    2,接收OutputStream类型

    3,接收文件名形式

    4,接收Writer类型

  此类有构造函数接收第二个参数类型为boolean类型的,若传为true则可将数据自动flush到流中

  演示如下:

     private static void function_demo2() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(System.out);
String line = null;
while ((line = reader.readLine()) != null) {
if (line.equals("over")) {
break;
} else {
writer.println(line.toUpperCase());
}
}
writer.close();
reader.close();
}

  注:以上代码在演示的时候每次输入完后并不会立刻输入到控制台,当在第九行后加writer.flush();时每次输入完后即可把相应信息打印到控制台,但printwriter类提供了自动刷新的方法就是用两个参数的构造函数,演示如下

     private static void function_demo2() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(System.out, true);
String line = null;
while ((line = reader.readLine()) != null) {
if (line.equals("over")) {
break;
} else {
writer.println(line.toUpperCase());
}
}
writer.close();
reader.close();
}
  注意以上代码的第三行,用了两个参数的构造函数
  当需要直接把信息输出到文件中的时候,并且想要每次输入完成后立即把信息输出到文件中,演示如下

     private static void function_demo2() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(new FileWriter("writer.txt"), true);
String line = null;
while ((line = reader.readLine()) != null) {
if (line.equals("over")) {
break;
} else {
writer.println(line.toUpperCase());
}
}
writer.close();
reader.close();
}

三,序列流SequenceInputStream

  表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

  此流相当于是一个集合,把若干个流放入到此集合,然后一个流接着一个流的读取,当完第一个判断此集合里是否还有其它流,若有接着读取,读到最后一个返回-1。

  此流有两个构造函数,一个是接收两个InputStream类型的参数,即接收两个流,若想读取多个流,则用接收Enumeration类型的参数。

  接下来我们用一个需求把此流演示一下,需求是把三个txt文档合并为一个文档

     private static void function_demo3() throws IOException {
Vector<InputStream> v = new Vector<InputStream>();// 定义Vector集合用于存储所有的流
v.add(new FileInputStream("1.txt"));
v.add(new FileInputStream("2.txt"));
v.add(new FileInputStream("3.txt"));
Enumeration<InputStream> enu = v.elements();// 因为SequenceInputStream接收的是Enumeration类型的参数,所以用Vector集合
SequenceInputStream sis = new SequenceInputStream(enu);
OutputStream out = new FileOutputStream("4.txt");
byte[] bt = new byte[1024];
int len = 0;
while ((len = sis.read(bt)) != -1) {
out.write(bt, 0, len);
}
out.close();
sis.close();// 序列流的关闭会把其中的所有的流都关闭
}

  大家都知道,Vector对象效率太低,开发中一般会用ArrayList,那么接下来就把Vector换成ArrayList,演示如下

     private static void function_demo3() throws IOException {
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();// 定义ArrayList集合接所有的流
al.add(new FileInputStream("1.txt"));
al.add(new FileInputStream("2.txt"));
al.add(new FileInputStream("3.txt"));
Iterator<FileInputStream> it = al.iterator();// 获取一个Iterator对象
// 没有枚举对象就new一个出来,然后重写里面的两个方法返回iterator对象的hasNext和next方法
Enumeration<FileInputStream> enumeration = new Enumeration<FileInputStream>() {
@Override
public boolean hasMoreElements() {
return it.hasNext();
} @Override
public FileInputStream nextElement() {
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(enumeration);
OutputStream out = new FileOutputStream("4.txt");
byte[] bt = new byte[1024];
int len = 0;
while ((len = sis.read(bt)) != -1) {
out.write(bt, 0, len);
}
out.close();
sis.close();// 序列流的关闭会把其中的所有的流都关闭
}

  看起来很麻烦的样子,有没有办法简化一下呢?Collections集合类里为我们提供了一个获取Enumeration的工具,演示如下:

   private static void function_demo3() throws IOException {
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();// 定义ArrayList集合接所有的流
al.add(new FileInputStream("1.txt"));
al.add(new FileInputStream("2.txt"));
al.add(new FileInputStream("3.txt"));
Iterator<FileInputStream> it = al.iterator();// 获取一个Iterator对象
Enumeration<FileInputStream> enumeration = java.util.Collections.enumeration(al);
SequenceInputStream sis = new SequenceInputStream(enumeration);
OutputStream out = new FileOutputStream("4.txt");
byte[] bt = new byte[1024];
int len = 0;
while ((len = sis.read(bt)) != -1) {
out.write(bt, 0, len);
}
out.close();
sis.close();// 序列流的关闭会把其中的所有的流都关闭
}

四,文件切割及合并

  把一个大的文件切割成若干个小的文件,方便文件上传的时候对大小的限制,实现代码如下

     private static final int SIZE = 1024 * 1024;

     private static void function_demo4() throws IOException {
File dir = new File("c:\\");
File file = new File(dir, "1.bmp");// 需要分隔的源文件
FileInputStream inputStream = new FileInputStream(file);// 字节流对象
byte[] bt = new byte[SIZE];// 缓冲数组,大小由常量固定
// 由于需要分隔文件,所以此处不能实例化输出流对象,需要在读取的时候每读取一次实例化一个输出流对象
FileOutputStream outputStream = null;
File dest = null;// 由于切割文件,每个被切割出来的文件名称不同,所以此处File不能实例化,需要在每切割出来一个文件则实例化一个File对象
int len;
int i = 0;// 为切割出来的每个文件名添加序列
while ((len = inputStream.read(bt)) != -1) {
i++;
dest = new File(dir, "\\temp\\" + i + ".part");//切割出来的文件对象
outputStream = new FileOutputStream(dest);//实例化每个输出流对象
outputStream.write(bt, 0, len);//读取每个切割出来的文件
outputStream.close();//关闭每个读取流对象
}
inputStream.close();//关闭输入流对象
}

  把切割后的文件合并为一个文件,实现代码如下

     private static void function_demo5() throws IOException {
File dir = new File("C:\\temp");//源目录对象
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();//存储输入流的集合对象
FileInputStream inputStream = null;//根据源文件的个数实例化输入流对象,因需要循环源文件数量,所以此处实例为null
File file = null;//源文件名字不一样,所以此处实例化为null
for (int i = 1; i < 4; i++) {
file = new File(dir, i + ".part");//源文件名
inputStream = new FileInputStream(file);//封装输入流对象
al.add(inputStream);//将输入流对象添加到流集合对象中
}
Enumeration<FileInputStream> enu = java.util.Collections.enumeration(al);//从输入流集合对象中获取Enumeration对象以便传给序列流SequenceInputStream
SequenceInputStream sis = new SequenceInputStream(enu);//封装序列流对象
BufferedInputStream bis = new BufferedInputStream(sis);//缓冲输入流对象
File dest = new File(dir, "4.bmp");//封装合并全的文件名及路径
FileOutputStream outputStream = new FileOutputStream(dest);//输出流对象
BufferedOutputStream bos = new BufferedOutputStream(outputStream);//输出缓冲对象
//以下代码是循环读取及写入流对象,关闭流
int len;
while ((len = bis.read()) != -1) {
bos.write(len);
}
bos.close();
bis.close();
}

五,完整的文件切割与合并

  由上面的例子大家可以考虑几个问题

    1,被切割后的文件数量在合并的时候并不知道

    2,源文件的文件扩展名在合并的时候并不知道

  鉴于这两点,在切割文件的时候应当把这两个信息写入到配置文件中,在合并文件的时候先读取配置文件中的信息然后检验配置文件中的信息和切割后的文件信息是否一致,若一致再进行合并操作,具体操作演示如下

     private static final int SIZE = 1024 * 1024;

     private static void function_demo6() throws IOException {
File dir = new File("c:\\");
File file = new File(dir, "1.bmp");// 需要分隔的源文件
FileInputStream inputStream = new FileInputStream(file);// 字节流对象
byte[] bt = new byte[SIZE];// 缓冲数组,大小由常量固定
// 由于需要分隔文件,所以此处不能实例化输出流对象,需要在读取的时候每读取一次实例化一个输出流对象
FileOutputStream outputStream = null;
File dest = null;// 由于切割文件,每个被切割出来的文件名称不同,所以此处File不能实例化,需要在每切割出来一个文件则实例化一个File对象
int len;
int i = 0;// 为切割出来的每个文件名添加序列
while ((len = inputStream.read(bt)) != -1) {
i++;
dest = new File(dir, "\\temp\\" + i + ".part");// 切割出来的文件对象
outputStream = new FileOutputStream(dest);// 实例化每个输出流对象
outputStream.write(bt, 0, len);// 读取每个切割出来的文件
outputStream.close();// 关闭每个读取流对象
}
inputStream.close();// 关闭输入流对象
String fileName = file.getName();// 获取源文件名
File fileCountFilter = new File("C:\\temp");// 被切割的文件的存放目录
String[] fileCountArray = fileCountFilter.list(new PartFileNameFilter(".part"));// 过滤被切割的文件
int count = fileCountArray.length;// 被切割的文件数量
Properties prop = new Properties();// 把切割的文件信息存储到配置文件中
prop.setProperty("fileName", fileName);// 源文件名
prop.setProperty("count", String.valueOf(count));// 被切割出来的文件数量
Writer writer = new FileWriter("C:\\temp\\config.properties");
prop.store(writer, "cut file info");
}
     private static void function_demo7() throws IOException {
File dir = new File("C:\\temp");// 源目录对象
String[] partFileArray = dir.list(new PartFileNameFilter(".part"));
int partFileCount = partFileArray.length;// 获取源目录中被切割的文件数量
File[] propertiesFile = dir.listFiles(new PartFileNameFilter(".properties"));// 过滤配置文件
String fileName = null;
int cutFileCount = 0;
if (propertiesFile.length != 1) {// 若切割文件配置文件不唯一则抛出异常
throw new RuntimeException("切割文件的配置信息没有或多于一个,无法完成文件合并");
} else {// 否则读取配置文件信息
Properties prop = new Properties();
prop.load(new FileReader(propertiesFile[0]));
fileName = prop.getProperty("fileName");// 获取配置文件中的源文件名
cutFileCount = Integer.parseInt(prop.getProperty("count"));// 获取配置文件中被切割后的文件数量
if (partFileCount != cutFileCount) {// 若读取到的配置文件中的文件数与源目录中被切割的文件数量不一样,则抛出异常
throw new RuntimeException("文件不全,无法进行文件合并");
}
}
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();// 存储输入流的集合对象
FileInputStream inputStream = null;// 根据源文件的个数实例化输入流对象,因需要循环源文件数量,所以此处实例为null
File file = null;// 源文件名字不一样,所以此处实例化为null
for (int i = 1; i <= cutFileCount; i++) {
file = new File(dir, i + ".part");// 源文件名
inputStream = new FileInputStream(file);// 封装输入流对象
al.add(inputStream);// 将输入流对象添加到流集合对象中
}
Enumeration<FileInputStream> enu = java.util.Collections.enumeration(al);// 从输入流集合对象中获取Enumeration对象以便传给序列流SequenceInputStream
SequenceInputStream sis = new SequenceInputStream(enu);// 封装序列流对象
BufferedInputStream bis = new BufferedInputStream(sis);// 缓冲输入流对象
File dest = new File(dir, fileName);// 封装合并全的文件名及路径
FileOutputStream outputStream = new FileOutputStream(dest);// 输出流对象
BufferedOutputStream bos = new BufferedOutputStream(outputStream);// 输出缓冲对象
// 以下代码是循环读取及写入流对象,关闭流
int len;
while ((len = bis.read()) != -1) {
bos.write(len);
}
bos.close();
bis.close();
}

  

 

Java中的IO流(五)的更多相关文章

  1. Java中的IO流(六)

    上一篇<Java中的IO流(五)>把流中的打印流PrintStream,PrintWriter,序列流SequenceInputStream以及结合之前所记录的知识点完成了文件的切割与文件 ...

  2. Java中的IO流(四)

    上一篇<Java中的IO流(三)>把IO流中的文件及目录操作的对象File类记录了一下,本篇把本不属性IO流但又和IO流有关系的一个对象作一下记录,此对象本属于集合框架里的一个子集,即Pr ...

  3. Java中的IO流(三)

    上一篇<Java中的IO流(二)>把学习Java的字符流以及转换流作了一下记录,从本篇开始将把IO流中对文件或文件夹操作的对象File类的学习进行一下记录. 一,File类的构造函数及字段 ...

  4. Java中的IO流(二)

    上一篇<Java中的IO流(一)>把学习IO流的字符流作了一下记录,本篇把字节流记录一下. 一,Java中的字节流 Java中的字节流的操作方式与字符流的操作方式大致相同,连方法名都是类似 ...

  5. java中的IO流

    Java中的IO流 在之前的时候我已经接触过C#中的IO流,也就是说集中数据固化的方式之一,那么我们今天来说一下java中的IO流. 首先,我们学习IO流就是要对文件或目录进行一系列的操作,那么怎样操 ...

  6. Java中的IO流总结

    Java中的IO流总结 1. 流的继承关系,以及字节流和字符流. 2. 节点流FileOutputStream和FileInputStream和处理流BufferedInputStream和Buffe ...

  7. Java中的IO流大体介绍

    由于Java中的IO流是在是知识点繁多,所以我大约花了1周的时间将其整理起来.但是整理起来后并不是将完事了,我还是要分字节流和字符流来讲述.然后字节流和字符流中还有是否带有缓冲流. 讲述完IO流后我将 ...

  8. Java中的IO流,Input和Output的用法,字节流和字符流的区别

    Java中的IO流:就是内存与设备之间的输入和输出操作就成为IO操作,也就是IO流.内存中的数据持久化到设备上-------->输出(Output).把 硬盘上的数据读取到内存中,这种操作 成为 ...

  9. JAVA 中的IO流

    Java中的IO流是用来处理设备与设备之前的数据传输,在java中以流的形式传输.流分为两类:字节流和字符流. 字节流:InputStream,OutPutSteam.(计算机内的数据都是以字节存储的 ...

随机推荐

  1. BZOJP1096[ZJOI2007]仓库建设——solution

    Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天, ...

  2. The memory graph Shared by the method

    Phone类 package com.itheima_03; /* * 手机类 */ public class Phone { String brand; int price; String colo ...

  3. web测试流程的总结及关注点

    项目的测试流程大只包含的几个阶段:立项.需求评审.用例评审.测试执行.测试报告文档 一.立项后测试需要拿到的文档 1.需求说明书 2.原型图(及UI图) 3.接口文档 4.数据库字典(表的数量.缓存机 ...

  4. spring boot(8)-mybatis三种动态sql

    脚本sql XML配置方式的动态SQL我就不讲了,有兴趣可以自己了解,下面是用<script>的方式把它照搬过来,用注解来实现.适用于xml配置转换到注解配置 @Select(" ...

  5. sqldataAdapter/dataset/datatable的使用

    public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Loa ...

  6. 提示"libc.so.6: version `GLIBC_2.14' not found"

    启动php 提示"libc.so.6: version `GLIBC_2.14' not found",原因可能是glibc版本太低,php使用了较高的glibc版本引起的 1,首 ...

  7. Ubuntu-18.04下安装mysql

    安装mysql服务器 1. sudo apt-get install mysql-server 2. sudo apt-get install mysql-client 登录问题 安装成功后,我们会发 ...

  8. Perl常用语法

    本文主要为了方便阅读.编写perl脚本而记录的常用的命令.语法. 一.条件判断语法 注意,数字 0, 字符串 '0' . "" , 空 list () , 和 undef 为 fa ...

  9. 译文 [ROM][多国语言][2015.06.11] Lenovo S750 (MTK6589) - andrea_d86-lenovos750-4.2.2

    ************************************************** andrea_d86-lenovos750-4.2.2-150530 ************** ...

  10. 如何写自定义的AlertView

    如何写自定义的AlertView 效果 说明 考虑到后面的可定制性以及可维护性,本人用AbstractAlertView定义了AlertView抽象的基类,实现通过子类来完成. 注:这只是粗略的写了一 ...