菜鸟学习笔记:Java IO流2——其他流
上一节讲解的是我们工作中常用的流,需要大家重点掌握,除此之外Java中还有一些流需要大家了解。
字节数组输入输出流
ByteArrayInputStream和ByteArrayOutputStream是字节数组的输入输出流,操作与正常输入输出流一致,只是接收的是一个字节数组,我们直接看代码:
public static void main(String[] args) throws IOException {
read(write());
}
public static byte[] write() throws IOException{
//目的地
byte[] dest;
//选择流不同点:输出流操作与文件输出流有些不同,有新增方法,不能使用多态
ByteArrayOutputStream bos =new ByteArrayOutputStream();
//操作 写出
String msg ="操作与 文件输入流操作一致";
byte[] info =msg.getBytes();
bos.write(info, 0, info.length);
//获取数据
dest =bos.toByteArray();
//释放资源
bos.close();
return dest;
}
public static void read(byte[] src) throws IOException{
//数据源传入
//选择流,传入的不再是文件对象,而是一个字符数组
InputStream is =new BufferedInputStream(
new ByteArrayInputStream(
src
)
);
//操作
byte[] flush =new byte[1024];
int len =0;
while(-1!=(len=is.read(flush))){
System.out.println(new String(flush,0,len));
}
//释放资源(可以不用)
is.close();
}
数据类型处理流
基本数据类型
DataInputStream和DataOutputStream为数据处理流,他们可以将固定类型的数据读出到文件中,也可以从文件中读取有相应类型的数据,同样直接看代码:
public static void write(String destPath) throws IOException{
double point =2.5;
long num=100L;
String str ="数据类型";
//创建源
File dest =new File(destPath);
//选择流 DataOutputStream
DataOutputStream dos =new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(dest)
)
);
//操作 写出的顺序 为读取准备
dos.writeDouble(point);
dos.writeLong(num);
dos.writeUTF(str);
dos.flush();
//释放资源
dos.close();
}
输出文件结果:
可以看到输出的文件是十六进制数,这个表示的是我们所选类型的数据,可以通过DataInputStream读取。
public static void read(String destPath) throws IOException{
//创建源
File src =new File(destPath);
//选择流
DataInputStream dis =new DataInputStream(
new BufferedInputStream(
new FileInputStream(src)
)
);
//操作 读取的顺序与写出一致 必须存在才能读取
//不一致,数据存在问题
long num2 =dis.readLong();
double num1 =dis.readDouble();
String str =dis.readUTF();
dis.close();
System.out.println(num2+"-->"+str);
}
程序结果:
引用类型
将引用类型数据(也就是对象)保存到文件中的过程叫做序列化,而将保存到文件中对象读取到程序中的过程称为反序列化。序列化和反序列化也是创建对象的一种方式(面试考点)。
对于序列化和反序列化有几点需要注意:
- 必须先序列化后反序列化,反序列化顺序必须与序列化一致。
- 只有实现了java.io.Serializable接口才能被序列化。序列化的类中使用triansient修饰的属性可以避免被序列化。
针对序列化和反序列化的问题Java提供了ObjectInputStream和ObjectOutputStream流来进行读写,接下来用代码来说明其过程:
我们先定义一个实现java.io.Serializable接口的类,在不需要序列化的属性前可以加上transient:
public class Employee implements java.io.Serializable {
//不需要序列化的属性
private transient String name;
private double salary;
public Employee() {
}
public Employee(String name, double salary) {
super();
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
然后对这个类进行序列化操作,操作过程与之前类似:
public static void seri(String destPath) throws IOException{
Employee emp =new Employee("张三",1000000);
int[] arr ={1,2,3,45};
//创建源
File dest =new File(destPath);
//选择流 ObjectOutputStream
ObjectOutputStream dos =new ObjectOutputStream(
new BufferedOutputStream(
new FileOutputStream(dest)
)
);
//操作 写出的顺序 为读取准备
dos.writeObject(emp);
dos.writeObject(arr);
//释放资源
dos.close();
}
序列化结果:
同样我们可以把文件反序列化读入程序:
public static void read(String destPath) throws IOException, ClassNotFoundException{
//创建源
File src =new File(destPath);
//选择流
ObjectInputStream dis =new ObjectInputStream(
new BufferedInputStream(
new FileInputStream(src)
)
);
//操作 读取的顺序与写出一致 必须存在才能读取
//不一致,数据存在问题
Object obj =dis.readObject();
if(obj instanceof Employee){
Employee emp=(Employee)obj;
System.out.println(emp.getName());
System.out.println(emp.getSalary());
}
obj =dis.readObject();
int[] arr=(int[])obj;
System.out.println(Arrays.toString(arr));
dis.close();
}
结果如下:
打印流
PrintStream和InputStream是Java中的打印流,看着比较陌生,但我们基本每次写程序都在用,println这个方法大家再熟悉不过了吧,它就是PrintStream对象的方法,换句话说,System.out返回的就是PrintStream类。
打印流除了可以和控制台直接交互之外,也可以进行文件写出地操作,如下例所示,但用的不多做了解即可。
public static void main(String[] args) throws FileNotFoundException {
System.out.println("test");
//接收PrintStream对象
PrintStream ps =System.out;
ps.println(false);
//输出到文件
File src = new File("e:/xp/test/print.txt");
ps = new PrintStream(new BufferedOutputStream(new FileOutputStream(src)));
ps.println("io is so easy....");
ps.close();
}
System.in、System.out、System.err
System.out、System.err返回的PrintStream都是向控制台输出的流,他们的原理没有什么本质区别,你可以理解为System.err就是System.out输出时把字体改为红色。
System.in是标准输入流,一般配合Senner流一起使用,可以接受我们键盘的输入。同样的我们也可以用其来读取文件内容:
public static void main(String[] args) throws FileNotFoundException {
InputStream is =System.in; //键盘输入
//is = new BufferedInputStream(new FileInputStream("e:/xp/test/print.txt"));
Scanner sc = new Scanner(is);
System.out.println(sc.nextLine());//也是一行一行读
}
在System类中我们也可以通过setOut指定输出位置:
public static void main(String[] args) throws FileNotFoundException {
//重定向
System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream("e:/xp/test/print.txt")),true));
//第二个参数true表示自动刷新,也就是自动调用flush方法
System.out.println("a"); //控制台 -->文件
System.out.println("test");
//回控制台
System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)),true));
//FileDescriptor类代表控制台,常用的有FileDescriptor.in、FileDescriptor.out、FileDescriptor.err
System.out.println("back....");
}
同样我们也可以用BufferedReader对打印流进行包裹,从而可以通过readLine()方法进行键盘读入:
public static void main(String[] args) throws IOException {
InputStream is =System.in;
BufferedReader br = new BufferedReader(new InputStreamReader(is));
System.out.println("请输入。。。。");
String msg =br.readLine();
System.out.println(msg);
}
随机流RandomAccessFile
这个流不属于IO流,但支持对文件的读取和写入随机访问。它的原理是首先把随机访问的文件对象看作存储在文件系统中的一个大型 byte 数组,然后通过指向该 byte 数组的光标或索引(即:文件指针 FilePointer)在该数组任意位置读取或写入任意数据。
RandomAccessFile最重要的是它的seek方法,它可以指定文件读取的初始位置,案例如下:
public static void main(String[] args) throws IOException {
RandomAccessFile rnd =new RandomAccessFile(new File("E:/xp/20130502/test/test.java"),"r");
//第二个参数"r"表示只读
//从文件第40个字节开始读
rnd.seek(40);
//定义缓冲大小
byte[] flush =new byte[1024];
//接收长度
int len =0;
//打印读取的前20个字节所代表的内容
while(-1!=(len=rnd.read(flush))){
if(len>=20){
System.out.println(new String(flush,0,20));
break;
}else{
System.out.println(new String(flush,0,len));
}
}
rnd.close();
}
运用这个流操作我们可以完成文件的分割,大家有兴趣可以自己试着实现。以上就是IO流的全部内容,这一章节需要理解的概念不多,主要以各种流的使用方法为主,所以实例很多,代码量也比较大,这就需要大家多读多写多练。做到可以熟练运用。
上一篇:菜鸟学习笔记:Java提升篇5(IO流1——IO流的概念、字节流、字符流、缓冲流、转换流)
下一篇:菜鸟学习笔记:Java提升篇7(线程1——进程、程序、线程的区别,Java多线程实现,线程的状态)