IO流:用于处理设备上的数据,即:InputStream,OutputStream
IO流的具体分类:
1,根据处理的数据类型不同分为:字节流与字符流
2,根据流的方向不同分为:输出流与输入流
字符流的由来:
因为文件的编码不同,而有了对字符进行高效操作的字符流对象
原理:其实就是基于字节流读取数据时,去查了 指定编码表
字节流与字符流的区别
1,字节流读取的 时候,读取一个字节就返回一个字节,
字符流使用了字节流读取到一个或多个字节流时,先去查指定的编码 表,将查到的字符返回
2,字节流能够读取所有的类型数据,而字符流只能处理字符类型
一.File
- 目录列表
假设我们想查看目录列表,可使用list()方法查看File对象下所有的目录,但是如果想查看类型为.java类的文件,那么我们就使用“目录过滤器”
package File;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.regex.Pattern;
public class DirList {
public static void main(String[] args) {
File file = new File(".");
String[] list;
list = file.list(new DirFilter(".*"));
Arrays.sort(list,String.CASE_INSENSITIVE_ORDER);
for(String str : list){
System.out.println(str);
}
}
}
package File;
import java.io.File;
import java.io.FilenameFilter;
import java.util.regex.Pattern;
public class DirFilter implements FilenameFilter{
private Pattern pattern;
public DirFilter(String filenName){
pattern = Pattern.compile(filenName);
}
@Override
public boolean accept(File dir, String name) {
return pattern.matcher(name).matches();
}
}
DirFilter 这个类存在的原因就是把accept() 方法提供给 list() 使用,使list()可以回调accept() 进而决定哪些文件包含在列表里 这就是策略模式的体现
list()方法会为此目录下的所有的方法都调用accept()方法,来判断此文件是否在内
- 目录的检查及创建
File 类不仅仅只代表存在的目录,也可以用File对象来创建不存在的目录,也可以用File查看文件的各种特性
输入流 InputStream
每一种数据源都有相应的InputStream子类,因为InputStream是个处于顶层的类,用来处理各种数据源的类都继承了InputStream类,我们来看看这些类:
ByteArrayInputStream:处理字节数组的类,允许将内存的缓冲区当做InputStream使用。
StringBufferInputStream:将String转换成InputStream,内部实现用的是StringBuffer。
FileInputStream:从文件中读取数据。
PipedInputStream:用于从管道中读取数据。
SequenceInputStream:将多个流对象转化成一个InputStream。
FilterInputStream:装饰器类,为其它InputStream类提供功能。
- 读取文件内容
package InputStream;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedInputFile2 {
public static String read(String fileName) throws IOException{
BufferedReader br = new BufferedReader(new FileReader(fileName));
StringBuilder sb = new StringBuilder();
String s = "";
while((s = br.readLine())!=null){
sb.append(s+"\n");
}
if(br!=null){
br.close();
}
return sb.toString();
}
public static void main(String[] args) {
try {
System.out.println(read("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
* DataInputStream类
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class DataOutputStreamDemo{
public static void main(String[] args) throws IOException{
File file = new File("d:" + File.separator +"hello.txt");
DataInputStream input = new DataInputStream(new FileInputStream(file));
char[] ch = new char[10];
int count = 0;
char temp;
while((temp = input.readChar()) != 'C'){
ch[count++] = temp;
}
System.out.println(ch);
}
}
输出流 OutputStream
OutputStream 是所有的输出字节流的父类,它是一个抽象类。
ByteArrayOutputStream、FileOutputStream是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,
ObjectOutputStream 和所有FilterOutputStream的子类都是装饰流。具体例子跟InputStream是对应的。
- 文件复制
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
if(args.length!=2){
System.out.println("命令行参数输入有误,请检查");
System.exit(1);
}
File file1=new File(args[0]);
File file2=new File(args[1]);
if(!file1.exists()){
System.out.println("被复制的文件不存在");
System.exit(1);
}
InputStream input=new FileInputStream(file1);
OutputStream output=new FileOutputStream(file2);
if((input!=null)&&(output!=null)){
int temp=0;
while((temp=input.read())!=(-1)){
output.write(temp);
}
}
input.close();
output.close();
}
}
* DataOutputStream
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamDemo{
public static void main(String[] args) throws IOException{
File file = new File("d:" + File.separator +"hello.txt");
char[] ch = { 'A', 'B', 'C' };
DataOutputStream out = null;
out = new DataOutputStream(new FileOutputStream(file));
for(char temp : ch){
out.writeChar(temp);
}
out.close();
}
}
添加属性和有用的接口
java IO 类库需要多种不同功能的组合,这正是使用装饰器模式的理由所在
这也是java IO类库里存在filter(过滤器)的原因所在,抽象类filter是所有装饰器的基类。装饰器类必须和它所装饰的类具有相同的接口,但它也可以扩展
装饰器在给我们提供许多灵活性的时候也给我们带来了复杂性,我们必须创建许多类 才能得到我们需要的单个的IO对象
Reader 和 Writer
Reader 是所有的输入字符流的父类,它是一个抽象类。
Writer 是所有的输出字符流的父类,它是一个抽象类
设计Reader和Writer主要是为了国际化,老的IO流仅支持8位的字节流,不能很好的支持16位的,所以添加Reader和Writer就是为了所有的IO操作中能很好地 支持Unicode
InputStreamReader 可以把 InputStream 转化为 Reader
OutoutStreamWrite 可以把OutputStream转化为Write
- 从文件中读取数据
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
char[] ch=new char[100];
Reader read=new FileReader(f);
int temp=0;
int count=0;
while((temp=read.read())!=(-1)){
ch[count++]=(char)temp;
}
read.close();
System.out.println("内容为"+new String(ch,0,count));
}
}
- BufferedReader
注意:BufferedReader只能接受字符流的缓冲区,因为每一个中文需要占据两个字节,所以需要将System.in这个字节输入流变为字符输入流
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BufferedReaderDemo{
public static void main(String[] args){
BufferedReader buf = new BufferedReader(
newInputStreamReader(System.in));
String str = null;
System.out.println("请输入内容");
try{
str = buf.readLine();
}catch(IOException e){
e.printStackTrace();
}
System.out.println("你输入的内容是:" + str);
}
}
字节流与字符流的转换
InputStreamReader:字节到字符的桥梁
OutputStreamWriter:字符到字节的桥梁
这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。
//将字节输出流转化为字符输出流
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "d:"+File.separator+"hello.txt";
File file=new File(fileName);
Writer out=new OutputStreamWriter(new FileOutputStream(file));
out.write("hello");
out.close();
}
//将字节输入流变为字符输入流
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "d:"+File.separator+"hello.txt";
File file=new File(fileName);
Reader read=new InputStreamReader(new FileInputStream(file));
char[] b=new char[100];
int len=read.read(b);
System.out.println(new String(b,0,len));
read.close();
}
}
标准IO流
标准IO模型,java提供了System.in,System.out,System.err
其中System.err和System.out都已报装成了PrintStream 但是System.in
却是一个未被报装过的InputStream,所以在System.in之前要对其进行包装
package OutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Echo {
public static void main(String[] args) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String c = "";
try {
while((c=reader.readLine())!=null&&c.length()!=0){
System.out.println(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 将System.out 转换为PrintWrite
System.out 是一个PrintStream 而PrintStream 是一个OutputStream 而PrintWrite有一个可以接受OutputStream 参数的构造器
PrintWriter out = new PrintWriter(System.out,true);
out.println("hello ");
压缩
- 利用GZIP进行简单的压缩
GZIP接口非常的简单,如果要对单个的数据流进行压缩,GZIP就很合适
package zip;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class GIZPcomress {
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(
new FileReader(
"E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
BufferedOutputStream os = new BufferedOutputStream(
new GZIPOutputStream(
new FileOutputStream(
"E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile4.java")));
System.out.println("write file");
int c;
while ((c = br.read()) != -1) {
os.write(c);
}
br.close();
os.close();
System.out.println("read file");
BufferedReader br2 = new BufferedReader(
new InputStreamReader(
new GZIPInputStream(
new FileInputStream(
"E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile4.java"))));
String s = "";
while ((s = br2.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- 用zip 进行压缩 解压
package zip;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
//压缩
public class ZipCompress {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile5.zip");
CheckedOutputStream cs = new CheckedOutputStream(fos, new Adler32());
ZipOutputStream zs = new ZipOutputStream(fos);
BufferedOutputStream bos = new BufferedOutputStream(zs);
zs.setComment("this is zip file");
System.out.println("开始压缩");
BufferedReader reader = new BufferedReader(new FileReader("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
zs.putNextEntry(new ZipEntry("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
int s = 0;
while((s=reader.read())!=-1){
bos.write(s);
}
bos.close();
System.out.println("checkNum:"+cs.getChecksum().getValue());
System.out.println("开始读文件");
FileInputStream fis = new FileInputStream("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile5.zip");
CheckedInputStream cis = new CheckedInputStream(fis, new Adler32());
ZipInputStream zi = new ZipInputStream(fis);
BufferedInputStream bis = new BufferedInputStream(zi);
ZipEntry zn = null;
while((zn = zi.getNextEntry())!=null){
System.out.println("this file:"+zn);
int n = 0;
while((n = bis.read())!=-1){
System.out.write(n);
}
}
System.out.println("checkNum:"+cs.getChecksum().getValue());
} catch (Exception e) {
e.printStackTrace();
}
}
}
序列化
Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在将来重新读取被保存的对象。Java对象序列化就能够帮助我们实现该功能。java 的对象的序列化将那些实现了Serializable接口的对象转换成字节序列,并且能够在以后将字节序列恢复为原来的对象
什么时候用序列化:
a)当你想把的内存中的对象保存到一个文件中或者数据库中时候;
b)当你想用套接字在网络上传送对象的时候;
c)当你想通过RMI传输对象的时候;
package Serializable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class A {
private static int i = 10;
private transient static String s = "java";
public static void main(String[] args) {
try {
User user = new User();
user.setSex('男');
user.setUsername("小李");
user.setUserpass("123");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.out"));
oos.writeObject(user);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.out"));
User user2 = (User)ois.readObject();
//String ss = ois.readUTF();
//System.out.println(ss);
System.out.println(user2.getUsername());
System.out.println(user2.getSex());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
- 序列化的控制
有时候我们不想整个对象都序列化,只需要对象的一部分序列化,此时就应该用到:Externalizable
Externalizable 是一个接口 需要实现两个方法writeExternal(),readExternal()
package Serializable;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class Bilp1 implements Externalizable{
private User user;
public Bilp1(){
System.out.println("Bilp1()");
}
public Bilp1(User user){
this.user = user;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
// TODO Auto-generated method stub
//out.writeObject(user);
System.out.println("writeExternal()");
}
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
// TODO Auto-generated method stub
System.out.println("readExternal()");
}
}
- transient关键字
当某个字段被声明为transient后,默认序列化机制就会忽略该字段。此处将User类中的username字段声明为transient
private transient String username;