第六节 IO流
- 一、IO流概述
- 二、管道流
- 三、编码表:
- 四、其它:
一、IO流概述
- IO流:对数据进行持久化的存储。(Input Output输入输出流。)
注:C++等语言中也有对数据的输入输出。
- 字节输入流:读取文件(InputStream)。
例1:
import java.io.*; //导入IO流的包,*号表示遍历IO下所有包以供使用
public class Exam01 {
public static void main(String[] args) throws IOException{ //IO流需要异常处理
// 创建一个文件字节输入流
FileInputStream in = new FileInputStream("test.txt"); //java文件夹需有此名的txt文件
int b = 0; // 定义一个int类型的变量b。记住每次读取的一个字节
// while ( (b = in.read() ) != -1){
// // 变量b记住读取的一个字节。如果读取的字节为-1时,跳出while循环,输出
// System.out.print((char)b); // 将b写出,数字、英文正常
// } //这种方法虽然也能输出,但文字这种两个字节的字符会分成一个解析(文字乱码)
byte[] byt = new byte[1024];//字节缓冲流用法,以数组形式让数据积累一定字节,再继续传递
// int b = 0;
while ((b = in.read()) != -1){
System.out.print(new String(byt,0,b)); // 将b写出,汉字也正常
} //使用数组进行处理后(长度将会足够),文字虽然仍分成两个字节解析,但之后会将解析合并回汉字字符
in.close(); //结束,释放资源
}
}
// 注:文本足够大,数组定义不够时,仍会出现乱码问题,此时需要别的方法(流)解决。
- 字节输出流:写入文件(OutputStream)。
例2:
import java.io.*; //导入IO流的包,*号表示遍历IO下所有包以供使用
public class Exam02 {
public static void main(String[] args) throws IOException{ //IO流需要异常处理
// 创建一个文件字节输入流
FileOutputStream on = new FileOutputStream("test.txt"); //java文件夹需有此名的txt文件
on.write(97); //向test.txt写入97这个字符——该字符代表编码位为a,所以添加a。
// Byte[] bys = "abcd" .getBytes(); //abcd转换类型Byte
// on.write(bys);
// on.write(bys,0,2); //从第一个开始(0角标,代表1),写入2个字节
}
in.close(); //结束,释放资源
}
}
// 注:当文本足够大,数组定义不够时,仍会出现乱码问题,此时需要别的方法(流)解决。
- 字节输入输出流综合运用
例3:
import java.io.*;
public class Exam02 {
public static void main(String[] args) throws IOException {
// 将it文本中的数据传到on本文文件中
File src=new File("tempfile\\it.txt");
File dest=new File("tempfile\\on.txt");
FileInputStream fos=new FileInputStream(src);
FileOutputStream fis=new FileOutputStream(dest);
int ch=0;
while((ch=fos.read())!= -1){
fis.write(ch);
}
fos.close();
fis.close();
}
}
- 字节缓冲流:提高读取效率。(BufferedInputStream、BufferedOutputStream)
传递数据时,将数据放到一个数组中,再继续传递,而非一个数据一个数据传递。(略)
例如:
BufferedInputStream fis=new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream fos=new BufferedOutputStream(new FileOutputStream(des));
- 字符输入流:(Reader)
LineNumberReader(显示行号)
InputReader。 - 字符输出流:(Writer)
OutputReader。 - 序列化及反序列化:ObjectInputStream(序列化)、ObjectOutputStream(反序列化)。[略]
- DataOutputStream、DataInputStream:使基本数值原类型,保持不变。(基本类型数据保持字节原样性。)
- 输出方法:
ps.write(94); //写入最低字节
ps.print(94); //将数据转换为字符串再写入,保持数据值形式。
二、管道流
- PipedInputStream和PipeOutputStream:输入输出可直接连接,配合线程使用。
- ByteArrayInputStream和ByteArrayOutputStream:用于操作字节数据数组流对象,它们是对应设备为内存的流对象。(注:不用定义数组(缓冲区),其自带一个数组缓冲区。)
- CharArrayInputStream和CharArrayOnputStream:用于操作字符数据数组流对象,它们是对应设备为内存的流对象。(释:文本文件数据读取到字符数组缓冲区,然后再将数据从字符数组缓冲区读出。)
- SequenceInputStream:当文件个数、对象(碎片)过多时,会产生过多的调用,导致效率下降。因此需要该容器,将流对象和(碎片)文件关联存储到容器中,再遍历容器获取流对象及读写操作。
例4:
import java.io.*;
import java.util.*;
public class Exam04 {
public static void main(String[] args) throws IOException {
List<FileInputStream> list = new ArrayList<FileInputStream>();
for(int i=1;i<6;i++){
list.add(new FileInputStream("D:\\" + i + ".part"));
}
FileOutputStream fos = new FileOutputStream("D:\\0.mp3");
byte[] buf = new byte[1024 * 1024];
//遍历集合,获取流对象
for(FileInputStream fis : list){
int len = fis.read(buf);
fos.write(buf,0,len);
}
fos.close();
//关闭所有流
for(FileInputStream fis : list){
fis.close();
}
}
// public static void mergerFile(File partsDir) throws IOException{
// //使用IO包的SequenceInputStream,对碎片文件合并,将对个读取流合并成一个读取流。
// List<FileInputStream> list = new ArrayList<FileInputStream>();
//
// for(int i=1;i<6;i++){
// list.add(new FileInputStream(new File("D:\\" + i + ".part")));
// } //获取枚举对象?
// Enumeration<FileInputStream> en = Collections.enumeration(list);
// //源
// SequenceInputStream sis = new SequenceInputStream(en);
// //目的
// FileOutputStream fos = new FileOutputStream(new File(partsDir,"0.mp3"));
// //不断的读写
// byte[] buf= new byte[4096];
// int len = 0;
// for((len = sis.read(buf))!=-1){
// fos.write(buf,0,len);
// }
// fos.close();
// sis.close();
// }
}
- 遍历指定目录下文件:
例5:
import java.io.File;
public class Exam07 {
public static void main(String[] args) {
//获取指定目录下内部内容
File dir = new File("D:");
String[] names = dir.list();
for(String name : names){
// System.out.println(name);
}
//获取文件目录:
File[] files = dir.listFiles(); //获取当前文件夹文件对象
for(File file : files){
System.out.println(file.getName());
}
//删除文件目录:
File dir1 = new File("D:\\删除目录"); //该方法无法删除文件夹中有内容的。
//计算机删除可以实现是因为,计算机简化操作,找到最内部文件,由内而外进行删除。
boolean b1 = dir1.mkdirs(); //创建多级目录
System.out.println("b1="+b1);
}
}
- RandomAccessFile:封装很多字节流工具。[略]
三、编码表:
- ascii:一个字节中的7位就可以表示。对应字节为正数。
- iso8859-1:拉丁码表(欧洲),用一个字节的8位。
- GB2312:简体中文码表。有六七千中文和符号。两个字节表示;
GBK:常用中文码表,两万中文及符号。 - unicode:国际标准码表
- utf-8:基于unicode,一个字节就可以存储数据。更加标准化。
四、其它:
- flush:刷新资源,流还可以继续使用。close:关闭资源,流不可使用。
- InputStream、OutputStream、Reader、Writer都是抽象类,不能直接new。
- 实际操作中,字节流较为常用,但因生活中文本数据常见,因此常转为字符流操作,因而开发中常有汉字问题。
- 字节流、字符流两者之间通过 InputStreamReader,OutputStreamWriter来关联,实际上是通过byte[]和String关联。
- 但凡键盘录入:(使用)
BufferedInputStream fis=new BufferedInputStream(new FileInputStream(src));
End.