Java 数据输入输出流、内存操作流、打印流、序列化流、随机访问流、Properties、SequenceInputStream
一、数据输入输出流
-
数据输入流: DataInputStream
-
数据输出流: DataOutputStream
-
特点: 可以写基本数据类型,可以读取基本数据类型
-
案例
import java.io.*; public class Test8 { public static void main(String[] args) throws IOException { writeData(); readData(); } private static void readData() throws IOException { DataInputStream in = new DataInputStream(new FileInputStream("a.txt")); //怎么存的就怎么取,顺序不能乱 boolean b = in.readBoolean(); double v = in.readDouble(); char c = in.readChar(); int i = in.readInt(); System.out.println(b); System.out.println(v); System.out.println(c); System.out.println(i); } private static void writeData() throws IOException { DataOutputStream out = new DataOutputStream(new FileOutputStream("a.txt")); out.writeBoolean(true); out.writeDouble(3.14); out.writeChar('a'); out.writeInt(2000); out.close(); } } //输出 true 3.14 a 2000
二、内存操作流
内存操作流:此流不关联文件,不直接读写文件,就在内存中操作数据
-
操作字节数组
ByteArrayOutputStream
ByteArrayInputStream
此流关闭无效,所以无需关闭。此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray () 和 toString () 获取数据。import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class Test9 { public static void main(String[] args) throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byteArrayOutputStream.write(97); //a byteArrayOutputStream.write("上甘岭".getBytes()); byte[] bytes = byteArrayOutputStream.toByteArray(); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); byte[] bytes1 = new byte[1024]; int len = byteArrayInputStream.read(bytes1); String s = new String(bytes1, 0, len); System.out.println(s); } } //输出: a上甘岭
-
操作字符数组
CharArrayWrite
CharArrayReaderpublic class MyTest3 { public static void main(String[] args) throws IOException { //操作字符数组 // CharArrayWrite //CharArrayReader CharArrayWriter charArrayWriter = new CharArrayWriter(); charArrayWriter.write(new char[]{'a','b','c'}); charArrayWriter.write("好好学习,天天向上,爱生活,爱Java"); char[] chars = charArrayWriter.toCharArray(); System.out.println(String.valueOf(chars)); String s1 = new String(chars); System.out.println(s1); String s = charArrayWriter.toString(); System.out.println(s); } }
-
操作字符串
StringWriter
StringReaderpublic class MyTest4 { public static void main(String[] args) { // StringWriter // StringReader StringWriter stringWriter = new StringWriter(); stringWriter.write("abc"); stringWriter.write("ddd"); String s = stringWriter.toString(); System.out.println(s); } }
三、打印流
-
特点
-
打印流只能操作目的地,不能操作数据源(不能进行读取数据)
-
可以操作任意数据类型的数据 调用print() 方法可以写任意数据类型
-
如果我们启用自动刷新,那么在调用println、printf 或 format 方法中的一个方法的时候,会完成自动刷新
public PrintWriter(OutputStream out, boolean autoFlush) 是否启动自动刷新
public PrintWriter(Writer out, boolean autoFlush) 是否启动自动刷新
-
这个流可以直接对文件进行操作(可以直接操作文件的流: 就是构造方法的参数可以传递文件或者文件路径)
import java.io.FileNotFoundException; import java.io.PrintStream; public class Test10 { public static void main(String[] args) throws FileNotFoundException { PrintStream printStream = new PrintStream("a.txt"); printStream.println(12); printStream.println(true); printStream.println("abc"); printStream.flush(); //实现换行和自动刷新 PrintWriter pw = new PrintWriter(new FileWriter("printWriter2.txt") , true) ; pw.println(true) ; pw.println(100) ; pw.println("中国") ; } }
-
-
打印流复制文本文件
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.PrintStream; public class Test11 { public static void main(String[] args) throws IOException { BufferedReader bufferedReader = new BufferedReader(new FileReader("e:\\test.txt")); PrintStream printStream = new PrintStream("e:\\test1.txt"); String s = null; while ((s=bufferedReader.readLine())!=null){ printStream.println(s); } } }
-
标准输入输出流概述和输出语句的本质
- public static final InputStream in: 标准输入流, 对应的设备是键盘
- public static final PrintStream out: 标准输出流 , 对应的设备就是显示器
- System.in的类型是InputStream
- System.out的类型是PrintStream是OutputStream的孙子类FilterOutputStream 的子类
-
第二种方式实现键盘录入
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Test12 { public static void main(String[] args) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); while (true){ String s = bufferedReader.readLine(); //自定义一个结束标记 if("-1".equals(s)){ break; } System.out.println(s); } } }
四、随机访问流
-
概述
RandomAccessFile概述 最大特点 能读能写
RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream、OutputStream的功能。支持对随机访问文件的读取和写入。RandomAccessFile的父类是Object , 这个流对象可以用来读取数据也可以用来写数据.可以操作任意数据类型的数据 -
注意
- 随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组
- 存在指向该隐含数组的光标或索引,称为文件指针
- 输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针
-
案例
import java.io.IOException; import java.io.RandomAccessFile; public class Test13 { public static void main(String[] args) throws IOException, IOException { writeData(); //你怎么写的就怎么读,顺不要乱 RandomAccessFile raf = new RandomAccessFile("e.txt", "rw"); boolean b = raf.readBoolean(); //获取当前文件的指针位置 System.out.println("指针位置:"+raf.getFilePointer()); double v = raf.readDouble(); System.out.println("指针位置:" + raf.getFilePointer()); int i = raf.readInt(); System.out.println("指针位置:" + raf.getFilePointer()); String s = raf.readUTF(); System.out.println("指针位置:" + raf.getFilePointer()); System.out.println(b); System.out.println(v); System.out.println(i); System.out.println(s); //设置指针的位置 raf.seek(13); String s2 = raf.readUTF(); System.out.println(s2); } private static void writeData() throws IOException { RandomAccessFile raf = new RandomAccessFile("e.txt", "rw"); raf.writeBoolean(true); raf.writeDouble(3.14); raf.writeInt(1000); //首先,把两个字节从文件的当前文件指针写入到此文件, //类似于使用 writeShort 方法并给定要跟随的字节数 raf.writeUTF("你好"); raf.close(); } } //输出: 指针位置:1 指针位置:9 指针位置:13 指针位置:21 true 3.14 1000 你好 你好
五、序列化流和反序列化流
-
概述
序列化 ObjectOutputStream:就是把对象通过流的方式存储到文件中
反序列化ObjectInputStream:就是把文件中存储的对象以流的方式还原成对象
-
注意
- 需要该类实现一个序列化接口Serializable
- 再加一个静态常量的UID
- 使用transient关键字声明不需要序列化的成员变量
-
案例
import java.io.Serializable; public class Student implements Serializable { private static final long serialVersionUID = -3227794823959836026L; private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = 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; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } } import java.io.*; public class Test14 { public static void main(String[] args) throws IOException, ClassNotFoundException { //序列化 ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("a.txt")); objectOutputStream.writeObject(new Student("张三",18)); objectOutputStream.writeObject(new Student("李四",19)); objectOutputStream.flush(); objectOutputStream.close(); //反序列化 ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("a.txt")); Object o = objectInputStream.readObject(); System.out.println(o); Object o1 = objectInputStream.readObject(); System.out.println(o1); } } //输出: Student{name='张三', age=18} Student{name='李四', age=19}
六、Properties
-
概述
Properties 类表示了一个持久的属性集。可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串,Properties父类是Hashtable,Properties可作为Map集合的使用
-
注意:属于双列集合,这个集合中的键和值都是字符串 Properties不能指定泛型
-
特殊功能
- public Object setProperty(String key,String value) 调用 Hashtable 的方法 put。使用 getProperty 方法提供并行性。强制要求为属性的键和值使用字符串。返回值是 Hashtable 调用 put 的结果
- public String getProperty(String key) 用指定的键在此属性列表中搜索属性。如果在此属性列表中未找到该键,则接着递归检查默认属性列表及其默认值。如果未找到属性,则此方法返回 null
- public Set stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,其键或值不是 String 类型的属性被忽略
- public void load(Reader reader): 读取键值对数据把数据存储到Properties中
- public void store(Writer writer, String comments)把Properties集合中的键值对数据写入到文件中, comments注释
import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Map; import java.util.Properties; import java.util.Set; public class Test15 { public static void main(String[] args) throws IOException { Properties properties = new Properties(); properties.setProperty("张三","18"); properties.setProperty("李四","20"); properties.setProperty("王五","23"); String s = properties.getProperty("李四"); System.out.println(s); Set<String> names = properties.stringPropertyNames(); System.out.println(names); //将键值对数据存储到properties文件中 properties.store(new FileWriter("a.properties"),null); //将properties文件中的数据读入双列集合 properties.load(new FileReader("a.properties")); Set<Map.Entry<Object, Object>> entries = properties.entrySet(); for (Map.Entry<Object, Object> entry : entries) { System.out.println(entry.getKey()+" "+entry.getValue()); } } } //输出: 20 [王五, 张三, 李四] 王五 23 张三 18 李四 20
七、SequenceInputStream
- 概述
SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止
-
构造方法
- SequenceInputStream(InputStream s1, InputStream s2) 通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。
- SequenceInputStream(Enumeration<? extends InputStream> e) 通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.SequenceInputStream; public class Test16 { public static void main(String[] args) throws IOException { FileInputStream in1 = new FileInputStream("test.txt"); FileInputStream in2 = new FileInputStream("test2.txt"); FileOutputStream outputStream = new FileOutputStream("all2.txt"); SequenceInputStream allIn = new SequenceInputStream(in1, in2); int len = 0; byte[] bytes = new byte[1024]; while ((len = allIn.read(bytes)) != -1) { outputStream.write(bytes, 0, len); } allIn.close(); outputStream.close(); } }