- 按操作数据单位分:字节流byte(8bit),字符流char[](16 bit)
- 按流向分:输入流、输出流
- 按角色分:节点流:直接作用在文件上、处理流(在节点流的基础上再加上个流)
注意:在UTF-8的中文占三个字节,UniCode、GBK中占俩字节
| 抽象基类 | 字节流 | 字符流 |
|---|---|---|
| 输入流 | InputStream | Reader |
| 输出流 | OutputStream | Writer |
| 作用 | 图片、视频(非文本) | 用于处理文本文件 |
作用:用于处理设备之间的数据传输。如:读/写文件、网络通讯
1.2、IO流体系| 分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
|---|---|---|---|---|
| 抽象基类 | InputStream | OutputStream | Reader | Writer |
| 访问文件(节点流) | FileInputStream | FileOutputStream | FileReader | FileWriter |
| 访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
| 访问管理 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
| 访问字符串 | StringReader | StringWriter | ||
| 缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
| 转换流 | InputStreamReader | OutputStreamWriter | ||
| 对象流 | ObjectInputStream | ObjectOutputStream | ||
| 打印流 | PringOutputStream | PrintWriter | ||
| 推回输入流 | PushbackInputStream | PushbackReader | ||
| 特殊流 | DataInputStream | DataOutputStream |
记忆:从不同的角度:主要以尾部为主:如果以InputStream输入流、OutputStream输出流结尾,则为字节流。如果以Reade输入流、Writer输出流结尾,则为字符流
字符输入流重点说明:
- read()的理解:返回读入的一个字符,如果达到文件末尾,返回-1,表示已读完
- 异常的处理:为了保证流资源一定可以执行关闭操作,需要try-catch-finally处理
- 读入文件一定存在,否则报FileNotFoundException
@Test
public void IOS(){
FileReader reader = null;
try {
//实例化file类的对象,指明要操作的文件
File file = new File("Sleep.txt");
//提供具体的字符流
reader = new FileReader(file);
//定义一个整形变量记录每次读入数据个数
int data;
//循环读取文件中的字符,当文件中的字符等于-1时,则不在读取
//表示读取完
while((data = reader.read()) != -1){
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//防止找不到文件,报空指针异常,造成流未关闭
if(reader != null)
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testIOS2(){
FileReader fileReader = null;
try {
File file = new File("Sleep.txt");
fileReader = new FileReader(file);
//每次读取5个字符
char[] chars = new char[5];
//记录每次读入到chars数组中的字符个数
int len;
while ((len = fileReader.read(chars)) != -1) {
for (int i = 0; i < len; i++) {
System.out.print(chars[i]);
}
// String string = new String(chars,0,len);
// System.out.print(string);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fileReader != null){
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
改变:
//每次读取5个字符
char[] chars = new char[5];
//int len;
while ((fileReader.read(chars)) != -1) {
String string = new String(chars,0,chars.length);
System.out.print(string);
}
字符输出流:
重点说明
-
输出操作:对应的File对应硬盘中文件可以不存在,如果不存在,会在输出过程中自动创建
-
File对应硬盘中文件存在:
- 如果流使用的构造器是:FileWriter(file,false)/FileWriter(file),对原有的数据文件进行覆盖
- 如果流使用的构造器是:FileWriter(file,true),则不会对原有的数据文件进行覆盖,而是在原有的数据文件之后做添加操作
-
@Test
public void testIOS3(){
FileWriter fileWriter = null;
FileWriter fileWriters = null;
try {
File file = new File("ten.txt");
fileWriter = new FileWriter(file,true);
fileWriters = new FileWriter(file,false);
String is = "从前从前n" +
"有一座山n" +
"山上有座庙n" +
"庙里有个和尚n" +
"和尚说n" +
"施主:从哪来,到哪去呀n" +
"施主说:我从东土大唐来,去到西天取经";
String i = "《中央日报》是韩国较全面、值得信赖的新闻载体之一,同时也是平面媒体的创新者。其推行的编辑管理模式首获成功。《中央日报》是韩国人较爱读的报纸,以其可靠、深入的新闻报道吸引了韩国高级知识分子和高收入读者的关注。《中央日报》还是韩国第一家创办教育报的媒体,致力于培养未来读者群。该报还同《国际先驱论坛》合作出版英文日报《JoongAng Daily》。另外,中央日报集团还出版有韩文版《新闻周刊》、《福布斯》、《时尚》等国际性杂志。除此之外,《中央日报》还通过因特网提供音视频的时代华纳动画片和美国有线电视新闻网新闻服务。1995年,《中央日报》创办了亚洲首家因特网新闻服务网。这家网站也一直是最受欢迎的新闻媒体网站。";
fileWriter.write(is,0,is.length());
fileWriter.write("《中央日报》");//直接写
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileWriter != null){
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}else if (fileWriters != null){
try {
fileWriters.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结论:
- 对于文本文件(.txt,.java、.c、.c++…),使用字符流处理
- 对于非文本文件、视频文件(.jpg、.mp3、.mp4、.avi、.doc、.ppt…),使用字节流处理
字节输入流、字节输出流
重点说明:读取非文本文件时,不能使用string进行读取
目的:实现对图片的复制
@Test
public void testIOS5(){
//重点说明:读取非文本文件时,不能使用string进行读取
//创建类对象
FileInputStream inputStream = null;
FileOutputStream outputStream = null;
try {
File file = new File("beauty.jpg");
File Copyfile = new File("beauty3.jpg");
//创建流
inputStream = new FileInputStream(file);
outputStream = new FileOutputStream(Copyfile);
//读取操作
//因为是字节流,所以用到byte[]数组
byte[] bytes = new byte[5];
//定义一个变量记录读取字节个数
int len;
//循环
while ((len = inputStream.read(bytes)) != -1){
outputStream.write(bytes,0,len);
// String s = new String(bytes,0,len);
// System.out.println(s);
}
System.out.println("复制成功!");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (inputStream != null){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (outputStream != null){
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符缓冲读、写流
* */
@Test
public void TestOutputStream(){
//造文件
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
File First = new File("six.txt");
File Second = new File("Error.txt");
//造流
FileReader fir = new FileReader(First);
FileWriter fwr = new FileWriter(Second);
//造缓冲流
bufferedReader = new BufferedReader(fir);
bufferedWriter = new BufferedWriter(fwr);
//读取细节
//小推车,容纳十个字符
char[] BufferChar = new char[10];
//定义一个计算长度
int len;
//循环读取,直至-1
while ((len =bufferedReader.read(BufferChar)) != -1){
bufferedWriter.write(BufferChar,0,len);
//string的缓冲字符
StringWriter writer = new StringWriter();
writer.write(BufferChar,0,len);
System.out.println(writer);
}
//String len;
//readLine()该方法没有换行符,所有语句全部都成为一条句子
//while ((len =bufferedReader.readLine()) != null){
//bufferedWriter.write(len);
//newLine():添加换行符
// bufferedWriter.newLine();
// }
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bufferedReader != null){
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedWriter != null){
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字节读、写缓冲流
@Test
public void testBufferInOnPutStream(){
BufferedInputStream Bfis = null;
BufferedOutputStream Bfos = null;
try {
//造文件
File Target = new File("beauty.jpg");
File Result = new File("beauty3.jpg");
//造流
FileInputStream fis = new FileInputStream(Target);
FileOutputStream fos = new FileOutputStream(Result);
//造字节缓冲流
Bfis = new BufferedInputStream(fis);
Bfos = new BufferedOutputStream(fos);
//读写操作
byte[] BuffByte = new byte[10];
//定义计算长度
int len;
//循环读取
while ((len = Bfis.read(BuffByte)) != -1){
Bfos.write(BuffByte,0,len);
}
System.out.println("缓冲流复制完成");
} catch (IOException e) {
e.printStackTrace();
}finally {
if (Bfis != null){
try {
Bfis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (Bfos != null){
try {
Bfos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
缓冲流总结:
- 缓冲流
- BufferedInputStream
- BufferedOutputStream
- BufferedReader
- BufferedWriter
- 作用:缓冲流内部提供了一个缓冲区:默认值为8192,并且提供了flush()方法,每次刷新的时候,不管缓冲区有多少数据,都会被读、写出去,当读写数据快到该默认值时,会自动刷新当前的默认空间,提高流的读取、写入速度。
定义:
- 转换流–>属于字符流
- InputStreamReader:将一个字节的输入流转换为字符的输入流
- OutputStreamWriter:将自已字符的输出流转换为字节的输出流
- 作用:提供字节流与字符流之间的转换
- 解码:从字节、字节数组 —> 字符数组、字符
编码: 从字符数组、字符 —> 字节、字节数组
4.字符集
重点注意:
streamReader = new InputStreamReader(fileInputStream,"gbk");
@Test
public void testInputStreamReader(){
InputStreamReader streamReader = null;
try {
//创建字节流,将字节文件导入
FileInputStream fileInputStream = new FileInputStream("eight.txt");
//创建字符转换流
//streamReader = new InputStreamReader(fileInputStream);
//定义字符编码格式,默认为UTF-8的编码格式
streamReader = new InputStreamReader(fileInputStream,"gbk");
//定义小推车,一次装十个字节
char[] ReaderChar = new char[10];
//抓取长度
int len;
//循环
while ((len = streamReader.read(ReaderChar)) != -1){
String s = new String(ReaderChar,0,len);
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (streamReader != null){
try {
streamReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
对象流
一、定义
- 对象流:ObjectInputStream、ObjectOutputStream
- 作用:用于存储和读取基本数据类型数据或对象的处理流,强大之处是可以把Java中的对象写入到数据源中,也能从数据源中还原回来。
- 序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
- 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
- 注意:①ObjectInputStream和ObjectOutputStream不能序列化static和transient修饰的成员变量。②要想实现可序列化操作,除了实现序列化接口以外,还必须保证其内部属性都是可序列化的,默认情况下基本数据类型都是可序列化的
二、简述序列化
-
何为对象序列化机制?
- 允许把内存中的Java对象转换成与平台无关的二进制流持久的存储在磁盘中。通过网络编程的方式将二进制流传输到另一个网络节点。如:ObjectInputStream
- 当其他网络程序获取到该二进制流,就可以自动转换成Java对象
-
好处
- 可将任何实现了Serializable接口的对象转换为字节数据,使其在保存和传输时可被还原
- 如果需要让某个对象支持序列化机制,则必须让对象所处的类及其属性是可序列化的,让某个类实现可序列化,必须实现如下俩接口之一:Serializable、Externalizable,否则会抛出NotSerializableException异常
-
实例:
-
public class Person implements Serializable { //在传输的过程中保证序列化对象的唯一性,防止在传输多个序列化对象时错乱 public static final long serialVersionUID = 15L; private int age; private String name; // private int id; // @Override // public String toString() { // return "Person{" + // "age=" + age + // ", name='" + name + ''' + // ", id=" + id + // '}'; // } // // public int getId() { // return id; // } // // public void setId(int id) { // this.id = id; // } // public Person(int id) { // this.id = id; // } public Person(int age, String name) { this.age = age; this.name = name; } public int getAge() { return age; } @Override public String toString() { return "Person{" + "age=" + age + ", name='" + name + ''' + '}'; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } } //方法 @Test public void testSerializable(){ ObjectOutputStream oos = null; FileOutputStream fos = null; try { //造文件 fos = new FileOutputStream("Object.dat"); //造流 oos = new ObjectOutputStream(fos); //方法 //序列化对象 Person person = new Person(22,"习大大"); oos.writeObject(person); // String s = new String("I like beijing"); oos.writeObject(s); oos.flush(); } catch (IOException e) { e.printStackTrace(); }finally { //关流 try { oos.close(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void testBackSerializable(){ ObjectInputStream ois = null; try { //造文件 FileInputStream fis = new FileInputStream("Object.dat"); //造流 ois = new ObjectInputStream(fis); //拿出序列化对象的数据 Object obj = ois.readObject(); Person person = (Person) obj; System.out.println(person); //方法 Object o = ois.readObject(); String st = (String) o; System.out.println("反序列化出来的字符串:"+st); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); }finally { //关流 try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } }
-
定义
- 创建RamdomAccessFile类实例需要指定一个mode参数,该参数指定RamdomAccessFile的访问模式;
- r:以只读的方式打开
- rw:读取和写入
- rwd:读取和写入,同时同步文件内容的更新
- rws:读取和写入,同时同步文件内容和元数据的更新
- 如果模式为只读r。则不会创建文件,而是读取一个已经存在的文件,如果读取的文件不存在则会出现异常。如果模式为读写rw,如果文件不存在则会创建文件,如果文件存在则不会创建
- JDK1.6上写到,每次write数据时,“rw"模式,数据不会立即写到硬盘中,而"rwd”,数据会被立即写到硬盘中,如果写数据的过程中出现异常,"rwd"模式中的数据被保存到硬盘中,而"rw"的数据则全部丢失
- 创建RamdomAccessFile类实例需要指定一个mode参数,该参数指定RamdomAccessFile的访问模式;
-
使用
-
RandomAccessFile的使用 1、直接继承于java.lang.Object类,实现了DataOutput,DataInput、Closeable接口 即为输入流,又为输出流 2、作为输出流时,写出到的文件如果不存在,在执行过程中会自动创建文件 如果文件存在,则会对原有文件内容进行覆盖(默认情况下从头覆盖) 注意:在写的过程中,mode必须为‘rw’,因为RandomAccessFile并没有定义‘w'为写 @Test public void TestRandomAccessFile() { RandomAccessFile raf = null; RandomAccessFile rafs = null; try { //造文件、造流 raf = new RandomAccessFile(new File("beauty.jpg"), "r"); rafs = new RandomAccessFile(new File("beauty6.jpg"), "rw"); //定义一个字节数组小车 byte[] bytes = new byte[1024]; //定义一个读取常量,记录 int len; //读 while ((len = raf.read(bytes)) != -1) { //写 rafs.write(bytes, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { //关流 if (raf != null) { try { raf.close(); } catch (IOException e) { e.printStackTrace(); } } if (rafs != null) { try { rafs.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void testRW(){ //测试是否全部覆盖还是覆盖长度 RandomAccessFile accessFile = null; try { accessFile = new RandomAccessFile("sevenEleven.txt","rw"); accessFile.write("shenghuojiuxiangyibawuqingdekedao".getBytes()); } catch (IOException e) { e.printStackTrace(); }finally { if (accessFile != null){ try { accessFile.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void testAppend(){ RandomAccessFile raf = null; try { raf = new RandomAccessFile(new File("sevenEleven.txt"),"rw"); //将指针调到下标为3的位置 raf.seek(3); //保存指针为3后面的所有数据到stringBuilder中 StringBuilder stringBuilder = new StringBuilder((int) new File("sevenEleven.txt").length()); byte[] bytes = new byte[20]; int len; while ((len = raf.read(bytes)) != -1){ stringBuilder.append(new String(bytes,0,len)); } //调回指针到3的位置,写入"sdksd" raf.seek(3); raf.write("sdksd".getBytes()); //将stringBuilder中的数据写入到文件中 raf.write(stringBuilder.toString().getBytes()); } catch (IOException e) { e.printStackTrace(); }finally { if (raf != null) { try { raf.close(); } catch (IOException e) { e.printStackTrace(); } } } }
-
###原创文章----南山程序猿



