其他流

mac2026-06-15  17

数据输入输出流

概述:可以直接读写基本数据类型

数据输入流:DataInputStream 数据输出流:DataOutputStream

构造方法: DataInputStream(InputStream in) :使用指定的底层 InputStream 创建一个 DataInputStream DataOutputStream(OutputStream out) :创建一个新的数据输出流,将数据写入指定基础输出流

应用:

package org.org.westos.demo; import java.io.*; public class MyClass { public static void main(String[] args) throws IOException { //创建一个输出流,并自动创建文件 DataOutputStream out = new DataOutputStream(new FileOutputStream("a.txt")); //写基本数据类型 out.writeInt(100); out.writeBoolean(true); out.writeDouble(3.14); //创建一个输入流,并关联文件 DataInputStream in = new DataInputStream(new FileInputStream("a.txt")); //获取文件中的基本类型数据 //这里注意,获取顺序跟写入顺序类型必须一致 int i = in.readInt(); System.out.println(i); boolean b = in.readBoolean(); System.out.println(b); double v = in.readDouble(); System.out.println(v); out.close(); in.close(); } }

读写基本数据类型是它的特有功能,当然,读写一个字节和读写字节数组也一样可以

内存操作流

概述:不操作文件,只操作内存中的数据

分类 (1)操作字节数组:ByteArrayOutputStream、ByteArrayInputStream,此流无需关闭 (2)操作字符数组:CharArrayWrite、CharArrayReader (3)操作字符串:StringWriter、StringReader

构造方法: (1)操作字节数组 ByteArrayOutputStream() :创建一个新的 byte 数组输出流 ByteArrayOutputStream(int size) :创建一个新的 byte 数组输出流,它具有指定大小的缓冲区容量(以字节为单位) ByteArrayInputStream(byte[] buf) :创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组 ByteArrayInputStream(byte[] buf, int offset, int length) :创建 ByteArrayInputStream,使用 buf 作为其缓冲区数组

package org.org.westos.demo; import java.io.*; public class MyClass { public static void main(String[] args) throws IOException { //根据空参构造创建一个输出流 ByteArrayOutputStream bos = new ByteArrayOutputStream(); //写入数据,参数要一个字节或一个字节数组,所以要调用getBytes方法 bos.write("你好".getBytes()); bos.write("世界".getBytes()); bos.write("hello".getBytes()); bos.write("java".getBytes()); //使用toByteArray方法取出这些数据 byte[] bytes = bos.toByteArray(); //创建一个输入流并将字节数组给它 ByteArrayInputStream bis = new ByteArrayInputStream(bytes); //读取数据 //定义一个变量,记录每次读取的字节 int len = 0; //创建一个数组充当缓冲区 byte[] bytes1 = new byte[1024]; //创建一个文件,将读取到的数据放入文件中 FileOutputStream out = new FileOutputStream("b.txt"); while((len=bis.read(bytes1))!=-1){ out.write(bytes1,0,len); } out.close(); } }

(2)操作字符数组 CharArrayWriter() :创建一个新的 CharArrayWriter CharArrayWriter(int initialSize) :创建一个具有指定初始大小的新 CharArrayWriter CharArrayReader(char[] buf) :根据指定的 char 数组创建一个 CharArrayReader CharArrayReader(char[] buf, int offset, int length) :根据指定的 char 数组创建一个 CharArrayReader

package org.org.westos.demo; import java.io.*; public class MyClass { public static void main(String[] args) throws IOException { //根据空参构造创建一个输出流 //底层维护的是字符数组 CharArrayWriter writer = new CharArrayWriter(); //写入数据 writer.write("aaa"); writer.write("bbb"); writer.write("ccc"); //将数据写入字符数组 char[] chars = writer.toCharArray(); //转换成字符串打印输出 String s = String.valueOf(chars); System.out.println(s); } }

(3)操作字符串 StringWriter() :使用默认初始字符串缓冲区大小创建一个新字符串 writer StringWriter(int initialSize) :使用指定初始字符串缓冲区大小创建一个新字符串 writer StringReader(String s) :创建一个新字符串 reader

package org.org.westos.demo; import java.io.*; public class MyClass { public static void main(String[] args) throws IOException { //根据空参构造创建一个输出流 //底层维护的是StringBuffer StringWriter writer = new StringWriter(); writer.write("aaaaa"); writer.write("aaaaa"); writer.write("aaaaa"); writer.write("aaaaa"); String s = writer.toString(); System.out.println(s); } }

后两种操作也可以使用输入流读取数据,跟操作字节数组是一样的,根据构造方法即可

打印流

概述:只能输出数据,不能读取数据

分类 字节打印流:PrintStream 字符打印流:PrintWriter

构造方法: (1)字节打印流: PrintStream(File file) :创建具有指定文件且不带自动行刷新的新打印流 PrintStream(OutputStream out) :创建新的打印流

package org.org.westos.demo; import java.io.*; public class MyClass { public static void main(String[] args) throws IOException { //封装文件 File file = new File("b.txt"); //创建字节打印流,输出数据进关联文件 PrintStream printStream = new PrintStream(file); printStream.println(100); printStream.println(200); printStream.println("aaa"); printStream.close(); //创建标准输出流,此流已打开并准备接受输出数据 // 通常,此流对应于显示器输出 PrintStream out = System.out; out.println(100); out.println(100); out.println(100); out.close(); } }

(2)字符打印流: PrintWriter(File file) :使用指定文件创建不具有自动行刷新的新 PrintWriter

package org.org.westos.demo; import java.io.*; public class MyClass { public static void main(String[] args) throws IOException { PrintWriter printWriter = new PrintWriter(new FileOutputStream("c.txt")); printWriter.println("abc"); printWriter.println("def"); printWriter.println("ghj"); //字符流必须刷新 printWriter.flush(); printWriter.close(); //根据构造方法启动自动刷新 //启用了自动刷新,只有在调用 println、printf 或 format 的其中一个方法时才执行 PrintWriter printWriter1 = new PrintWriter(new FileOutputStream("d.txt"),true); printWriter1.println("111"); printWriter1.println("222"); printWriter1.println("33"); //启动了自动刷新,无需手动刷新 printWriter1.close(); } }

两种键盘录入方式

Scanner录入,这是之前一直的用的方式,应该很熟悉BufferedReader的readLine方法 package org.org.westos.demo; import java.io.*; public class MyClass { public static void main(String[] args) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("请输入内容"); String s = bufferedReader.readLine(); System.out.println(s); } }

如果想多次输入,用while循环就行,然后给个条件break即可

随机访问流

概述:RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能,支持对随机访问文件的读取和写入,可以操作任意数据类型的数据使用:通过getFilePointer方法获取指针,并且可以通过seek方法设置文件指针构造方法: RandomAccessFile(File file, String mode) :创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定 RandomAccessFile(String name, String mode) :创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称 package org.org.westos.demo; import java.io.*; public class MyClass { public static void main(String[] args) throws IOException { //调用方法,写入数据 writeData(); //读取数据并获取指针位置,按顺序读 RandomAccessFile rw = new RandomAccessFile(new File("a.txt"), "rw"); int i = rw.readInt(); long filePointer = rw.getFilePointer(); System.out.println(i); System.out.println("指针位置:"+filePointer); boolean b = rw.readBoolean(); filePointer = rw.getFilePointer(); System.out.println(b); System.out.println("指针位置:"+filePointer); double v = rw.readDouble(); filePointer = rw.getFilePointer(); System.out.println(v); System.out.println("指针位置:"+filePointer); //设置指针位置 rw.seek(5); //可以再次读取数据 double v1 = rw.readDouble(); System.out.println(v1); rw.close(); } //创建一个写入数据的方法 private static void writeData() throws IOException { //创建一个随即访问流 RandomAccessFile rw = new RandomAccessFile(new File("a.txt"), "rw"); //写入数据 rw.writeInt(100); rw.writeBoolean(true); rw.writeDouble(3.14); rw.close(); } }

随机访问流有指针,所以适合用于断点操作

序列化流和反序列化流

概述: 序列化流就是把对象通过流的方式存储到文件中,此对象需重写Serializable接口 反序列化就是把文件中存储的对象以流的方式还原成对象

序列化:ObjectOutputStream 反序列化:ObjectInputStream

应用

package org.org.westos.demo; import java.io.Serializable; //一个类对象,要想序列化成功,就要实现Serializable这个标记接口 //标记接口就是该接口内部没有任何方法 public class Student implements Serializable { //这个类,实现了Serializable接口最后在生成一个serialVersionUID,建议自己给出 private static final long serialVersionUID=42L; private String name; //要想某个字段不被序列化,则用transient修饰 private transient int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } import java.io.*; class MyTest3 { public static void main(String[] args) throws IOException, ClassNotFoundException { write(); read(); } //编写方法,将对象保存到文件中 private static void write() throws IOException { Student student = new Student(); student.setName("张三"); student.setAge(23); ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("a.txt")); objOut.writeObject(student); objOut.close(); } //编写方法,将文件中的对象读取出来 private static void read() throws IOException, ClassNotFoundException { ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("a.txt")); Object o = objIn.readObject(); //向下转型,获取对象 Student student = (Student) o; String name = student.getName(); int age = student.getAge(); System.out.println(name+"-"+age); } }

年龄字段被序列化的情况 年龄字段被transient修饰,不被序列化的情况 另外,序列化流和反序列化流还用于深克隆

Properties

概述:Properties 类表示了一个持久的属性集,继承自Hashtable,有自己的特有功能构造方法: Properties() :创建一个无默认值的空属性列表 Properties(Properties defaults) :创建一个带有指定默认值的空属性列表其他方法 getProperty(String key) :用指定的键在此属性列表中搜索属性 setProperty(String key, String value) :调用 Hashtable 的方法 put load(InputStream inStream) :从输入流中读取属性列表(键和元素对) store(OutputStream out, String comments) :将集合数据存储到文本文件中 package org.org.westos.demo; import java.io.*; import java.util.Properties; public class MyClass { public static void main(String[] args) throws IOException { //根据空参构造创建属性集合 //不指定泛型,规定键值都是字符串类型 Properties map = new Properties(); //调用setProperty方法给集合存数据 map.setProperty("zhangsan","19"); map.setProperty("lisi","24"); map.setProperty("wangwu","28"); System.out.println(map); //调用getProperty方法通过键找值 String value = map.getProperty("zhangsan"); System.out.println(value); //调用store方法将集合数据存储到文本文件 //注意:文本文件后缀名一般是properties map.store(new FileWriter("data.properties"),null); Properties properties = new Properties(); //调用load方法把配置文件中键值对数据,读取到集合中 properties.load(new FileInputStream("data.properties")); System.out.println(properties); } }

顺序流

概述:SequenceInputStream,它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止构造方法: SequenceInputStream(Enumeration<? extends InputStream> e) :通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数 SequenceInputStream(InputStream s1, InputStream s2) :通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节 package org.org.westos.demo; import java.io.*; import java.util.Enumeration; import java.util.Vector; public class MyClass { public static void main(String[] args) throws IOException { //封装待合并歌曲并创建输入流 FileInputStream in1 = new FileInputStream("许巍 - 曾经的你.mp3"); FileInputStream in2 = new FileInputStream("许巍 - 蓝莲花.mp3"); //将输入流放入集合 Vector<FileInputStream> vector = new Vector<>(); vector.add(in1); vector.add(in2); //合区歌曲 Enumeration<FileInputStream> elements = vector.elements(); SequenceInputStream all = new SequenceInputStream(elements); FileOutputStream out = new FileOutputStream("合并歌曲"); int len = 0; byte[] bytes = new byte[1024]; while((len=all.read(bytes))!=-1){ out.write(bytes,0,len); } out.close(); all.close(); in1.close(); } }

压缩流和解压流

概述: 压缩流就是对文件或者文件夹的压缩 解压流就是把压缩文件还原成文件或文件夹

压缩流:zipOutputStream 解压流:ZipInputStream

方法 void putNextEntry(ZipEntry e):开始写入新的zip文件条目并将流定位到条目数据的开始处 ZipEntry getNextEntry():读取下一个zip文件条目并将流定位到该条目数据的开始处 String getName():返回条目名称 boolean isDirectory():如果为目录条目,则返回 true

应用(多级文件夹的压缩以及解压)

//多级文件夹的压缩 package org.org.westos.demo; import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class MyClass2 { public static void main(String[] args) throws IOException { //封装多级文件夹 File srcFile = new File("D:\\java"); //封装目标压缩文件 ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream("D:\\java.zip")); //创建高效流包装压缩流 BufferedOutputStream bos = new BufferedOutputStream(zipOut); //调用压缩方法 yasuo(srcFile,srcFile.getName(),zipOut,bos); //释放资源 zipOut.close(); bos.close(); } private static void yasuo(File srcFile, String name, ZipOutputStream zipOut, BufferedOutputStream bos) throws IOException { //判断srcFile是文件还是文件夹 if(srcFile.isFile()){ //如果是文件,直接压缩 //封装压缩条目 zipOut.putNextEntry(new ZipEntry(name)); //创建高效输入流 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile)); //读写 int len = 0; byte[] bytes = new byte[1024]; while((len=bis.read())!=-1){ bos.write(bytes,0,len); bos.flush(); } bis.close(); }else{ //如果是文件夹,递归 File[] files = srcFile.listFiles(); for (File file : files) { //传路径的时候,最好不要带盘符号,把盘符号压缩进压缩包里,没有意义 yasuo(file,name+"\\"+file.getName(),zipOut,bos); } } } } //多级文件夹的解压 package org.org.westos.demo; import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; //解压多级文件夹 public class MyTest { public static void main(String[] args) throws IOException { //封装压缩文件夹 ZipInputStream zipIn = new ZipInputStream(new FileInputStream("D:\\java.zip")); //创建高效流包装解压流 BufferedInputStream bis = new BufferedInputStream(zipIn); //获取下一个压缩条目 ZipEntry nextEntry=null; File file = null; //循环获取每一个压缩条目 while((nextEntry=zipIn.getNextEntry())!=null&&!nextEntry.isDirectory()){ //把压缩条目封装成文件 file = new File("D:\\", nextEntry.getName()); //如果一个压缩条目它的父目录不存在,就创建 if(!file.getParentFile().exists()){ new File(file.getParent()).mkdirs(); } //读写 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); int len = 0; byte[] bytes = new byte[1024]; while((len=bis.read())!=-1){ bos.write(bytes,0,len); bos.flush(); } bos.close(); } bis.close(); zipIn.close(); } }

学会了多级文件夹的操作,对于文件和单级文件夹的操作也就会了

以上就是所学习的一些其他流 在学习每一个流时,还是要借助API文档,以获得更好的了解和使用 每个流针对不同的需求都会有一定程度上的方便,这也就是我们需要学习其他流的目的 虽然字节流可以完成任意类型的文件操作,但有时会不方便,实现会比较复杂,这时,这些其他流就派上用场了

最新回复(0)