1.1基于数组操作的流
ByteArrayInputStream可以基于字节数组创建输入流
构造方法:
//创建一个带有缓冲字节数据的字节数组输出流
ByteArrayInputStream(byte[] buf);
//创建一个带有缓冲字节数据的字节数组输出流
ByteArrayInputStream(byte[] buf,int off,int len);
主要方法:
int read();//返回此输入流的下一个字节
int read(byte []b,intvoff,int len);//将输入流中的len个字节如入到字节数组b中。
ByteArrayOutputStream:可以把数据输出字节数组中
构造方法:
ByteArrayOutputStream();
ByteArratOutputStream(int size);//创建一个指定缓冲区大小的字节数组输出流。
主要方法:
String toString();//使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。
void write(int ch);//将该字节写入到输出流中。
void write(byte[]b,int off,int length);//将该字节数组b,length个字节写入到该输出流中。
代码如下:
输入:
@Test
/**
* ByteArrayInputStream可以基于字节数组创建输入流
*/
public void test1() throws IOException {
byte[] arr={97,98,99,100,101,102};
ByteArrayInputStream in = new ByteArrayInputStream(arr);
int length = -1;
byte[] buffer = new byte[3];
while ((length=in.read(buffer))!=-1){
System.out.println(Arrays.toString(buffer));
}
}
结果演示:
输出:
@Test
/**
* ByteArrayOutputStream:可以把数据输出字节数组中
*/
public void test2() throws Exception {
BufferedInputStream in = new BufferedInputStream(new FileInputStream("hello.txt"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int length = -1;
byte[] buffer = new byte[5];
while ((length=in.read(buffer))!=-1){
out.write(buffer,0,length);
}
byte[] data = out.toByteArray();//得到输出字符数组
in.close();
out.close();
System.out.println(Arrays.toString(data));
}
结果演示:
扩:CharArrayReader:基于字符数组产生输入流,CharArrayWriter:输出到字节数组中的输出流,其方法与上例相似
1.2数据流
- 为了方便地操作Java语言的基本数据类型和String的数据,可以使用数据流。
- 数据流有两个类: (用于读取和写出基本数据类型、 String类的数据)
-
- DataInputStream 和 DataOutputStream
- 分别“套接”在 InputStream 和 OutputStream 子类的流上
- DataInputStream中的方法
-
- boolean readBoolean()
- byte readByte()
- char readChar()
- float readFloat()
- double readDouble()
- short readShort()
- long readLong()
- int readInt()
- String readUTF()
- void readFully(byte[] b)
- DataOutputStream中的方法
-
- 将上述的方法的read改为相应的write即可
代码示例:
正确输出:
注意:write与read相对对应,否则会出现输出异常
代码最后要关闭输入输出流close();
据输入流和输出流以机器无关的方式进行写入和读取数据,实际上数据输出流是将java的基本类型,底层存储的时候以字节形式进行存储.而数据输入流读取后数据后,会将字节的进行拼接.得到java基本类型
注意:UTF-8是1-4个字节可变的;GBK是1~2个字节
1.3PrintStream方法
编写代码报错时,我们可以通过PrintStream方法编写日志,方便查找错误
PrintStream特点:
1. 只负责输出,不负责数据的读取
2. 与其他输出流不同,printStream永远不会抛出IOException
3. 有特有的方法
1. PrintStream(File file):输出的目的地是一个文件
2. PrintStream(OutputStream out):输出的目的地是一个字节流
3. PrintStream(String fileName):输出的目的地是文件路径
PrintStream extends OutputStream,继承自父类的成员方法:
1.public void close():关闭此输出流并释放此流相关联的任何系统资源
2.public void flush():刷新此流并强制任何缓冲流的输出字节被写出。
3.public void write(byte[] b):将b.Length字节从指定的字节写入此输出流。
4.public void write(byte[] b,int off,int len):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。
5. public abstract void write(int b):将指定的字节流输出
String s=null;
String s1 = s.toString();
System.out.println(s1);//空指针
编译后:
Exception in thread "main" java.lang.NullPointerException
at com.lina.test.e_printStream.test1.main(test1.java:6)
改写:
public static void main(String[] args) throws FileNotFoundException {
try {
String s=null;
s.toString();//空指针异常
} catch (Exception e) {
//e.printStackTrace();
PrintStream writer = new PrintStream("logo.txt");
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
writer.println(sf.format(new Date())+":"+e.getMessage());
writer.close();
}
}
2023-08-14 06:58:55:null 在log里打印错误
1.4对象流
- 介绍
用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到文件源中(序列化),也能把对象从文件源中还原回来(反序列化)
2.序列化机制
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从
而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传
输到另一个网络节点。
当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
反序列化:用ObjectInputStream类读取基本类型数据或对象的机制注意:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
3.序列化好处
可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原
4.注意
首先,如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可
序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一。
- Serializable(主要实现这个接口)
- Externalizable
对象流使用时,自定义对象必须实现Serializable接口,否则会抛出java.io.NotSerializableException
凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
1、确保不同版本有不同的UID
2、序列化一个类实例,更改一个字段或者添加一个字段,不设置UID,任何更改导致无法反序列化实例,并抛出异常,如果添加UID,反序列化旧实例,新增加或者 更改字段被设为初始值,对象为null
private static final long serialVersionUID = 1755878437777619416L;
5.步骤
使用对象节点流序列化
1. 创建节点输出流(FileOutputStream)
2. 创建对象流(ObjectOutputStream)
3. 调用 ObjectOutputStream 对象的 writeObject(对象) 方法输出可序列化对象
4. 关闭流close
public void test1() throws Exception {
User user = new User(18,"l","China");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user"));
out.writeObject(user);
out.close();
System.out.println(user);
}
输出序列化对象后,需要进行反序列化操作才能得到内容!否则乱码!
使用对象反序列化
1. 创建节点输出流(FileInputStream)
2. 创建对象流(ObjectInputStream)
3. 调用 ObjectOutputStream 对象的 readObject() 方法输出可序列化对象
4. 关闭流
public void test2() throws Exception {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("user"));
User user = (User) in.readObject();
System.out.println(user);
in.close();
}