Java基础进阶_day12_(其他IO流)
1.数据输入流和输出流
数据输入流和输出流:DataInputStream,DataOutputStream可以按照基本数据类型大小读写数据.
# DataInputStream类:
构造方法:public DataInputStream(InputStream in):使用指定的底层 InputStream 创建一个 DataInputStream.
# DataOutputStream类:
构造方法:public DataOutputStream(OutputStream out)创建一个新的数据输出流,将数据写入指定基础输出流.计数器 written被设置为零.
# 注意事项:
存取的使用的读写方法是相对应的,不能使用字符的读方法去读取布尔类型的值.
案例
public class My_DataStream_Demo {
public static void main(String[] args) throws Exception{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("d.txt"));
dos.writeDouble(12.34);
dos.writeFloat(23.3F);
dos.writeLong(89L);
dos.close();
DataInputStream dis = new DataInputStream(new FileInputStream("d.txt"));
System.out.println(dis.readDouble());
System.out.println(dis.readFloat());
System.out.println(dis.readLong());
dis.close();
}
}
2. 内存输出流
# 内存输出流:该输出流可以向内存中写数据, 把内存当作一个缓冲区, 写出之后可以一次性获取出所有数据.
# 内存输出流分类:不需要关闭流,可以直接输出对象,调用toString方法
* 字节输出流:
ByteArrayInputStream:
构造方法:public ByteArrayInputStream(byte[] buf):使用一个字节数组作为缓冲区
ByteArrayOutputStream:
构造方法:public ByteArrayOutputStream():创建一个新的 byte 数组输出流.
* 字符输出流:
CharArrayReader
构造方法:public CharArrayReader(char[] buf):根据指定的 char 数组创建一个 CharArrayReader.
CharArrayWrite
构造方法:public CharArrayWriter():创建一个新的 CharArrayWriter.
* 字符串输出流:
StringReader:public StringReader(String s):创建一个新字符串 reader.
StringWriter:public StringWriter():使用默认初始字符串缓冲区大小创建一个新字符串 writer.
案例
public class My_InternalStream_Demo {
public static void main(String[] args) throws IOException {
// 字符输出流
// test01();
// 字符输出流
// test02();
// 字符串输出流
// test03();
// 测试题
// 定义一个文件输入流,调用read(byte[] b)方法,将a.txt文件中的内容打印出来(byte数组大小限制为5)
test04();
}
public static void test04() throws FileNotFoundException, IOException {
// 定义一个文件输入流,调用read(byte[] b)方法,将a.txt文件中的内容打印出来(byte数组大小限制为5)
FileInputStream fis = new FileInputStream("a.txt");
// 使用字节内出输出流接收读取的字节
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bys = new byte[5];
int len = 0;
while((len = fis.read(bys)) != -1) {
baos.write(bys, 0, len);
}
// 直接输出对象调用toString方法
System.out.println(baos);
fis.close();
}
public static void test03() throws IOException {
StringWriter sw = new StringWriter();
sw.write("somnus");
sw.write("\r\n");
sw.write("hello");
sw.write("\r\n");
sw.write("world");
String s = sw.toString();
StringReader sr = new StringReader(s);
int by = 0;
while((by = sr.read()) != -1) {
System.out.print((char)by);
}
}
public static void test02() throws IOException {
CharArrayWriter caw = new CharArrayWriter();
caw.write("somnus");
caw.write("\r\n");
caw.write("hello");
caw.write("\r\n");
caw.write("World");
char[] chs = caw.toCharArray();
CharArrayReader car = new CharArrayReader(chs);
int by = 0;
while((by = car.read()) != -1) {
System.out.print((char)by);
}
}
public static void test01() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(98);
baos.write(99);
baos.write(96);
baos.write(97);
byte[] bys = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bys);
System.out.println(bais.read());
System.out.println(bais.read());
System.out.println(bais.read());
System.out.println(bais.read());
}
}
3.对象操作流
# 对象操作流:该流可以将一个对象写出,或者读取一个对象到程序中,也就是执行了序列化和反序列化的操作.
* 序列化:将对象以流的形式写到文件中;
* 反序列化:将对象以流的形式从文件中读取出来.
# 注意事项:
* 需要对象所属的类实现Serializable接口,才能被序列化;
* 为防止读取时出现InvalidClassException错误,需要给类定义一个ID号(自动生成);
* 属性不要被序列化时使用transient关键字修饰
* ObjectOutputStream类:对象输出流
* ObjectInputStream类:对象输入流
案例
public class My_ObjectStream_Demo {
public static void main(String[] args) throws Exception {
// 测试对象输入输出流
test01();
// 使用集合的方式存储对象
// test02();
}
public static void test02() throws IOException, FileNotFoundException,
ClassNotFoundException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
"c.txt"));
ArrayList<Person> list = new ArrayList<Person>();
Person p1 = new Person("somnus", 23);
Person p2 = new Person("somnus", 24);
list.add(p1);
list.add(p2);
oos.writeObject(list);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c.txt"));
@SuppressWarnings("unchecked")
ArrayList<Person> reList = (ArrayList<Person>)ois.readObject();
for (Person p : reList) {
System.out.println(p);
}
ois.close();
}
public static void test01() throws IOException, FileNotFoundException,
ClassNotFoundException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
"c.txt"));
Person p1 = new Person("somnus", 23);
Person p2 = new Person("somnus", 24);
oos.writeObject(p1);
oos.writeObject(p2);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c.txt"));
Object obj = ois.readObject();
Object obj1 = ois.readObject();
System.out.println(obj);
System.out.println(obj1);
ois.close();
}
}
class Person implements Serializable {
private static final long serialVersionUID = -6099349754495282989L;
private String name;
private transient int age;
public Person() {
}
public Person(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 "Person [name=" + name + ", age=" + age + "]";
}
}
4.打印流
# 打印流:该流可以很方便的将对象的toString()结果输出, 并且自动加上换行, 而且可以使用自动刷出的模式,自动刷新方法只是针对println方法.
* PrintStream类:字节打印流,可以打印任意类型的数据
构造方法:
public PrintStream(OutputStream out,boolean autoFlush):创建新的打印流,并可以自动刷新数据.
* PrintWriter类:字符打印流
# 注意事项:
* print()和println()方法可以打印数据,但前者没有空参数的方法;
* 输出流只能操作目的数据,不能操控源数据;
* 输出流可以自动将数据刷新到文件,可以不使用flush方法,但是流还是需要关闭.
案例
public class My_PrintStream_Demo {
public static void main(String[] args) throws IOException {
// System.out调用的实际上是printstream输出流实例.
PrintStream ps = System.out;
ps.print(true);
ps.print(23.4);
// 测试自动刷新数据
PrintStream ps2 = new PrintStream(new FileOutputStream("e.txt"), true);
ps2.write(98); // 直接将98数字直接输出,打印的是b
ps2.print(98); // 输出前先将98转换为字符串再打印,打印的是98
ps2.write(99);
ps2.close();
// 复制文本文件
test01();
}
public static void test01() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
PrintStream ps = new PrintStream(new FileOutputStream("n.txt"));
String line = null;
while((line = br.readLine()) != null) {
ps.println(line);
}
ps.close();
br.close();
}
}
5.Properties类
# Properties的概述,一般作为Map集合使用
Properties 类表示了一个持久的属性集;
Properties 可保存在流中或从流中加载;
属性列表中每个键及其对应值都是一个字符串.
# 构造方法:
public Properties():创建一个无默认值的空属性列表.
# 特殊功能:操作的均是字符串
public Object setProperty(String key,String value)
public String getProperty(String key)
public Enumeration<String> stringPropertyNames()
# Properties的load()和store()功能:存储键值对元素,必须是使用等号连接,存储的只能是String类型的键值对元素
public void load(InputStream inStream):从输入流中读取属性列表(键和元素对).
public void load(Reader reader):按简单的面向行的格式从输入字符流中读取属性列表(键和元素对).
public void store(Writer writer,String comments):以适合使用 load(Reader)方法的格式,将此Properties表中的属性列表(键和元素对)写入输出字符.
public void store(OutputStream out,String comments):以适合使用 load(InputStream)方法加载到Properties表中的格式,将此Properties表中的属性列表(键和元素对)写入输出流.
案例
public class My_Properties_Demo {
public static void main(String[] args) throws IOException, IOException {
// 作为Map集合使用
Properties p = new Properties();
p.put(12, 123);
System.out.println(p.get(12));
//特殊功能
p.setProperty("somnus", "0809");
p.setProperty("sunmos", "0729");
System.out.println(p.getProperty("somnus"));
Set<String> names = p.stringPropertyNames();
for (String n : names) {
System.out.println(p.getProperty(n));
}
// Properties的load()和store()功能
// load()功能
Properties p = new Properties();
p.load(new FileInputStream("g.txt"));
Set<String> names = p.stringPropertyNames();
System.out.println(names);
// store()功能
Properties p = new Properties();
p.put("0809", "somnus");
p.setProperty("sunmos", "0729");
p.store(new FileOutputStream("h.txt"), "输出数据");
}
}
6.随机访问流
# 随机访问流:RandomAccessFile类,需要关闭流.
RandomAccessFile类不属于流,是Object类的子类.但它融合了InputStream和OutputStream的功能.
支持对随机访问文件的读取和写入.
# 构造方法:
public RandomAccessFile(String name,String mode):创建从中读取和向其中写入的随机访问文件流,该文件具有指定名称.mode是读取文件的模式,rw等
# 方法:
public long getFilePointer():返回此文件中的当前偏移量.
public int read():读取一个字节数据;
public void seek(long pos):设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作.
案例
public class My_RandomAccessFile_Demo {
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile("a.txt", "rw");
System.out.println(raf.getFilePointer());
System.out.println((char)raf.read());
System.out.println(raf.getFilePointer());
raf.seek(10);
System.out.println((char)raf.read());
System.out.println(raf.getFilePointer());
}
}
7.序列流
# 序列流:序列流可以把多个字节输入流整合成一个, 从序列流中读取数据时, 将从被整合的第一个流开始读, 读完一个之后继续读第二个, 以此类推.
# SequenceInputStream类:
* 构造方法:
public SequenceInputStream(InputStream s1,InputStream s2):创建合并两个字节输入流的序列流对象
public SequenceInputStream(Enumeration<? extends InputStream> e):创建含多个输入流的序列流对象,Enumeration可以通过Vector集合获得.
# 注意事项:只能使用输出字节流写数据.
案例
public class My_SequenceInputStream_Demo {
public static void main(String[] args) throws IOException {
// 两个输入流复制文件
test01();
// 多个输入流复制文件
// test02();
}
public static void test02() throws FileNotFoundException, IOException {
Vector<InputStream> ve = new Vector<InputStream>();
FileInputStream fis1 = new FileInputStream("a.txt");
FileInputStream fis2 = new FileInputStream("b.txt");
FileInputStream fis3 = new FileInputStream("c.txt");
ve.add(fis1);
ve.add(fis2);
ve.add(fis3);
Enumeration<InputStream> elements = ve.elements();
SequenceInputStream sis = new SequenceInputStream(elements);
FileOutputStream fos = new FileOutputStream("e.txt");
int by = 0;
while((by = sis.read()) != -1) {
fos.write(by);
}
fos.close();
sis.close();
}
public static void test01() throws FileNotFoundException, IOException {
SequenceInputStream sis = new SequenceInputStream(new FileInputStream("a.txt"), new FileInputStream("b.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("c.txt"));
int by = 0;
while((by = sis.read()) != -1) {
bos.write(by);
}
bos.close();
sis.close();
}
}
8.标准输入输出流
# 标准输入输出流:
System.in是InputStream, 标准输入流, 默认可以从键盘输入读取字节数据,标准输入流只有一个,多个InputStream对象使用同一个流,并且不用关闭.
System.out是PrintStream, 标准输出流, 默认可以向Console中输出字符和字节数据
# 修改标准输入输出流:
* 修改输入流: System.setIn(InputStream)
* 修改输出流: System.setOut(PrintStream),修改之后需要手动将流关闭.
# 键盘录入数据的方式:
* A:Scanner方式
* B:BufferedReader的readLine()方法:BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
案例
public class My_StandardStream_Demo {
public static void main(String[] args) throws IOException {
// 测试标准输入输出流
// test01();
// 修改标准输入流
// test02();
// 修改标准输入输出流
// test03();
// 键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println(br.readLine());
br.close();
}
public static void test03() throws FileNotFoundException, IOException {
System.setIn(new FileInputStream("a.txt"));
System.setOut(new PrintStream("f.txt"));
// 获取标准输入流
InputStream is = System.in;
PrintStream ps = System.out;
byte[] bys = new byte[1024];
int len = 0;
while((len = is.read(bys)) != -1) {
ps.write(bys, 0, len);
}
is.close();
ps.close();
}
public static void test02() throws FileNotFoundException, IOException {
System.setIn(new FileInputStream("a.txt"));
// 获取标准输入流
InputStream is = System.in;
// 定义内存输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int by = 0;
while((by=is.read()) != -1) {
baos.write(by);
}
is.close();
// 输出数据
System.out.println(baos);
}
public static void test01() throws IOException {
// 获取标准输入流
InputStream is = System.in;
// 获取标准输出流
PrintStream ps = System.out;
// 每次读取一个字节数据
System.out.println(is.read());
ps.print(23.34);
}
}