一篇文章总结java IO流(File、字节流、字符流、特殊操作流)
目录
1.File
1.1 File类概述和构造方法
1.2 File类创建功能
1.3 File类删除功能
1.4 File类判断和获取功能
2.字节流
2.1 IO流概述和分类
2.2 字节流写数据
2.3 字节流写数据的3种方式
2.4 字节流写数据的两个小问题
2.5 字节流写输入加异常处理
2.6 字节流读数据(一次读一个字节数据)
2.7 字节流读数据(一次读一个字节数组的数据)
2.8 案例:复制图片
2.9 字节缓冲流
2.10 案例:复制视频
3.字符流
3.1 为什么会出现字符流
3.2 编码表
3.3 字符串中的编码解码问题
3.4 字符流中的编码解码问题
3.5 字符流写数据的五种方式
3.6 字符流读数据的两种方式
3.7 案例:复制java文件
3.8 字符缓冲流
3.9 案例:复制java文件(字节缓冲流改进版)
3.10 字符缓冲流特有功能
3.11 IO流小结
4.特殊操作流
4.1 标准输入输出流
4.2 打印流
4.3 对象序列化流
4.4 Properties
1.File
1.1 File类概述和构造方法
File:它是文件和目录路径名的抽象表示
- 文件和目录是可以通过File封装成对象的
- 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的。
方法名 | 说明 |
|
通过将给定的路径名字符串转换为抽象路径名来创建新的File实例 |
|
从父路径名字符串和子路径名字符串创建新的File实例 |
|
从父抽象路径名和子路径名字符串创建新的File实例 |
实例:
public class FileTest {public static void main(String[] args) {File f1 = new File("F:\\project\\Java\\java-03-IO\\java.txt");System.out.println(f1);File f2 = new File("F:\\project\\Java\\java-03-IO", "java.txt");System.out.println(f2);File f3 = new File("F:\\project\\Java\\java-03-IO");File f4 = new File(f3, "java.txt");System.out.println(f4);}
}
控制台输出:
1.2 File类创建功能
方法名 | 说明 |
|
当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件 |
|
创建由此抽象路径名命名的目录 |
|
创建由此抽象路径名命名的目录,包括任何必须但不存在的父目录 |
实例:
public class FileTest2 {public static void main(String[] args) throws IOException {File f1 = new File("F:\\project\\Java\\java-03-IO\\java2.txt");System.out.println(f1.createNewFile());File f2 = new File("F:\\project\\Java\\java-03-IO\\test");System.out.println(f2.mkdir());File f3 = new File("F:\\project\\Java\\java-03-IO\\test\\test2\\test3");System.out.println(f3.mkdirs());}
}
控制台输出:
1.3 File类删除功能
方法名 | 说明 |
|
删除由此抽象路径名表示的文件或目录 |
绝对路径和相对路径的区别
- 绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件,例如:F:\\project\\Java\\java-03-IO\\java2.txt
- 相对路径:必须使用取自其他路径名的信息进行解释。例如:java-03-IO\\java3.txt
删除目录时的注意事项:
- 如果一个目录中有内容(目录,文件),不能直接删除,应该先删除目录中的内容,最后才能删除目录。
实例:
public class FileTest3 {public static void main(String[] args) throws IOException {//File f1 = new File("F:\\project\\Java\\java-03-IO\\java2.txt");//在当前模块目录下创建java3.txt文件File f2 = new File("java-03-IO\\java3.txt");System.out.println(f2.createNewFile());//删除当前模块目录下的java.txt文件System.out.println(f2.delete());System.out.println("==========");//在当前模块目录下创建test目录File f3 = new File("java-03-IO\\test2");System.out.println(f3.mkdir());System.out.println("==========");//删除当前模块目录下的test2目录System.out.println(f3.delete());//在当前模块创建一个目录test3,,然后再该目录下创建一个文件java.txtFile f4 = new File("java-03-IO\\test3");System.out.println(f4.mkdir());File f5 = new File("java-03-IO\\test3\\java.txt");System.out.println(f5.createNewFile());//删除当前模块下的目录test3System.out.println(f5.delete());System.out.println(f4.delete());}
}
控制台输出:
1.4 File类判断和获取功能
方法名 | 说明 |
|
测试此抽象路径名表示的File是否为目录 |
|
测试此抽象路径名表示的file是否为文件 |
|
测试此抽象路径名表示的File是否存在 |
|
返回此抽象路径名的绝对路径名字符串 |
|
将此抽象路径名转换为路径名字符串 |
|
返回由此抽象路径名表示的文件或目录的名称 |
|
返回此抽象路径名表示的目录中的文件和目录的名称字符串数组 |
|
返回此抽象路径名表示的目录中的文件和目录的File对象数组 |
实例:
/*方法名 说明
public boolean isDirectory() 测试此抽象路径名表示的File是否为目录
public boolean isFile() 测试此抽象路径名表示的file是否为文件
public boolean exists() 测试此抽象路径名表示的File是否存在
public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串
public String getPath() 将此抽象路径名转换为路径名字符串
public String getName() 返回由此抽象路径名表示的文件或目录的名称
public String[] list() 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
public File[] listFiles() 返回此抽象路径名表示的目录中的文件和目录的File对象数组
*/
public class FileTest4 {public static void main(String[] args) {//public boolean isDirectory() 测试此抽象路径名表示的File是否为目录File f1 = new File("F:\\project\\Java\\java-03-IO");System.out.println(f1.isDirectory());System.out.println("========");//public boolean isFile() 测试此抽象路径名表示的file是否为文件File f2 = new File("F:\\project\\Java\\java-03-IO\\java.txt");System.out.println(f1.isFile());System.out.println("========");//public boolean exists() 测试此抽象路径名表示的File是否存在System.out.println(f1.exists());System.out.println(f2.exists());System.out.println("========");//public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串System.out.println(f1.getAbsolutePath());System.out.println(f2.getAbsolutePath());System.out.println("========");//public String getPath() 将此抽象路径名转换为路径名字符串System.out.println(f1.getPath());System.out.println(f2.getPath());System.out.println("========");//public String getName() 返回由此抽象路径名表示的文件或目录的名称System.out.println(f1.getName());System.out.println(f2.getName());System.out.println("========");//public String[] list() 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组String[] strArray = f1.list();for (String str :strArray) {System.out.println(str);}System.out.println("========");//public File[] listFiles() 返回此抽象路径名表示的目录中的文件和目录的File对象数组File[] files = f1.listFiles();for (File f :files) {System.out.println(f);}}
}
控制台输出:
2.字节流
2.1 IO流概述和分类
IO流概述:
- IO:输入/输出(Input/Output)
- 流:是一中抽象概念,是对数据传输的总称。也就是说数据在设备间的传输成为流,流的本质是数据传输
- IO流就是用来处理设备间数据传输问题的
- 常见的应用:文件复制,文件上传,文件下载
IO流分类:
按照数据的流向
- 输入流:读数据
- 输出流:写数据
按照数据类型来分
- 字节流:字节输入流,字节输出流
- 字符流:字符输入流,字符输出流
一般来说,我们说IO流是按照数据类型来分的
- 如果数据通过记事本打开,我们还可以读懂里面的内容,我们就用字符流
- 否则使用字节流。如果不知道使用哪种类型的流,就使用字节流
2.2 字节流写数据
字节流抽象基类
- InputStream:这个抽象类是表示字节输入流的所有类的超类
- OutputStream:这个抽象类是表示字节输出流的所有类的超类
- 子类名特点:子类名称都是以其父亲名作为子类名的后缀
FileOutputSteam:文件输出流用于将输入写入File
- FileOutputSteam(String name):创建文件输出流以指定的名称写入文件
使用字节输出流写数据的步骤:
- 创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)
- 调用字节输出流对象的写数据方法
- 释放资源(close)
实例:
/*
FileOutputSteam:文件输出流用于将输入写入File
FileOutputSteam(String name):创建文件输出流以指定的名称写入文件
*/
public class FileOutputSteamTest {public static void main(String[] args) throws IOException {//创建字节输出流对象//FileOutputSteam:文件输出流用于将输入写入FileFileOutputStream fos = new FileOutputStream("java-03-IO\\fos.txt");/** 做了三件事情* 1.调用系统功能创建了文件* 2.创建了字节输出流对象* 3.让字节输出流对象指向创建好的文件* *///public void write(int b):将制定的字节写入此文件输出流fos.write(97);//最后都要释放资源 public void close()fos.close();}
}
控制台输出:
2.3 字节流写数据的3种方式
方法名 | 说明 |
|
将指定的字节写入此文件输出流 一次写一个字节数据 |
|
将b.length字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据 |
|
将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流,一次写一个字节数组的部分数据 |
实例:
/*方法名 说明
public void write(int b) 将指定的字节写入此文件输出流一次写一个字节数据
public void write(byte b[]) 将b.length字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据
public void write(byte b[], int off, int len) 将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流,一次写一个字节数组的部分数据
* */
public class FileOutputStreamTest2 {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("java-03-IO\\fos2.txt");//FileOutputStream fos = new FileOutputStream(new File("java-03-IO\\fos2.txt"));//public void write(int b)fos.write(90);fos.write(91);fos.write(92);fos.write(93);//public void write(byte b[])byte[] bytes = {94,95,96,97};fos.write(bytes);byte[] bytes1 = " [][]".getBytes();fos.write(bytes1);//public void write(byte b[], int off, int len)byte[] bytes2 = " {[1!@#$%^&]".getBytes();fos.write(bytes2,0,bytes2.length);}
}
控制台输出:
2.4 字节流写数据的两个小问题
字节流写数据实现换行呢?
- 写完数据后,加换行符\n
字节流写数据如何实现追加写入呢?
- public FileOutputStream(File file, boolean append)
- 创建文件输出流以指定的名称写入文件如果第二个参数为true,则字节将写入文件的末尾而不是开头
实例:
/*
* 字节流写数据实现换行呢?window:\r\nlinux:\nmac:\r字节流写数据如何实现追加写入呢?public FileOutputStream(File file, boolean append)创建文件输出流以指定的名称写入文件如果第二个参数为true,则字节将写入文件的末尾而不是开头
* */
public class FileOutputStreamTest3 {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("java-03-IO\\fos3.txt",true);//写数据,实现换行for (int i = 0; i < 10; i++) {fos.write("java".getBytes());fos.write("\n".getBytes());}fos.close();}
}
控制台输出:
2.5 字节流写输入加异常处理
finally:在异常处理时提供finally块来执行所有清除操作,比如说IO流中的释放资源
实例:
public class FileOutputStreamTest4 {public static void main(String[] args) {FileOutputStream fos = null;try {fos = new FileOutputStream("java-03-IO\\fos4.txt");//fos = new FileOutputStream("X:java-03-IO\\fos4.txt");fos.write("java".getBytes());} catch (IOException e) {e.printStackTrace();}finally {if (fos != null) {try {fos.close();} catch (IOException e) {e.printStackTrace();}}}}
}
控制台输出:
2.6 字节流读数据(一次读一个字节数据)
FileInputStream:从文件系统中的文件获取输入字节
- FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名
使用字节输入流读数据的步骤:
- 创建字节输入流对象
- 调用字节输入流对象的读数据方法
- 释放资源
需求:把文件fos.txt中的内容读取出来,在控制台输出
fos.txt文件中的内容为:
古巨基
博士
与复古一幅一幅一幅一幅付一半
iuhuhiuhiu
!#$$%%$%%$465r56456
实例:
public class FileInputStreamTest {public static void main(String[] args) throws IOException {//创建字节流输入对象FileInputStream fis = new FileInputStream("java-03-IO\\fos.txt");//调用字节输入流对象的读数据方法//public int read(): 从该输入流读取一个字节的数据/*//第一次读取数据int read = fis.read();System.out.println(read);System.out.println((char) read);//第二次读取数据int read2 = fis.read();System.out.println(read2);System.out.println((char) read2);*//*int by = fis.read();while (by != -1) {System.out.println((char)by);by = fis.read();}*///优化上面的程序int by;while ((by=fis.read()) != -1) {System.out.println((char)by);}//释放资源fis.close();}
}
控制台输出:
2.7 字节流读数据(一次读一个字节数组的数据)
需求:把文件fos.txt中的内容读取出来在控制台输出
实例:
public class FileInputStreamTest2 {public static void main(String[] args) throws IOException {//创建字节流输入对象FileInputStream fis = new FileInputStream("java-03-IO\\fos.txt");/*//调用字节输入流对象的读数据方法//public int read(byte b[])byte[] bytes = new byte[5];//第一次读取数据int len = fis.read(bytes);System.out.println(len);//System.out.println(new String(bytes));System.out.println(new String(bytes,0,len));//第二次读取数据len = fis.read(bytes);System.out.println(len);//System.out.println(new String(bytes));System.out.println(new String(bytes,0,len));//第三次读取数据len = fis.read(bytes);System.out.println(len);System.out.println(new String(bytes,0,len));//第四次读取数据len = fis.read(bytes);System.out.println(len);System.out.println(new String(bytes,0,len));*//** hello\r\n* world\r\n** 第一次:hello* 第二次:\r\nwor* 第三次:ld\r\nr 会对第二次读取到的进行替换,正好替换前苏哥* */byte[] bytes = new byte[1024];int len;while ((len=fis.read(bytes)) != -1) {System.out.println(new String(bytes,0,len));}//释放资源fis.close();}
}
控制台输出:
2.8 案例:复制图片
实例:
public class CopyJpgTest {public static void main(String[] args) throws IOException {//根据数据源创建字节输入流对象FileInputStream fis = new FileInputStream("C:\\Users\\Administrator.LAPTOP-62FQ379R\\Desktop\\copy.png");//根据目的地创建字节输出流对象FileOutputStream fos = new FileOutputStream("java-03-IO\\copy.png");//读取数据,复制图片byte[] bytes = new byte[1024];int len;while ((len=fis.read(bytes)) != -1) {fos.write(bytes,0,len);}//释放资源fis.close();fos.close();}
}
查看有没有图片
成功!
2.9 字节缓冲流
字节缓冲流:
- BufferedOutputStream:该类实现缓冲输出流。通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
- BufferedInputStream:创建BufferedInputStream将创建一个内部缓冲区数组。当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节
构造方法:
- 字节缓冲输出流:public BufferedOutputStream(OutputStream out)
- 字节缓冲输入流:public BufferedInputStream(InputStream in)
为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?
- 字节缓冲区仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作
实例:
/*
字节缓冲流:BufferedOutputStream:该类实现缓冲输出流。通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
BufferedInputStream:创建BufferedInputStream将创建一个内部缓冲区数组。当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节构造方法:字节缓冲输出流:public BufferedOutputStream(OutputStream out)
字节缓冲输入流:public BufferedInputStream(InputStream in)
* */
public class BufferStreamTest {public static void main(String[] args) throws IOException {//字节缓冲输出流:BufferedOutputStream/*FileOutputStream fos = new FileOutputStream("java-03-IO\\fos.txt");BufferedOutputStream bos = new BufferedOutputStream(fos);*//*BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("java-03-IO\\fos.txt"));//写数据bos.write("hello\r\n".getBytes());bos.write("world\r\n".getBytes());//释放资源bos.close();*///字节缓冲输入流:BufferedInputStreamBufferedInputStream bis = new BufferedInputStream(new FileInputStream("java-03-IO\\fos.txt"));/*//一次读取一个字节数据int by;while((by=bis.read()) != -1) {System.out.println((char)by);}*///一次读取一个字节数组数据byte[] bytes = new byte[1024];int len;while((len = bis.read(bytes)) != -1) {System.out.println(new String(bytes,0,len));}//释放资源bis.close();}
}
控制台输出:
2.10 案例:复制视频
需求:把"C:\Users\Administrator.LAPTOP-62FQ379R\Desktop\copy.mp4"复制到模块目录下的"copy.mp4"
思路:
- 根据数据源创建字节输入流对象
- 根据目的地创建字节输出流对象
- 读写数据,复制视频
- 释放资源
四种方式实现复制视频:并记录每种方式复制视频的事件1.基于字节流一次读写一个字节2.基于字节流一次读写一个字节数组3.基于缓冲流一次读写一个字节4.基于缓冲流一次读写一个字节数组
第一种方法:基于字节流一次读写一个字节
/*
需求:把"C:\Users\Administrator.LAPTOP-62FQ379R\Desktop\copy.mp4"复制到模块目录下的"copy.mp4"思路:根据数据源创建字节输入流对象
根据目的地创建字节输出流对象
读写数据,复制视频
释放资源四种方式实现复制视频:并记录每种方式复制视频的事件1.基于字节流一次读写一个字节2.基于字节流一次读写一个字节数组3.基于缓冲流一次读写一个自己4.基于缓冲流一次读写一个字节数组
* */
public class CopyMp4 {public static void main(String[] args) throws IOException {long startTime = System.currentTimeMillis();FileInputStream fis = new FileInputStream("C:\\Users\\Administrator.LAPTOP-62FQ379R\\Desktop\\copy.mp4");FileOutputStream fos = new FileOutputStream("java-03-IO\\copy.mp4");//1.基于字节流一次读写一个字节int by;while((by = fis.read()) != -1) {fos.write(by);}long endTime = System.currentTimeMillis();System.out.println("第一种方法共耗时:" + (startTime - endTime) + "毫秒");fis.close();fos.close();}
}
控制台输出:
第二种方法:基于字节流一次读写一个字节数组
public class CopyMp4Test2 {public static void main(String[] args) throws IOException {long startTime = System.currentTimeMillis();FileInputStream fis = new FileInputStream("C:\\Users\\Administrator.LAPTOP-62FQ379R\\Desktop\\copy.mp4");FileOutputStream fos = new FileOutputStream("java-03-IO\\copy.mp4");//2.基于字节流一次读写一个字节数组byte[] bytes = new byte[1024];int len;while((len = fis.read(bytes)) != -1) {fos.write(bytes,0,len);}long endTime = System.currentTimeMillis();System.out.println("第二种方法共耗时:" + (endTime - startTime) + "毫秒");fis.close();fos.close();}
}
控制台输出:
第三种方法:基于缓冲流一次读写一个字节
public class CopyMp4Test3 {public static void main(String[] args) throws IOException {long startTime = System.currentTimeMillis();BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\Administrator.LAPTOP-62FQ379R\\Desktop\\copy.mp4"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("java-03-IO\\copy.mp4"));//3.基于缓冲流一次读写一个字节int by;while((by = bis.read()) != -1) {bos.write(by);}long endTime = System.currentTimeMillis();System.out.println("第三种方法共耗时:" + (endTime - startTime) + "毫秒");bis.close();bos.close();}
}
控制台输出:
第四种方法:基于缓冲流一次读写一个字节数组
public class CopyMp4Test4 {public static void main(String[] args) throws IOException {long startTime = System.currentTimeMillis();BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\Administrator.LAPTOP-62FQ379R\\Desktop\\copy.mp4"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("java-03-IO\\copy.mp4"));//4.基于缓冲流一次读写一个字节数组byte[] bytes = new byte[1024];int len;while((len = bis.read(bytes)) != -1) {bos.write(bytes,0,len);}long endTime = System.currentTimeMillis();System.out.println("第四种方法共耗时:" + (endTime - startTime) + "毫秒");bis.close();bos.close();}
}
控制台输出:
由结果可知,基于缓冲流一次读写一个字节数组的方式最快
3.字符流
3.1 为什么会出现字符流
由于字节流操作中文不是特别的方便,所以java就提供字符流
- 字符流 = 字节流 + 编码表
用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼装成中文,如何识别中文的呢?
- 汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数
3.2 编码表
基础知识:
- 计算机中存储的信息都是用二进制数表示的,我们在屏幕上看到的英文,汉字等字符都是二进制数转换之后的结果
- 按照某种规则,将字符存储到计算机中,成为编码。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,成为解码。
- 按照哪种编码规则编码就必须按照此种规则进行解析
字符编码:就是一套自然语言的字符与二进制之间的对应规则
字符集:
- 是一个系统支持的所有字符的集合,包括各国家文字,标点符号,图形符号,数字等
- 计算机要准确的存储和识别各种字符集符号,就需要进行字符编码,一套字符集必然至少有一套字符编码。
- 常见的字符集有ASCII字符集,GBXXX字符集,Unicode字符集等
ASCII字符集:
- ASCII ((American Standard Code for Information Interchange): 美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准ISO/IEC 646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符。
- ASCII 码使用指定的7 位或8 位二进制数组合来表示128 或256 种可能的字符。标准ASCII 码也叫基础ASCII码,使用7 位二进制数(剩下的1位二进制为0)来表示所有的大写和小写字母,数字0 到9、标点符号,以及在美式英语中使用的特殊控制字符
GBXXX字符集:
GB2312:
- GB2312编码适用于汉字处理、汉字通信等系统之间的信息交换,通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持GB 2312。
- 基本集共收入汉字6763个和非汉字图形字符682个。整个字符集分成94个区,每区有94个位。每个区位上只有一个字符,因此可用所在的区和位来对汉字进行编码,称为区位码。
GBK:
- GBK与GB 2312—1980国家标准所对应的内码标准兼容,同时在字汇一级支持ISO/IEC10646—1和GB 13000—1的全部中、日、韩(CJK)汉字,共计20902字。
GB18030:
- 是我国制订的以汉字为主并包含多种我国少数民族文字(如藏、蒙古、傣、彝、朝鲜、维吾尔文等)的超大型中文编码字符集强制性标准,其中收入汉字70000余个
Unicode字符集:
- 统一码,也叫万国码、单一码(Unicode)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
- 有三种编码方案,UTF-8、UTF-16和UTF32。最为常见的是UTF-8
- UTF-8(8位元,Universal Character Set/Unicode Transformation Format)是针对Unicode的一种可变长度字符编码。它可以用来表示Unicode标准中的任何字符,而且其编码中的第一个字节仍与ASCII相容,使得原来处理ASCII字符的软件无须或只进行少部分修改后,便可继续使用。因此,它逐渐成为电子邮件,网页及其他存储或传送文字的应用中,优先采用的编码。
编码规则:
- UTF-8使用1~4字节为每个字符编码:
- 一个US-ASCIl字符只需1字节编码(Unicode范围由U+0000~U+007F)。
- 带有变音符号的拉丁文、希腊文、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文等字母则需要2字节编码(Unicode范围由U+0080~U+07FF)。
- 其他语言的字符(包括中日韩文字、东南亚文字、中东文字等)包含了大部分常用字,使用3字节编码。
- 其他极少使用的语言字符使用4字节编码。
小结:采用何种规则编码,就要采用何种规则解码!
3.3 字符串中的编码解码问题
编码:
- byte[] getBytes():使用平台(idea)默认字符集将该String编码为一系列字节,将该结果存储到新的字符数组中
- byte[] getBytes(String charsetName):使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中
解码:
- String(byte[] bytes):通过使用平台(idea)的默认字符集解码指定的字节数组来构造新的String
- String(bytes[] bytes,String charsetName):通过指定的字符集解析指定的字节数组来构造新的String
实例:
public class StringTest {public static void main(String[] args) throws UnsupportedEncodingException {String s = "周星驰";//默认方式编码byte[] bytes = s.getBytes();//[-27, -111, -88, -26, -104, -97, -23, -87, -80]System.out.println(Arrays.toString(bytes));//指定方式编码:utf-8byte[] bytes1 = s.getBytes("utf-8");System.out.println(Arrays.toString(bytes1));//指定方式编码:gbkbyte[] bytes2 = s.getBytes("gbk");System.out.println(Arrays.toString(bytes2));//默认方式解码String ss = new String(bytes);System.out.println(ss);//指定字符集解码String ss2 = new String(bytes2,"GBK");System.out.println(ss2);}
}
控制台输出:
3.4 字符流中的编码解码问题
字符流抽象基类
- Reader:字符输入流的抽象类
- Writer:字符输出流的抽象类
字符流中和编码解码问题相关的两个类:
- InputStreamReader
- OutputStreamWriter
实例:
public class ConversionStreamTest {public static void main(String[] args) throws IOException {//public OutputStreamWriter(OutputStream out)//public OutputStreamWriter(OutputStream out, String charsetName)
// FileOutputStream fos = new FileOutputStream("java-03-IO\\fos.txt");
// OutputStreamWriter osw = new OutputStreamWriter(fos);
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("java-03-IO\\fos.txt"));OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("java-03-IO\\fos.txt"),"gbk");osw.write("周星驰x");osw.close();//public InputStreamReader(InputStream in)//public InputStreamReader(InputStream in, String charsetName)InputStreamReader isr = new InputStreamReader(new FileInputStream("java-03-IO\\fos.txt"),"gbk");//一次读取一个字符数据int ch;while ((ch = isr.read()) != -1) {System.out.println((char) ch);}isr.close();}
}
控制台输出:
3.5 字符流写数据的五种方式
方法名 | 说明 |
|
写入一个字符 |
|
写入一个字符数组 |
|
写入字符数组的一部分 |
|
写入一个字符串 |
|
写入一个字符串的一部分 |
方法名 | 说明 |
flush() | 刷新流,还可以继续写数据 |
close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
实例:
/*方法名 说明
public void write(int c) 写入一个字符
public void write(char cbuf[]) 写入一个字符数组
public void write(char cbuf[], int off, int len) 写入字符数组的一部分
public void write(String str) 写入一个字符串
public void write(String str, int off, int len) 写入一个字符串的一部分
*/
public class OutputStreamWriterTest {public static void main(String[] args) throws IOException {OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("java-03-IO\\fos.txt"));//public void write(int c):写入一个字符
// osw.write(97);
// osw.flush();//public void write(char cbuf[]):写入一个字符数组char[] chs = {'粥','星','吃','或','和'};
// osw.write(chs);//public void write(char cbuf[], int off, int len):写入字符数组的一部分
// osw.write(chs,0,chs.length);//public void write(String str) 写入一个字符串
// osw.write("abc周星驰");// osw.write("abc周星驰",0,"abc周星驰".length());
// osw.write("abc周星驰",1,2);osw.close();}
}
控制台输出:
3.6 字符流读数据的两种方式
方法名 | 说明 |
int read() | 一次读一个字符数据 |
int read(char[] read) | 一次读一个字符数组数据 |
实例:
/*
方法名 说明
int read() 一次读一个字符数据
int read(char[] read) 一次读一个字符数组数据
*/
public class InputStreamReaderTest {public static void main(String[] args) throws IOException {InputStreamReader isr = new InputStreamReader(new FileInputStream("java-03-IO\\fos.txt"));//int read():一次读一个字符数据
// int ch;
// while ((ch = isr.read()) != -1) {
// System.out.print((char)ch);
// }//int read(char[] read):一次读一个字符数组数据char[] chars = new char[1024];int len;while ((len = isr.read(chars)) != -1) {System.out.println(new String(chars,0,len));}//释放资源isr.close();}
}
控制台输出:
3.7 案例:复制java文件
需求:把模块目录下的"OutputStreamWriterTest.java"复制到模块目录下的"copy.java"
分析:
- 转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化书写,转换流提供了对应的子类
- FileReader:用于读取字符文件的便捷类:FileReader(String fileName)
- FileWriter:用于写入字符文件的边界类(FileWriter(String fileName)
数据源和目的地的分析
数据源: OutputStreamWriterTest.java---读数据---Reader---InputStreamReader---FileReader
目的地:copy.java---写数据---Writer---OutputStreamWriter---FileWriter
思路:
- 根据数据源创建字符输入流对象
- 根据目的地创建字符输出流对象
- 读写数据,复制文件
- 释放资源
实例:
/*
根据数据源创建字符输入流对象
根据目的地创建字符输出流对象
读写数据,复制文件
释放资源
* */
public class CopyJavaTest {public static void main(String[] args) throws IOException {//根据数据源创建字符输入流对象FileReader fr = new FileReader("java-03-IO\\OutputStreamWriterTest.java");//根据目的地创建字符输出流对象FileWriter fw = new FileWriter("java-03-IO\\copy.java");//读写数据,复制文件
// int ch;
// while ((ch = fr.read()) != -1) {
// fw.write(ch);
// }char[] chars = new char[1024];int len;while ((len = fr.read(chars)) != -1) {fw.write(chars,0,len);}//释放资源fw.close();fr.close();}
}
控制台输出:
3.8 字符缓冲流
字符缓冲流:
- BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接收默认大小。默认值足够大,可用于大多数用途
- BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。默认值足够大,可用于大多数用途
构造方法:
BufferedWriter(Writer out)
BufferedReader(Reader in)
实例:
public class BufferedStreamTest {public static void main(String[] args) throws IOException {
// FileWriter fw = new FileWriter("java-03-IO\\fos.txt");BufferedWriter bw = new BufferedWriter(fw);
//
// BufferedWriter bw = new BufferedWriter(new FileWriter("java-03-IO\\fos.txt"));
// bw.write("hello\n");
// bw.write("world");
// bw.close();BufferedReader br = new BufferedReader(new FileReader("java-03-IO\\fos.txt"));//一次读一个字符数据
// int ch;
// while ((ch = br.read()) != -1) {
// System.out.print((char)ch);
// }//一次读取一个字符数组数据char[] chars = new char[1024];int len;while ((len = br.read(chars)) != -1) {System.out.println(new String(chars,0,len));}br.close();}
}
控制台输出:
3.9 案例:复制java文件(字节缓冲流改进版)
需求:把模块目录下的"OutputStreamWriterTest.java"复制到模块目录下的"copy.java"
思路:
- 根据数据源创建字符缓冲输入流对象
- 根据目的地创建字符缓冲流输出对象
- 读写数据,复制文件
- 释放资源
实例:
public class CopyJavaTest {public static void main(String[] args) throws IOException {//根据数据源创建字符缓冲输入流对象BufferedReader br = new BufferedReader(new FileReader("java-03-IO\\OutputStreamWriterTest.java"));//根据目的地创建字符缓冲流输出对象BufferedWriter bw = new BufferedWriter(new FileWriter("java-03-IO\\copy.java"));//读写数据,复制文件
// int ch;
// while ((ch = br.read()) != -1) {
// bw.write(ch);
// }//一次读写一个字符数组的数据char[] chars = new char[1024];int len;while ((len = br.read(chars)) != -1) {bw.write(chars,0,len);}//释放资源br.close();bw.close();}
}
控制台输出:
3.10 字符缓冲流特有功能
BufferedWriter:
- void newLine():写一行行分隔符,行分隔符字符串由系统属性定义
BufferedReader:
- public String readLine():读一行文字。结果包含行的内容的字符串,不包括任何行终止字符,如果流的结尾已经到达,则为null
实例:
public class BufferedStreamTest2 {public static void main(String[] args) throws IOException {
// BufferedWriter bw = new BufferedWriter(new FileWriter("java-03-IO\\fos.txt"));
//
// for (int i = 0; i < 10; i++) {
// bw.write("hello" + i);bw.write("\r\n");
// bw.newLine();
// bw.flush();
// }
// bw.close();//创建字符缓冲输入流BufferedReader br = new BufferedReader(new FileReader("java-03-IO\\fos.txt"));// String s = br.readLine();
// System.out.println(s);
// s = br.readLine();
// System.out.println(s);String line;while ((line = br.readLine()) != null) {System.out.println(line);}br.close();}
}
控制台输出:
3.11 IO流小结
4.特殊操作流
4.1 标准输入输出流
System类中有两个静态的成员变量:
- public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
- public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标
自己实现键盘录入数据:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
写起来太麻烦,java就提供了一个类实现键盘录入
Scanner sc = new Scanner(System.in);
实例:
public class SystemInTest {public static void main(String[] args) throws IOException {
// InputStream in = System.in;
//
// int by;
// while ((by = in.read()) != -1) {
// System.out.println((char)by);
// }
//
// //如何把字节流转换成字符流?
// InputStreamReader isr = new InputStreamReader(in);
// //使用字符流能不能欧一次读取一行数据呢?
// //但是一次读取一行数据的方法是字符缓冲输入流的特有方法
// BufferedReader br = new BufferedReader(isr);BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.println("请输入一个字符串:");String line = br.readLine();System.out.println("你输出的字符串是:" + line);System.out.println("请输入一个整数:");int i = Integer.parseInt(br.readLine());System.out.println("你输入的整数是:" + i);//自己实现键盘录入数据太麻烦了,所以java提供了一个类供我们使用Scanner sc = new Scanner(System.in);}
}
控制台输出:
输出语句的本质:是一个标准的输出流
- PrintStream out = System.out;
- PrintStream类特有的方法,System.out都可以使用
实例:
public class SystemOutTest {public static void main(String[] args) {PrintStream out = System.out;
// out.print("hello");
// out.print(100);//System.out的本质是一个字节输出流System.out.println("hello");System.out.println(100);}
}
控制台输出:
4.2 打印流
打印流分类:
- 字节打印流:PrintStream
- 字符打印流:PrintWriter
打印流的特点:
- 只负责输出数据,不负责读取数据
- 有自己的特有方法
字节打印流
- PrintStream(String fileName):使用指定的文件名创建新的打印流
- 使用继承父类的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看的数据原样输出
实例:
public class PrintStreamTest {public static void main(String[] args) throws FileNotFoundException {PrintStream ps = new PrintStream("java-03-IO\\fos.txt");//写数据//字节输出流的方法ps.write(98);//使用特有方法写数据ps.print(97);//释放资源ps.close();}
}
控制台输出:
字符打印流PrintWriter的构造方法:
方法名 | 说明 |
PrintWriter(String fileName) | 使用指定的文件名创建一个新的PrintWriter,而不需要自动执行刷新 |
PrintWriter(Writer out,boolean autoFlush) |
创建一个新的PrintWriter
|
实例:
public class PrintWriterTest {public static void main(String[] args) throws IOException {
// PrintWriter pw = new PrintWriter("java-03-IO\\fos.txt");
//pw.write("hello");pw.write("\r\n");pw.flush();pw.write("world");pw.flush();
//
// pw.println("hello");
// pw.flush();
// pw.println("world");
// pw.flush();
//
// pw.close();PrintWriter pw = new PrintWriter(new FileWriter("java-03-IO\\fos.txt"), true);pw.println("hello");pw.println("world");pw.close();}
}
控制台输出:
4.3 对象序列化流
对象序列化:就是将对象保存在磁盘中,或者在网络中传输对象
这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
反之,该字节序列还可以从文件中读取出来,重构对象,对它进行反序列化
要实现序列化和反序列化就要使用对象序列化流和对象反序列化流
- 对象序列化流:ObjectOutputStream
- 对象反序列化流:ObjectInputStream
对象序列化流:ObjectOutputStream
- 将java对象的原始数据类型和图形写入OutputStream。可以使用ObjectInputStream读取(重构)对象。可以通过使用流的文件来实现对象的持久存储。如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
构造方法:
- ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
序列化对象的方法:
- void writeObject(Object obj):将指定的对象写入ObjectOutputStream
注意:
一个对象要想被序列化,该对象所属的类必须 实现Serializable接口
Serializable是一个标记接口,实现该接口,不需要重写任何方法
实例:
public class ObjectOutputStreamTest {public static void main(String[] args) throws IOException {ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("java-03-IO\\fos.txt"));//创建对象Student student = new Student("周星驰",30);oos.writeObject(student);//释放资源oos.close();}
}
控制台输出:
对象反序列化流:ObjectInputStream
- ObjectInputStream反序列化先前使用ObjectOutputSteam编写的原始数据对象
构造方法:
- ObjectInputStream(InputSteam in):创建从指定的InputStream读取的ObjectInputStream
反序列化对象的方法:
Object readObject():从ObjectInputStream读取一个对象
实例:
public class ObjectInputStreamTest {public static void main(String[] args) throws IOException, ClassNotFoundException {ObjectInputStream ois = new ObjectInputStream(new FileInputStream("java-03-IO\\fos.txt"));Object obj = ois.readObject();Student s = (Student)obj;System.out.println(s.getName() + s.getAge());//释放资源ois.close();}
}
控制台输出:
4.4 Properties
Properties概述:
- 是一个Map体系的集合类
- Properties可以保存到流中或从流中加载
练习:Properties作为Map集合的使用
public class PropertiesTest {public static void main(String[] args) {//创建集合对象//Properties<String,String> prop = new Properties<String,String>();//错误Properties properties = new Properties();//存储元素properties.put("001","周星驰");properties.put("002","刘德华");properties.put("003","周润发");//遍历集合Set<Object> keySet = properties.keySet();for (Object key :keySet) {Object value = properties.get(key);System.out.println(key + "," + value);}}
}
控制台输出:
Properties作为集合的特有方法:
方法名 | 说明 |
Object setProperty(String key,String value) | 设置集合的键和值,都是String类型,底层调用Hashtable方法put |
String getProperty(String key) | 使用此属性列表中指定的键搜索属性 |
Set<String> stringPropertyNames() | 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串 |
实例:
public class PropertiesTest2 {public static void main(String[] args) {//创建集合对象Properties prop = new Properties();//添加元素prop.setProperty("001","周星驰");prop.setProperty("002","刘德华");prop.setProperty("003","周润发");System.out.println(prop.getProperty("001"));System.out.println(prop);Set<String> names = prop.stringPropertyNames();for (String key :names) {String value = prop.getProperty(key);System.out.println(key + "," + value);}}
}
控制台输出:
Properties和IO流结合的方法:
方法名 | 说明 |
void load(InputStream inStream) | 从输入字节流读取属性列表(键和元素对) |
void load(Reader reader) | 从输入字符流读取属性列表(键和元素对) |
void store(OutputStream out,String comments) | 将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(InputStream)方法的格式写入输出字节流 |
void store(Winter winter,String comments) | 将此属性列表(键和元素对)写入此Properties表中,以适合使用load(Reader)方法的格式写入输出字符流 |
实例:
public class PropertiesTest3 {public static void main(String[] args) throws IOException {//把集合中的数据保存到文件myStore();//把文件中的数据加载到集合myLoad();}private static void myStore() throws IOException {Properties prop = new Properties();prop.put("001","周星驰");prop.put("002","刘德华");prop.put("003","周润发");FileWriter fw = new FileWriter("java-03-IO\\fos.txt");prop.store(fw,null);fw.close();}private static void myLoad() throws IOException {Properties prop = new Properties();FileReader fr = new FileReader("java-03-IO\\fos.txt");prop.load(fr);fr.close();System.out.println(prop);}
}
控制台输出:
一篇文章总结java IO流(File、字节流、字符流、特殊操作流)相关推荐
- 一篇文章了解 Java IO 流
一:IO 流的概述 1. 什么是 IO 流? 存储和读取数据的解决方法 I:input O:output 流:像水流一样传输数据 2. IO 流的作用? 用于读写数据(本地文件,网络) 3. IO 流 ...
- Java IO 、 File 、 文件复制
目录 1.1转换流 1.1.1概述 1.1.2 InputStreamReader 1.2打印流 1.2.1概述 1.2.2 使用 1.3 对象流 / 序列化 1.3.1 概述 1.3.2序列化 1. ...
- Java IO 3-字节流与字符流的区别
java以流的形式操纵IO,又将流分为两种:字节流与字符流,对JavaIO流操作不清楚的可以参考 Java IO 2-字节流与字符流 那字节流与字符流之间又有什么区别呢 区别 字节流用于操作文件数据, ...
- 安装好hadoop集群后,报错如下n org.apache.hadoop.ipc.RemoteException(java.io.IOException): File /data/hadoop-roo
master错误: n org.apache.hadoop.ipc.RemoteException(java.io.IOException): File /data/hadoop-root-namen ...
- Java异常捕获论文_一篇文章解决Java异常处理
前言 与异常相关的内容其实很早就想写了,但由于各种原因(懒)拖到了现在.在大二开学前夜(今天是8.31)完成这篇博客,也算完成了暑期生活的一个小心愿. 以下内容大多总结自<Java核心技术 卷Ⅰ ...
- Glide java.io.IOException(File unsuitable for memory mapping)
异常信息 03-06 14:43:26.656 W/Glide ( 852): class com.bumptech.glide.load.engine.GlideException: Failed ...
- Java IO:File类方法简介
Java IO:File类方法 File类 能新建.删除.重命名文件和目录,但不能访问文件内容本身. 访问文件名 getName() getPath() getAbsoluteFile() getAb ...
- Hadoop2.2.0 中错误总结之(org.apache.hadoop.ipc.RemoteException(java.io.IOException): File /test._COPYING)
错误: [root@xiajie01 sbin]# hadoop fs -put /root/20131210110122880.doc hdfs://192.168.30.169:9000/tes ...
- lo流知识(字节流 字符流)
概述:lo流分为字节流字符流 字节流分为:输出流和输入流 输入流:从文件到控制台(把数据从其他设备输到内存中去)读操作 输出流:从控制台到文件(把数据从内存上输出到别的地方)写操作 按数据类型分: 字 ...
最新文章
- 猜数游戏python_Hello,Python!小鲸教你学Python(九)之文件操作
- 从库备份中恢复一张表
- tushare正确爬取 指数数据
- 201671010128 2017-11-05《Java程序设计》之集合
- webpack使用加载器来加载CSS样式
- 学长毕业日记 :本科毕业论文写成博士论文的神操作20170324
- boost::hana::test::TestLogical用法的测试程序
- 我和ABP vNext 的故事
- oracle+资料类型不一致吗,oracle数据库中,字段类型不一致,导致查询慢
- 24小时BTC合约大单成交1.43亿美元 现货大单成交2.08亿美元
- linux tick异常变化,linux tickGet()
- 弹出页面,弹出框,$(‘‘).modal({});模态框
- 软件测试达内视频笔记(一)
- 如何使用cmd查看jdk版本
- PPT学习整理(四)表格
- sql解决数据库日志文件过大的问题
- qconshanghai2015
- 速度测试(speed test)
- php 月初时间,php 月初,月末时间大统计
- UESTC 1607 大学生足球联赛 构造、蛇形安排赛程表