JAVASE-26: IO流之其他的一些字符流、字节流

tech2025-07-18  3

1. 数据输入输出流

DataOutputStream写-DataInputStream读

怎么写的就怎么读,能够读写基本数据类型(ctrl+q可以查看传入什么参数)

特有方法:

DataOutputStream 写 writeInt(); writeDouble(); writeBoolean(); writeUTF();

DataInputStream 读 readInt(); readDouble(); readBoolean(); readUTF();

public static void main(String[] args) throws IOException { DataInputStream in = new DataInputStream(new FileInputStream("a.txt")); int i = in.readInt(); System.out.println(i); double v = in.readDouble(); System.out.println(v); boolean b = in.readBoolean(); System.out.println(b); String s = in.readUTF(); System.out.println(s); writeData(); } private static void writeData() throws IOException { DataOutputStream out = new DataOutputStream(new FileOutputStream("a.txt")); out.writeInt(100); out.writeDouble(3.14); out.writeBoolean(true); out.writeUTF("你好世界"); out.close(); }

2. 内存操作流

不直接关联任何文件,只在内存中进行读写

2.1. 操作字节数组

ByteArrayOutputStream写-ByteArrayInputStream读 (常用)

ByteArrayOutputStream 写:

他在内存中维护了一个字节数组作为缓冲区,随着数据的不断写入,缓冲区会自动不断扩充,要取出缓冲区数据,可以使用toByteArray()、toString()。此类实现了一个输出流,其中的数据被写入一个 byte 数组。

toByteArray() 返回的是它所维护的字节数组

toString() 返回字符串类型

ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write("爱生活".getBytes()); out.write("爱java".getBytes()); out.write("好好学习".getBytes()); out.write("天天向上".getBytes()); out.write("天天向上".getBytes()); byte[] bytes = out.toByteArray(); String s = new String(bytes); System.out.println(s); String s1 = out.toString(); System.out.println(s1); out.close();

ByteArrayInputStream(byte[] buf) 读:

使用buf作为其缓冲区数组,传入一个有数据的字节数组

然后它会把这个字节数组里的数据,读入创建的新字节数组

ByteArrayInputStream bis = new ByteArrayInputStream(bytes); byte[] bytes1 = new byte[1024]; int len = bis.read(bytes1); String s2 = new String(bytes1, 0, len); System.out.println(s2);

2.2 操作字符数组 CharArrayWriter-CharArrayReader

维护了一个字符数组作为缓冲区

取 .valueof()

CharArrayWriter charArrayWriter = new CharArrayWriter(); charArrayWriter.write("一行字符串"); charArrayWriter.write(new char[]{'a','b','c'}); char[] chars = charArrayWriter.toCharArray(); System.out.println(String.valueOf(chars)); System.out.println(charArrayWriter.toString());

2.3 操作字符串 StringWriter-StringReader

取 .toString()

StringWriter stringWriter = new StringWriter(); stringWriter.write("abc"); stringWriter.write("abc"); stringWriter.write("abc"); stringWriter.write("abc"); System.out.println(stringWriter.toString());

练习:要两首mp3合并成一首歌

public static void main(String[] args) throws IOException { FileInputStream in1 = new FileInputStream("许巍 - 蓝莲花.mp3"); FileInputStream in2 = new FileInputStream("许巍 - 曾经的你.mp3"); FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\许巍合.mp3"); ArrayList<FileInputStream> list = new ArrayList<>(); list.add(in1); list.add(in2); int len = 0; byte[] bytes = new byte[1024 * 8]; for (FileInputStream in : list) { while ((len = in.read(bytes)) != -1) { out.write(bytes,0,len); } in.close(); } System.out.println("合并完毕"); }

3. 打印流

只能写出数据 不能读取数据

字节打印流 PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式

PrintStream(File file) 创建具有指定文件且不带自动行刷新的新打印流。 PrintStream(OutputStream out, boolean autoFlush) 创建新的打印流。

PrintStream stream = new PrintStream("a.txt"); stream.write("你好".getBytes()); stream.println("我很好"); stream.flush(); stream.println("我很好"); stream.println("我很好"); PrintStream out = System.out; out.write("hhhe".getBytes()); System.out.println("abc"); // hhheabc System.out.write("ab".getBytes()); // ab

字符打印流 PrintWriter 字符流要刷新才能过去

public static void main(String[] args) throws FileNotFoundException { PrintWriter writer = new PrintWriter("b.txt"); writer.write("abc"); writer.println("abc"); writer.println("abc"); writer.flush(); writer.close(); }

PrintWriter(OutputStream out, boolean autoFlush) 通过现有的 OutputStream 创建新的 PrintWriter

PrintWriter printWriter = new PrintWriter(new FileOutputStream("c.txt"), true); /* printWriter.write("abc"); printWriter.write("\r\n"); printWriter.write("abc"); printWriter.write("\r\n"); */ printWriter.println("abc"); printWriter.println("abc"); printWriter.println("abc"); // printWriter.flush(); printWriter.close();

练习:打印流复制文本文件

public static void main(String[] args) throws IOException { PrintWriter printWriter = new PrintWriter(new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\a.java"),true); BufferedReader in = new BufferedReader(new FileReader("MyTest1.java")); while (true){ String s = in.readLine(); if(s!=null){ printWriter.println(s); }else{ break; } } in.close(); printWriter.close(); }

4. 随机访问流

RandomAccessFile 能读也能写。random 形容词 随机的 随意的 胡乱的、access 动词 存取 访问 使用

此类不属于流,是Object的子类。但它融合了InputStream和OutputStream的功能。

.writeInt();

.writeDouble();

.writeUTF();

… …

.getFilePointer(); 获取指针

.seek(某个位置); 定位文件指针位置

public static void main(String[] args) throws IOException { RandomAccessFile in = new RandomAccessFile("e.txt", "rw"); int i = in.readInt(); long filePointer = in.getFilePointer(); System.out.println("指针位置:"+filePointer);// 指针位置:4 double v = in.readDouble(); filePointer = in.getFilePointer(); System.out.println("指针位置:"+filePointer);// 指针位置:12 boolean b = in.readBoolean(); filePointer = in.getFilePointer(); System.out.println("指针位置:" + filePointer);// 指针位置:13 String s = in.readUTF(); filePointer = in.getFilePointer(); System.out.println("指针位置:" + filePointer);// 指针位置:21 // 定位文件指针的位置 in.seek(13); s = in.readUTF(); System.out.println(i);// 200 System.out.println(v);// 32.2 System.out.println(b);// false System.out.println(s);// 你好 System.out.println(s);// 你好 } private static void writeData() throws IOException { RandomAccessFile out = new RandomAccessFile("e.txt", "rw"); out.writeInt(200); out.writeDouble(32.2); out.writeBoolean(false); out.writeUTF("你好"); }

RandomAccessFile的父类是Object, 这个流对象可以用来读取数据也可以用来写数据,可以操作任意数据类型的数据。我们可以通过getFilePointer方法获取文件指针,并且可以通过seek方法设置文件指针。

练习:利用RandomAccessFile模拟下载文件

public static void main(String[] args) throws IOException { RandomAccessFile in=null; RandomAccessFile out=null; try { in = new RandomAccessFile("许巍 - 蓝莲花.mp3", "rw"); out = new RandomAccessFile("C:\\Users\\ShenMouMou\\Desktop\\许巍 - 蓝莲花.mp3", "rw"); // 点了继续下载:1.先 判断之前的那个文件,在不在,如果不在 File file = new File("C:\\Users\\ShenMouMou\\Desktop\\许巍 - 蓝莲花.mp3"); if (!file.exists()) { in.seek(0); out.seek(0); }else{ BufferedReader reader = new BufferedReader(new FileReader("config.txt")); String s = reader.readLine(); long l = Long.parseLong(s); in.seek(l+1); out.seek(l+1); } int len=0; byte[] bytes = new byte[2]; int i=0; while ((len=in.read(bytes))!=-1){ out.write(bytes,0,len); } in.close(); out.close(); } catch (Exception e) { e.printStackTrace(); long pointer = in.getFilePointer(); PrintWriter printWriter = new PrintWriter("config.txt"); printWriter.println(pointer); printWriter.flush(); printWriter.close(); } }

5. 序列化流 反序列化流

序列化—针对对象,把对象通过流的方式存储到文件中,此对象 要重写Serializable 接口(serializable 形容词 可序列化 可串行化的)才能被序列化

new ObjectOutputStream(new FileOutputStream());

.writeObject();

必须给类实现一个接口:Serializable 序列化接口

如果想要一个类的对象 能被序列化 要求该类要实现Serializable 序列化接口,

如果不想序列化某个参数 可以加上transient 排除某些属性 不要被序列化

private transient int age ;// 可以阻止成员变量的序列化使用transient(transient 形容词 瞬态 瞬时的)

反序列化 就是把文件中存储的对象以流的方式还原成对象

new ObjectInputStream(new FileInputStream());

.readObject();

public static void main(String[] args) throws IOException, ClassNotFoundException { readData(); } private static void readData() throws IOException, ClassNotFoundException { ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.txt")); Student s = (Student) in.readObject(); System.out.println(s.getName()+"=="+s.getAge()); } private static void writeData() throws IOException { Student s1 = new Student("张三", 23); // NotSerializableException ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student.txt")); out.writeObject(s1); out.close(); } public class Student implements Serializable { private static final long serialVersionUID = -7476321121279308524L; private String name; // transient 可以排除某些属性,不要被序列化。 // private transient int age; private int age;

6. 属性集合

Properties 类表示了一个持久的属性集。properties–名词 性能 道具 内容 属性 特性 property的复数形式 Properties 可保存在流中或从流中加载。 属性列表中每个键及其对应值都是一个字符串。 Properties父类是Hashtable

属于双列集合,这个集合中的键和值都是字符串 Properties不能指定泛型

Properties的键值都是定好的,默认为String

new Properties();

操作一些配置文件

读取配置文件,配置文件有要求,一般配置文件的后缀名 .properties

配置文件中键值 ,以=分割

public static void main(String[] args) throws IOException { // 读取配置文件中的数据 HashMap<String, String> hm = new HashMap<>(); BufferedReader reader = new BufferedReader(new FileReader("user.properties")); while (true){ String line = reader.readLine(); if(line!=null){ String[] s = line.split("="); hm.put(s[0],s[1]); }else{ break; } } System.out.println(hm); }

Properties的特殊功能

存数据 .setProperty()

取数据 .getProperty()

public static void main(String[] args) { // Properties 他的键和值的数据类型,已经默认为String Properties properties = new Properties(); /* properties.put("username","zhangsan"); Object username = properties.get("username"); */ properties.setProperty("username", "zhangsan"); String username = properties.getProperty("username2"); // String username = properties.getProperty("username2","aaa"); System.out.println(username);// null System.out.println(properties);// {username=zhangsan} }

Properties和IO流进行配合使用:

public void load(Reader reader): 读取键值对数据把数据存储到Properties中

public void store(Writer writer, String comments)把Properties集合中的键值对数据写入到文件中, comments注释

.store(new FileOutputStream(""))

.load(new FileInputStream(""))


7. 顺序流

sequence 名词 顺序 序列

合并文件,SequenceInputStream

表示其他输入流的逻辑串联。 它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

a:构造方法 SequenceInputStream(InputStream s1, InputStream s2) 通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。

public static void main(String[] args) throws IOException { // 将a.txt和b.txt两个文本文件的内容合并到c.txt FileInputStream in1 = new FileInputStream("a.txt"); FileInputStream in2 = new FileInputStream("b.txt"); FileInputStream in3 = new FileInputStream("b.txt"); SequenceInputStream allIn = new SequenceInputStream(in1, in2); SequenceInputStream allIn2 = new SequenceInputStream(allIn, in3); FileOutputStream out = new FileOutputStream("ff.txt"); int len=0; byte[] bytes = new byte[1024]; while ((len=allIn.read(bytes))!=-1){ out.write(bytes,0,len); out.flush(); } allIn.close(); out.close(); }

b:构造方法 SequenceInputStream(Enumeration<? extends InputStream> e) 通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。

new Vector

Vector.elements();

public static void main(String[] args) throws IOException { FileInputStream in1 = new FileInputStream("a.txt"); FileInputStream in2 = new FileInputStream("b.txt"); FileInputStream in3 = new FileInputStream("b.txt"); Vector<FileInputStream> vector = new Vector<>(); vector.add(in1); vector.add(in2); vector.add(in3); // Enumeration Enumeration<FileInputStream> elements = vector.elements(); SequenceInputStream allIn = new SequenceInputStream(elements); FileOutputStream out = new FileOutputStream("ff.txt"); int len = 0; byte[] bytes = new byte[1024]; while ((len = allIn.read(bytes)) != -1) { out.write(bytes, 0, len); out.flush(); } allIn.close(); out.close(); }

8. scanner

scanner 名词 扫描仪 扫描机

Scanner(File source) 构造一个新的 Scanner,它生成的值是从指定文件扫描的。

Scanner(InputStream source) 构造一个新的 Scanner,它生成的值是从指定的输入流扫描的。

public static void main(String[] args) throws FileNotFoundException { Scanner scanner = new Scanner(new File("MyTest1.java")); while (scanner.hasNextLine()){ String s = scanner.nextLine(); System.out.println(s); } Scanner scanner1 = new Scanner(new FileInputStream("MyTest1.java")); }

键盘录入的 第二种方式

public static void main(String[] args) throws IOException { // Scanner scanner = new Scanner(System.in); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); while (true){ System.out.println("请输入数据"); String s = reader.readLine(); System.out.println(s); if("886".equals(s)){ break; } } }
最新回复(0)