IO流
1 字节流
InputStream
与OutputStream
是两个抽象类,是字节流的基类,所有具体的字节流实现类都是分别继承了这两个类。
字符是一个一个字节读取的,可以读取一切文件,那他读取文本文件可以吗?当读取英文字符时是可以的,因为一个字节表示一个英文字符,可是当我们读取到中文时,一个中文一般由多个字节来表示,如果字节流第一次读取读到一个中文字符的前一般字节,将它输出,这时中文字符就丢失了,所以我们引入了字符流来读取文本文件,而用字节流读取图像视频之类的文件。
当然字节流依然可以读取到字符,下面演示字节流读取中文(不推荐,可能会乱码)
public static void main(String[] args) throws IOException {
File file = new File("2.txt");
//写入字符
String s = "昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。";
FileOutputStream fos = new FileOutputStream(file);
fos.write(s.getBytes());//字节流只能读写字节,所以需要将字符串转为字节
//读取
FileInputStream fis = new FileInputStream(file);
byte[] arr= new byte[1024];
int len = 0;
StringBuilder sb = new StringBuilder();
while((len=fis.read(arr))!=-1){//如果刚好一个中文字符被分开读取了,那就会乱码
String s2 = new String(arr, 0, len);//字节数组转为字符串
sb.append(s2);//字符串拼接
}
System.out.println(sb);//昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。
}
插入
结点流与处理流之间的关系
在诸多处理流中,有一个非常重要,那就是缓冲流。
我们知道,程序与磁盘的交互相对于内存运算是很慢的,容易成为程序的性能瓶颈。减少程序与磁盘的交互,是提升程序效率一种有效手段。缓冲流,就应用这种思路:普通流每次读写一个字节,而缓冲流在内存中设置一个缓存区,缓冲区先存储足够的待操作数据后,再与内存或磁盘进行交互。这样,在总数据量不变的情况下,通过提高每次交互的数据量,减少了交互次数。
2 字符流
与字节流类似,字符流也有两个抽象基类,分别是Reader
和Writer
。其他的字符流实现类都是继承了这两个类。
使用字符流输入输出字符
public static void main(String[] args) throws IOException {
File file = new File("2.txt");
//写入字符
String s = "昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。";
FileWriter fw = new FileWriter(file);
fw.write(s);
//读取
FileReader fr = new FileReader(file);
int len = 0;
char[] arr = new char[1024];
StringBuilder sb = new StringBuilder();
while((len=fr.read(arr))!=-1){
sb.append(arr);
}
System.out.println(sb);//输出为空
}
咦?为什么我们输出为空呢?
注意:关闭资源时,与FileOutputStream不同。 如果不关闭,数据只是保存到缓冲区,并未保存到文件。
有两种解决方法,一是每次写入后刷新缓冲区,二是关闭流。
flush :刷新缓冲区,流对象可以继续使用。
close :先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
public static void main(String[] args) throws IOException {
File file = new File("2.txt");
//写入字符
String s = "昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。";
FileWriter fw = new FileWriter(file);
fw.write(s);
fw.flush();
//读取
FileReader fr = new FileReader(file);
int len = 0;
char[] arr = new char[1024];
StringBuilder sb = new StringBuilder();
while((len=fr.read(arr))!=-1){
sb.append(arr,0,len);//注意,一定要写清楚追加长度,不让把数组中空的也加进来会乱码
}
// fr.close();
// fw.close();
System.out.println(sb);//输出为空
}
3 字节缓冲流
public static void main(String[] args) throws IOException {
File file = new File("2.txt");
String s = "昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
//写入字符
bos.write(s.getBytes());
bos.flush();
//读取
int len = 0;
byte[] arr = new byte[1024];
StringBuilder sb = new StringBuilder();
while((len=bis.read(arr))!=-1){
String s2 = new String(arr,0,len);
sb.append(s2);
}
System.out.println(sb);
}
4 字符缓冲流
public static void main(String[] args) throws IOException {
File file = new File("2.txt");
String s = "昨日同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈。";
BufferedReader br = new BufferedReader(new FileReader(file));
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
//写入
bw.write(s);
bw.flush();
//读取
int len = 0;
char[] arr = new char[1024];
StringBuilder bs = new StringBuilder();
while((len=br.read(arr))!=-1){
bs.append(arr,0,len);
}
System.out.println(bs);
}
5 转换流
转换流 java.io.InputStreamReader ,是Reader的子类,是从字节流到字符流的桥梁。它读取字节,并使用指定 的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。
转换流 java.io.OutputStreamWriter ,是Writer的子类,是从字符流到字节流的桥梁。使用指定的字符集将字符 编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。
6 序列化流
对象可以被序列化的条件:
Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该 对象的数据 、 对象的 类型 和 对象中存储的属性 等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。
该类必须实现 java.io.Serializable 接口, Serializable 是一个标记接口,不实现此接口的类将不会使任 何状态序列化或反序列化,会抛出 NotSerializableException 。
该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用 transient 关键字修饰。 (static修饰的属性无法被序列化)
**注意:**对于JVM可以反序列化对象,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个 ClassNotFoundException 异常。 另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操 作也会失败,抛出一个 InvalidClassException 异常。
-
该类的序列版本号与从流中读取的类描述符的版本号不匹配
-
该类包含未知数据类型
-
该类没有可访问的无参数构造方法
反序列化进行连续读取时,如果读取到最后一个,再读取下一个为空的值时会抛出异常,我们可以再序列化所有数据后,在追加一个null。
public class ObjectIO { public static void main(String[] args){ Student s1 = new Student(12,"zhansagn"); Student s2 = new Student(13,"lsii"); Student s3 = new Student(14,"wangwu"); Student s4 = new Student(15,"zhaoliu"); ObjectInputStream ois = null; ObjectOutputStream oos = null; try { File file = new File("obj.txt"); oos = new ObjectOutputStream(new FileOutputStream(file)); oos.writeObject(s1); oos.writeObject(s2); oos.writeObject(s3); oos.writeObject(s4); oos.writeObject(null);// ois = new ObjectInputStream(new FileInputStream(file)); Object o = null; while((o=ois.readObject())!=null){ Student s = (Student) o; System.out.println(s); } } catch (IOException e) { // e.printStackTrace(); // System.out.println("读取结束"); } catch (ClassNotFoundException e) { e.printStackTrace(); }finally { if(ois!=null){ try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } if(oos!=null){ try { oos.close(); } catch (IOException e) { e.printStackTrace(); } } } } } @AllArgsConstructor @NoArgsConstructor @Data class Student implements Serializable{ private static final long serialVersionUID = -2985676753883318447L; int age; String name; }
7 Properties
public static void main(String[] args) throws IOException {
File file = new File("pro.properties");
Properties pro = new Properties();
pro.load(new InputStreamReader(new FileInputStream(file),"GBK"));
String name = pro.getProperty("name");
System.out.println(name);
Set<String> strings = pro.stringPropertyNames();
for (String s : strings) {
System.out.println(s+"="+pro.getProperty(s));
}
}