1、打印流:就是输出流,可以直接操作输入流和文件
printStream:字节流
特点:1、构造函数接收File对象、字符路径、字符输出流
2、该对象具有特有的方法,print println可以打印任何数据类型的数据。
3、特有的printf方法可以保持任意类型的数据表现形式的原样性,将数据输出到目的地,对于OutputStream父类中的write是将数据的最低字节写出去、
API:为其他的输出流添加了功能,使他们能够方法便的打印各种数据值表示形式,它还提供了其他两项功能。与其他输出流不同,printStream永远不会抛出IOException异常,而是异常情况仅设置可通过checkError方法测试的内部标识,另外,为了自动刷新,可以创建一个printStream,这以为着可在写入byte数组之后自动调用flush方法,可吊桶其中一个println方法,或者写入一个换行符或者字节(\r\n),printStream打印的所有字符都使用平台默认字符编码转换为字节,在需要写入字符而不是写入字节的情况下,应该使用printWriter类。
注意:能写一个整数、还能打印一个整数为什么?
Write(97);a
0000-0000 0000-0000 0000-0000 0110-0001 97
将最后一个八位写入到硬盘,也就是最后一个字节0110-0001记事本把这个二进制解析了,然后查表返回a;
Print(97);你看到是什么?目的里面就是什么?97
原理:先把97--->"97"--->"97".getBytes()(2个字节)
printWriter字符流:使用频繁,因为需要将数据从服务端打印到客户端
特点:
1、当操作的数据是字符时,可以选择printWriter比printStream更方便。
2、它的构造函数可以接收File对象,字符串路径、字节输出流、字符流。
3、可以在构造函数中、如果参数是输出流,那么可以通过指定另一个参数true来完成自动刷新,该方法只对println()有效。
实现代码:
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(new BufferedWriter( new FileWriter("out.txt")),true);
//加上true它能自动刷新,但是只能对println有效,需要高效,而且具备自动刷新的功能的只有字符流和字节流,所以需要封装为字符输出流。
String line=null;
while((line=buf,.readLine())!=null){
If("over".equals(line))
break;
}
out.println(line);
out.close();
//什么时候用?当需要保证数据表现的原样性时,就可以使用打印流的打印方法来完成,保证(表现形式)原样性的原理:其实就是将数据变成字符串,再进行写入操作。
2、序列流:按照一定顺序排列。
SequenceInputStream:对多个流进行合并。作用:将多个字节读取流合并成一个读取流。
特点:
1、将多个自己流合并成一个读取流,将多个源合并成一个源,操作起来方便。
2、需要的枚举接口可以通过collections.enumeration(collection);
练习:切割照片
注意:切割有两种方式:1、按照大小,2、按照文件个数。
3、操作对象:
将对象写入设备的方式,称为对象的持久化存储。
ObjectInputStream ObjectOutputStream
实现代码:
public staticvoid main(String[] args){
writeObj();
readObj();
}
Public staticvoid readObj(){
FileInputStream fis=new FileInputStream("obj.txt");
ObjectInputStream ois=new ObjectInputStream(fis);
Person p=(Person)ois.readObject();
Sysotem.out.println(p.getAge()+p.getName());
ois.close();
}
Public staticvoid writeObj(){
FilleOutputStream fos=new FileOutputStream("obj.txt");
Person p=new Person("wangwu",34);
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(p);
fos.close();
}
给需要序列化的类打个标记,seriablizeble接口
注意:
框架和面试的时候常面到,比如对象的声明周期的延长,以前是内存,现在存储到硬盘中,静态数据不会被序列化,
eg:private static String name,静态之后读取的是34,null;因为静态之后name存储到了方法区,写到硬盘中与它无关。
Transient:可以让非静态的数据不被序列化。
细节:
1、用ObjectOutputStream写出的数据只能用ObjectInputStream读取。
2、文件存储的是对象的时候,使用object来表示扩展名的。
4、RandomAccessFile:随进访问文件,此类的实例支持对随进访问的文件读和写。
特点:
1、可以读取又可以写入
2、内部维护了一个大型的byte数组,通过对数组的操作完成读取和写入
3、通过getFilePointer方法获取指针的位置,还可以通过seek方法获取指针的位置。
4、该对象内容应该封装了字节输入流和字节输出流。
5、该对象只能操作文件。
实现代码:
public classRandomAccessFileDemo {
public static void main(String[] args)throws IOException {
randomWrite();
}
/*
* 随机写入。
*/
public static void randomWrite()throwsIOException{
RandomAccessFileraf = new RandomAccessFile("random.txt", "rw");
int num = 0;
raf.seek(8*num);
/*
* 写入信息。
*/
raf.write("张三".getBytes());
raf.writeInt(65);
raf.close();
}
/*
* 随机读取。
*/
public static void randomRead() throwsIOException{
//读取信息
RandomAccessFile raf = new RandomAccessFile("random.txt", "r");
int n = 1;
//只要改变指针的位置,通过seek方法。
raf.seek(8*n);
byte[] buf = new byte[4];
raf.read(buf);//一次读四个字节并存储。
String name = new String(buf);
int age = raf.readInt();
System.out.println(name+".."+age);
System.out.println("pos:"+raf.getFilePointer());
raf.close();
}
/*
* 读取数据。random.txt 使用RandomAccessFile.
*/
public static void readFile() throwsIOException{
RandomAccessFile raf = new RandomAccessFile("random.txt","r");
byte[] buf = new byte[4];
raf.read(buf);//一次读四个字节并存储。
String name = new String(buf);
int age = raf.readInt();
System.out.println(name+".."+age);
raf.close();
}
/*
* 通过RandomAccessFile类创建文件并给文件中写入数据。
* 数据以:姓名+年龄为主的个人信息。
*/
public static void writeFile() throwsIOException{
/*
* 创建RandomAccessFile对象时,如果文件不存在则创建,
* 如果文件已存在,则不创建。
*/
RandomAccessFile raf = new RandomAccessFile("random.txt","rw");
raf.write("张三".getBytes());
raf.writeInt(97);
raf.write("李四".getBytes());
raf.writeInt(99);
raf.close();
}
}
通过seek方法操作指针,可以从这个数组中任意位置上进行读和写,还可以完成数据的修改,但是要注意数据必须是有规律的。
5、管道流:需要多线程技术相结合的流对象。
PipedInputStream和PipedOutputStream
可以将管道输出流连接到管道输入流来创建通信管道。
Read方法有一个特点:阻塞,没数据的时候在等待,不往下执行
Eg:
-->write--->read:能正常执行
-->read---->write:这就会出现死锁。所以管道流需要和多线程技术相结合的流
有两个方式进行连接:1、构造函数,已初始化就明确,2、connect();方法。
实现代码:
public static void main(String[] args) throws IOException {
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
pis.connect(pos);
newThread(new MyRead(pis)).start();
newThread(new MyWrite(pos)).start();
}
}
class MyRead implements Runnable{
private PipedInputStream pis;
public MyRead(PipedInputStream pis) {
super();
this.pis= pis;
}
public void run(){
try{
byte[] buf = new byte[1024];
System.out.println("正在读取中。。。。。。。");
int len = pis.read(buf);
String str = new String(buf,0,len);
System.out.println("str="+str);
pis.close();
}catch (Exception e) {
}
}
}
class MyWriteimplements Runnable{
private PipedOutputStream pos;
public MyWrite(PipedOutputStream pos) {
super();
this.pos= pos;
}
public void run(){
try{
System.out.println("数据准备写入。。。。。。。。");
Thread.sleep(5000);
pos.write("管道流,我来了!".getBytes());
pos.close();
}catch (Exception e) {
}
}
}
6、IO包中其他的类
1、操作基本数据类型DataInputStream和DataOutputStream用于操作基本是的数据类型值的对象。
实现代码:
public staticvoid main(Strijng[] args){
readData();
}
public staticvoid writeData(){
DataOutputStream dos=new DataOutputStream(newFileOutoutStream("data.txt"));
dos.writeBoolean(true);
dos.close();
}
public staticvoid readData(){
DataInputStream dis=new DataInputStream(newFileInputStream("data.txt"));
Boolean b=dis.readBoolean();
Sysotem.out.println(b);
Dis.close();
}
2、ByteArrayInputStream 和ByteArrayOutStream
操作字节数组的。其实就是操作内存设备的流对象。
ByteArrayOutStream:
此类实现了一个输出流,其中数据被写入到一个byte数组,缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。
关闭是无效的,为什么?因为此类并没有调用低层的资源,而是直接在操作内存中的数组。
ByteArrayInputStream:
包含一个内部缓冲区,该缓冲区包含从流中读取的字节,关闭也是无效的,一初始化必须有数据。该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。 关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
实现代码:
//源是内存,目的也是内存,用的就是流的读写思想来操作数组。
ByteArrayInputStream bis=new ByteArrayInputStream("abcds".getBytes());
ByteArrayOutputStream bos=new ByteArrayOutputStream();
int ch=0;
while((ch=bis.read())!=-1){
bos.write(ch);
}