Java中的IO流(五)
上一篇《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流(五)的更多相关文章
- Java中的IO流(六)
上一篇<Java中的IO流(五)>把流中的打印流PrintStream,PrintWriter,序列流SequenceInputStream以及结合之前所记录的知识点完成了文件的切割与文件 ...
- Java中的IO流(四)
上一篇<Java中的IO流(三)>把IO流中的文件及目录操作的对象File类记录了一下,本篇把本不属性IO流但又和IO流有关系的一个对象作一下记录,此对象本属于集合框架里的一个子集,即Pr ...
- Java中的IO流(三)
上一篇<Java中的IO流(二)>把学习Java的字符流以及转换流作了一下记录,从本篇开始将把IO流中对文件或文件夹操作的对象File类的学习进行一下记录. 一,File类的构造函数及字段 ...
- Java中的IO流(二)
上一篇<Java中的IO流(一)>把学习IO流的字符流作了一下记录,本篇把字节流记录一下. 一,Java中的字节流 Java中的字节流的操作方式与字符流的操作方式大致相同,连方法名都是类似 ...
- java中的IO流
Java中的IO流 在之前的时候我已经接触过C#中的IO流,也就是说集中数据固化的方式之一,那么我们今天来说一下java中的IO流. 首先,我们学习IO流就是要对文件或目录进行一系列的操作,那么怎样操 ...
- Java中的IO流总结
Java中的IO流总结 1. 流的继承关系,以及字节流和字符流. 2. 节点流FileOutputStream和FileInputStream和处理流BufferedInputStream和Buffe ...
- Java中的IO流大体介绍
由于Java中的IO流是在是知识点繁多,所以我大约花了1周的时间将其整理起来.但是整理起来后并不是将完事了,我还是要分字节流和字符流来讲述.然后字节流和字符流中还有是否带有缓冲流. 讲述完IO流后我将 ...
- Java中的IO流,Input和Output的用法,字节流和字符流的区别
Java中的IO流:就是内存与设备之间的输入和输出操作就成为IO操作,也就是IO流.内存中的数据持久化到设备上-------->输出(Output).把 硬盘上的数据读取到内存中,这种操作 成为 ...
- JAVA 中的IO流
Java中的IO流是用来处理设备与设备之前的数据传输,在java中以流的形式传输.流分为两类:字节流和字符流. 字节流:InputStream,OutPutSteam.(计算机内的数据都是以字节存储的 ...
随机推荐
- 【转载】MySQL数据库可以用任意ip连接访问的方法
通过CMD命令行修改数据库表的一个字段的值,实现连接,访问. 第一步.找到MYSQL软件安装所在的bin目录: (1)cd\当前目录 (2)指定MYSQL安装的bin目录 (3)输入 -h local ...
- 关于AJAX的一些事
在JQ中运用AJAX的操作是很舒服的一件事,一直以来我对他都有个错误的认识,直到遇见了问题才把他研究个透彻. 下面贴出两种AJAX的写法,当然都是正确的. 其一: $.ajax({ type: 'po ...
- Monkey测试运用实例
测试命令是多样性的,根据个人的测试思路,设计执行你想要的测试命令 1.monkey -p com.junte -v 1000 团贷网模拟用户随机操作,无延时点击1000次 -p测试包 ...
- js重名的处理
### 关于重名的处理 > 在变量提升阶段,如果名字重复了,不会重新的进行声明,但是会重新的进行定义(后面赋的值会把前面赋的值给替换掉) ```javascript //=>变量提升:fn ...
- C#使用yield关键字构建迭代器
http://www.cnblogs.com/Huaran1chendu/p/4838536.html 以前,如果我们希望构建支持foreach枚举的自定义集合,只能实现IEnumerable接口(可 ...
- CentOS随笔 - 1.虚拟机VMware安装CentOS7系统
前言 转帖请注明出处: http://www.cnblogs.com/Troy-Lv5/ 需要安装CentOS首先你得下载安装镜像文件(地址: https://www.centos.org/downl ...
- Java学习---Java面试基础考核·
Java中sleep和wait的区别 ① 这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类. sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线 ...
- 企业级NGINX的重定向rewrite
vim /usr/local/nginx/conf/nginx.conf server { listen 80; server_name www.ftl.com; rewrite ^/(.*) htt ...
- 沉淀再出发:java的文件读写
沉淀再出发:java的文件读写 一.前言 对于java的文件读写是我们必须使用的一项基本技能,因此了解其中的原理,字节流和字符流的本质有着重要的意义. 二.java中的I/O操作 2.1.文件读写的本 ...
- [EffectiveC++]item03:尽可能使用const 并且转载一篇关于const函数的博客
速度 #include <iostream> using namespace std; class TextBlock { private: string text; public: Te ...