目录
序列流
序列流可以把多个字节输入流整合成一个,从序列流中读取数据时,将从被整合的第一个流开始读,读完之后继续读第二个,以此类推
好处是可以提高代码的复用性
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
public class demo1 {
public static void main(String[] args) throws IOException {
FileInputStream fis1 = new FileInputStream("a.txt"); //创建输入流对象,关联a.txt
FileInputStream fis2 = new FileInputStream("b.txt");//创建输入流对象,关联b.txt
SequenceInputStream sis = new SequenceInputStream(fis1,fis2);//将两个流合成一个流
FileOutputStream fos = new FileOutputStream("c.txt");//创建输出流对象,关联c.txt
int b;
while((b = sis.read()) != -1) { //用整合后的读
fos.write(b); //写到指定文件上
}
sis.close(); //sis在关闭的时候会将构造方法中传入的流对象也都关闭
fos.close();
}
}
序列流整合多个
根据构造方法的不同。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;
public class demo2 {
public static void main(String[] args) throws IOException {
FileInputStream fis1 = new FileInputStream("a.txt");
FileInputStream fis2 = new FileInputStream("b.txt");
FileInputStream fis3 = new FileInputStream("c.txt");
Vector<FileInputStream> v = new Vector<>(); //创建集合对象
v.add(fis1);
v.add(fis2);
v.add(fis3);
Enumeration<FileInputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en); //将枚举对象的输入流整合成一个
FileOutputStream fos = new FileOutputStream("d.txt");
int b;
while((b = sis.read()) != -1) {
fos.write(b);
}
fos.close();
sis.close();
}
}
内存输出流
该输出流可以向内存中写数据,把内存当作一个缓冲区,写出之后可以一次性获取所有数据
使用方式:
- 创建对象:new ByteArrayOutOutStream()
- 写出数据:write(int),write(byte[])
- 获取数据:toByteArray()
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class demo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream();//在内存中创建了可以增长的内存数组
int b;
while((b = fis.read())!= -1) {
baos.write(b);
}
//Byte[] newArr = baos.toByteArray(); //可以使用指定编码表
//System.out.println(new String(newArr);
System.out.println(baos); //使用平台默认编码表,再输出语句中可以省略调用tostring()方法
fis.close();
}
}
面试题
定义一个文件输入流,调用read(byte[] b)方法将a.txt文件中的内容打印出来(byte数组大小限制为5)
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class test {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b = new byte[5];
int len;
while((len=fis.read(b)) !=-1){
baos.write(b,0,len);
}
System.out.println(baos);
fis.close();
}
}
随机访问流
RandomAccessFile类不属于流,是object的子类,但是它融合了InputStream和OutputStream的功能,支持对随机访问文件的读取和写入
read(),write(),seek()
mode参数指定用以打开文件的访问模式,允许的值及其含义为:
"r"以只读方式打开
"rw"打开以便读取和写入,如果该文件尚不存在,则尝试创建该文件
"rws"打开文件以便读取和写入,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备
"rwd"打开以便读取和写入,还要求对文件内容的每个更新都同步写入到底层数据
import java.io.IOException;
import java.io.RandomAccessFile;
public class demo3 {
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile("a.txt","rw");
raf.seek(0); //在指定位置设置指针
raf.write(98);
raf.close();
}
}
文件不会清空,会续写
有seek()方法的好处是多线程使用,可以提高效率
对象操作流ObjectOutputStream
该流可以将一个对象写出,或者读取一个对象到程序中,也就是执行序列化和反序列化操作
import dd.Person;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class demo4 {
public static void main(String[] args) throws IOException {
Person p1 = new Person("张三",23);
Person p2 = new Person("李四",24);
// FileOutputStream fos = new FileOutputStream("b.txt");
// fos.write(p1);
// FileWriter fw = new FileWriter("b.txt");
// fw.write(p1);
//字节输出流,字符输出流都不能直接写出对像
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("b.txt"));
oos.writeObject(p1);
oos.writeObject(p2);
oos.close();
//Person中必须要实现Serializable类,排序规则
}
}
虽然存入文件的会乱码,但是写出会正常写出这是由于编码表的不同
import dd.Person;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class demo5 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("b.txt"));
Person p1 = (Person)ois.readObject(); //方法读出的是Object因此要强转
Person p2 = (Person)ois.readObject(); //当文件读取到了末尾是出现
//EOFException
System.out.println(p1);
System.out.println(p2);
ois.close();
}
}
操作流优化
import hhh.Person;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
public class demo6 {
public static void main(String[] args) throws IOException {
Person p1 = new Person("zhang",222);
Person p2 = new Person("lay",21);
ArrayList<Person> al = new ArrayList<>();
al.add(p1);
al.add(p2);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("hhh.txt"));
oos.writeObject(al);
oos.close();
}
}
import hhh.Person;
import java.io.*;
import java.util.ArrayList;
public class demo6 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hhh.txt"));
ArrayList<Person> p = (ArrayList<Person>) ois.readObject();
for(Person q :p){
System.out.println(q);
}
ois.close();
}
}
数据输入输出流
DataInputStream,DateOutputStream可以按照基本数据类型大小读取数据
例如按Long大小写出一个数字,写出时该数据占8字节,读取时也可以按照Long类型读取一次读取八个字节
import java.io.*;
public class demo8 {
public static void main(String[] args) throws IOException {
//d();
DataInputStream dis = new DataInputStream(new FileInputStream("a.txt"));
int x = dis.readInt();
int y = dis.readInt();
int z = dis.readInt();
System.out.println(x);
System.out.println(y);
System.out.println(z);
dis.close();
}
public static void d() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("a.txt"));
dos.writeInt(997);
dos.writeInt(998);
dos.writeInt(999);
dos.close();
}
}
打印流
该流可以很方便的将对象的toString()结果输出,并且加上自动换行,而且可以使用自动刷出的模式
PrintStream和PrintWrite分别操作字节流和字符流,只操作数据目的
import hhh.Person;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
public class demo9 {
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = System.out; //在控制台输出
ps.println(97); //底层采用的是Integer.toString(x)将x转换为数字字符串打印
ps.write(97); //找到对应的码表然后对其结果进行打印
ps.println("xxx");
ps.println(new Person("z",23));
Person p = null; //如果是null就返回null不是就调用对象的toString()方法
ps.println(p);
ps.close();
PrintWriter pw = new PrintWriter(new FileOutputStream("b.txt"),true);//写入文件
pw.println(97); //存入的就是97
pw.write(97);
pw.print("你好");
pw.println("q"); //自动刷出只针对println
pw.close();
}
}
标准输入输出流
System.in 是InputStream,标准输入流,默认可以从键盘读取字节数据
System.out是PrintStream,标准输出流,默认可以向Console中输出字符和字节数据
由于标准输入流,输入时只能读一个字节,因此输入12只读第一个1
修改标准输入输出流
修改输入流:System.setIn(InputStream)
修改输出流:System.setOut(PrintStream)
import java.io.*;
public class demo10 {
public static void main(String[] args) throws IOException {
System.setIn(new FileInputStream("a.txt")); //修改标准流
System.setOut(new PrintStream("b.txt"));
InputStream is = System.in; //获取标准流,默认指向键盘,改变后指向文件
PrintStream ps = System.out; //默认指向控制台,改变后指向文件
int b;
while((b = is.read())!=-1) {
ps.write(b);
}
is.close();
ps.close();
}
}
没有和硬盘上产生关联的管道就不用关
修改标准输入输出流拷贝图片
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
public class demo11 {
public static void main(String[] args) throws IOException {
System.setIn(new FileInputStream("a.jpg"));
System.setOut(new PrintStream("copy.jpg"));
InputStream is = System.in;
PrintStream ps = System.out;
byte[] arr = new byte[1024];
int len;
while((len = is.read(arr))!=-1){
ps.write(arr,0,len);
}
is.close();
ps.close();
}
}
两种方式实现键盘输入
BufferReader的readLine()
InputStreamReader转换流将字节转换成字符流
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class demo12 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
System.out.println(line);
br.close();
}
}
Scanner就是我们常用的键盘录入方法
import java.util.Scanner;
public class demo13 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
System.out.println(line);
}
}
Properties的概述和作为map集合的使用
Properties类表示了一个持久的属性集,Hashtable的子类
Properties可保存在流中或者从流中加载
属性列表中每个及其对应的值都是字符串
import java.util.Properties;
public class demo14 {
public static void main(String[] args) {
Properties p = new Properties();
p.put("qwe",123);
System.out.println(p);
}
}
Properties的特殊功能使用
public Object setProperty(String key,String value)
public String getProperty(String key)
public Enumeration<String> stringPropertyNames()
import java.util.Enumeration;
import java.util.Properties;
public class demo15 {
public static void main(String[] args) {
Properties p = new Properties();
p.put("qwe","aaa");
p.put("qqq","ddd");
// System.out.println(p);
Enumeration<String> en = (Enumeration<String>) p.propertyNames();
while (en.hasMoreElements()){
String key = en.nextElement();
String value = p.getProperty(key);
System.out.println(key+"="+value);
}
}
}
Properties的load()和store()功能
import java.io.*;
import java.util.Properties;
public class demo16 {
public static void main(String[] args) throws IOException {
Properties p = new Properties();
System.out.println("读取前:" + p);
p.load(new FileInputStream("config.properties"));
System.out.println("读取后:" + p);
p.setProperty("tel","1878888");
p.store(new FileOutputStream("config.properties"),"xxx");//comments是对列表进行描述,不描述可以改成null
System.out.println("修改后:"+p);
}
}