IO流与File文件
IO流
前置知识
常见字符集
ASCII :美国信息交换标准代码,包括了英文、符号等
标准ASCII使用一个字节存储一个字符,首位是0,总共可以表示128个字符
GBK(汉字内码扩展规范,国标)
GBK中一个中文字符编码成两个字节的形式存储 英文数字占一个字节
GBK兼容ASCII字符集
GBK规定:汉字的第一个字节的第一位必须是1
Unicode字符集(统一码,也叫万国码)
Unicode是国际组织制定的,可以容纳世界上所有的文字、符号的字符集
UTF-32 四个字节 奢侈! 占存储 通讯效率低
UTF-8 是Unicode字符集的一种编码方案,采取可变长编码方案,共分为四个长度区:1个字节,2个字节,3个字节、4个字节
英文字符、数字等只占一个字节(兼容标准ASCII编码),汉字字符占用了3个字节
对于所需不同字节的编码规则如下表所示:
技术人员开发时应使用 UTF-8编码! 英文和数字一般不会出现乱码 (英文多种字符集的编码方案都是兼容ASCII编码的 )
字符集的编码、解码操作
Java代码完成对字符的编码
| String提供了如下方法 | 说明 |
|---|---|
| byte[] getBytes() | 使用平台默认的字符集将该String编码为一系列字节,将结果存储到新的字节数组中 |
| byte[]getBytes(String charsetName) | 使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中 |
Java代码完成对字符的解码
| String提供了如下方法 | 说明 |
|---|---|
| String (byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组来构造新的String |
| String(byte[]bytes,String charsetName) | 通过指定的字符集解码指定的字节数组来构造新的String |
IO流概述
I指Input,称为输入流:负责把数组读到内存中去 O指Output,称为输出流:负责写数据出去
总的来说:IO流就是输入输出流,读写数据的
IO流的分类
按流的方向分为:
graph TD;
IO流-->输入流
IO流-->输出流
按流中的数据的最小单位,分为:
graph TD
IO流-->字节流
IO流-->字符流
字节流-->适合操作所有类型的文件
适合操作所有类型的文件
字符流-->只适合操作纯文本文件
IO流总体看来有四大流
- 字节输入流
- 字节输出流
- 字符输入流
- 字符输出流
IO流---字节流
FileInputStream(文件字节输入流)
作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去
运用字节流的一个实例
public static void main(String[] args) throws IOException {
//1、创建一个字节输入流管道与源文件进行接通
InputStream is = new FileInputStream("D:\\Idea文档\\IO\\kj.txt");
byte [] buffer=new byte[3]; // 创建 字节数组 每次输出几个字节
int len=is.read(buffer);
String s = new String(buffer);
System.out.println(s);
}
使用FileInputStream每次读取一个字节(使用read方法),读取性能较差,并且读取汉字会输出乱码。
使用FileInputStream每次读取多个字节,读取性能得到提升,但读取汉字输出还是容易会乱码
使用字节流读取中文,如何保证输出不乱码
:定义一个与文件一样大的字节数组,一次性读取完文件的全部字节
存在的问题:如果文件过大,创建的字节数组也会过大,可能引起内存溢出
读取文本内容更适合用 字符流
字节流适合做数据的转移,如文件的复制等
FileOutputStream(文件字节输出流)
作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去
(getBytes()方法 将一个字符串转化为字节数组byte[]的方法)
默认是一个覆盖管道:覆盖之前的数据
public FileOutputStream(File file,boolean append) 当boolean append为true时,就是一个一个追加 不会清空原来的文件
释放资源的方式
防止出现在代码执行过程中出现异常导致无法进行后面的代码,使得流一直无法进行关闭 需要使用 try-catch-finally
finallu代码区的特点:无论try中的程序是正常执行了,还是出现异常,最后都一定会执行finally区,除非JVM终止
千万不要在finally中返回数据!!!
try-with-resource 更简单的资源释放方式
把所要用到的资源都放在try()小括号里面,和上面的相比就可以把finally去掉了 流的关闭都是自动完成 简单了很多
注:try()小括号里面只能放置资源对象
**资源:**都会实现AutoCloseable()接口。资源都会有一个close方法,并且资源放到这里后,用完之后,会被调用其close方法完成资源的释放操作
IO流---字符流
FileReader(文件字符输入流)-读字符数据进来
作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去
代码示例:读取我的文件的一个内容 并且输出
public class FileReaderTs1 {
public static void main(String[] args) throws Exception {
try ( //1、创建一个文件字符输入流管道与源文件进行接通
Reader reader = new FileReader("D:\\Idea文档\\IO\\kj.txt")) {
//2、读取文本文件的内容
//每次读一个字节的形式 性能较差
int c; //记住每次读取的字符编号
while((c=reader.read())!=-1){
System.out.print((char)c);
}
//3、每次读取多个字符 //性能比较不错
char []buffer=new char[3];
int len;
while((len==reader.read(buffer))!=-1){
System.out.print(new String(buffer,0,len));
}
}
catch (Exception e){
e.printStackTrace();
}
}
FileWriter(文件字符输出流)-写字符数据到文件中去
public static void main(String[] args) {
try ( //1、创建一个文件字符输出流管道与源文件进行接通
Writer fw = new FileWriter("D:\\Idea文档\\IO\\kj2.txt")) {
//2、public void writer(int c) :写一个字符出去
fw.write('a');
fw.write('b');
fw.write('c');
fw.write("\r\n"); //换行
//3、public void writer(String c) :写一个字符串出去
fw.write("come on!");
//4、public void writer(String c) :写一个字符数组出去
char [] buffer={'会','变','好','哒'};
fw.write(buffer);
//5、public void write(char [] buffer,int pos,int len)写字符数据一部分出去
fw.write(buffer,2,2);
} catch (Exception e) {
e.printStackTrace();
}
}
字符输出流的注意事项
字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效
flush() 刷新流
close()关闭流,关闭流包含刷新流
IO流---缓冲流
字节缓冲流
字节缓冲流作用:提高字节流读写数据的性能
原理:字节缓冲输入流自带了8kb缓冲池;字节缓冲输出流也自带了8kb缓冲池
字符缓冲流
BufferedReader(字符缓冲输入流)
:自带8k的字符缓冲池,可以提高输入流读取字符数据的性能
小例子:
public static void main(String[] args) throws Exception {
try ( //1、创建一个文件字符输入流管道与源文件进行接通
Reader reader = new FileReader("D:\\Idea文档\\IO\\kj.txt");
BufferedReader br = new BufferedReader(reader);
) {
char []buffer=new char[3];
int len;
while((len=br.read(buffer))!=-1){
System.out.print(new String(buffer,0,len));
}
}
catch (Exception e){
e.printStackTrace();
}
}
readline() 读取一行的内容的方法
BufferedWriter(字符缓冲输出流)
:自带8k的字符缓冲池,可以提高输出流写字符数据的性能
IO流---转换流
InputStreamReader(字符输入转换流)
解决 不同编码读取出现乱码的问题
思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不会乱码。
OutputStreamWriter(字符输出转换流)(了解)
解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出取得字符就会用该字符集编码了
IO流---打印流
作用:实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去
打印流的一种应用:输出语句的重定向 setOut把系统默认的打印流对象改成自己设置的位置
序列化流
对象如果需要序列化,必须实现序列化接口!
transient 修饰成员变量 可以将其不序列化
ArrayList存储多个对象,然后直接对集合进行序列化
ArrayList集合已经实现了序列化接口
IO框架
解决某类问题,编写的一套类、接口等,可以理解为半成品,多数框架由第三方研发
File文件
File是java.io包下的类,File类的对象,用于代表当前操作系统的文件(可以是文件或者文件夹)
File:代表文本
创建File类的对象方法
主要都使用第一种方法 后面两种比较少见
下面是一个创建File类的对象的小案例 存储的路径是我设置的 D盘里面的Idea文档里面
//创建一个File对象,指代某个具体的文件
// 写路径位置的时候,可以用/ 或者 \\
File f1=new File("D:\\Idea文档\\Test.txt");
ystem.*out*.println(f1.length());
File f2=new File("D:\\Idea文档");
System.*out*.println(f2.length());
绝对路径与相对路径
绝对路径:带盘符号的,比如C盘 有前缀 C: 等等 注:带盘号一定不要忘记了 :
相对路径:不带盘符,默认是直接去工程下面去找文件
//注意:File对象可以指代一个不存在的文件路径
//exists()可以用于判断目录是否存在
System.out.println(f2.exists());
//绝对路径:带盘符号的
File f4=new File("D:\\Idea文档\\oop\\src\\File_Study\\kj.txt");
System.out.println(f4.getName());
//相对路径:不带盘符,默认是直接去工程下面去找文件
File f3=new File("oop\\src\\File_Study/Tes2");
System.out.println(f4.length());
File提供的判断文件类型、获取文件信息功能
创建文件和删除文件的常用方法
代码块中有以下四种方法
//1、public boolean creatNewFile(): 创建一个新文件(文件内容为空),创建成功则返回true,否则反之
File f1=new File("D:\\Tes1.txt");
System.out.println(f1.createNewFile());
//2、public boolean mkdir(): 用于创建一级文件夹
File f2=new File("D:/a");
//3、public boolean mkdirs():用于创建文件夹,可以创建多级文件夹
File f3=new File("D:\\aaa\\bb\\cc");
System.out.println(f3.mkdirs());
// public boolean delete():删除文件,或者空文件,注意不能删除非空文件夹
System.out.println(f1.delete());
遍历文件夹
// 1、 public String[] list(): 获取当前目录下所有的一级文件名称到一个字符串数组中去返回
File f1=new File("D:\\software");
String[] name = f1.list();
for (String s : name) {
System.out.println(s);
}
// 2、public File[] listFiles(): 获取当前目录下所有的一级文件对象到一个文件对象数组中去返回
File [] files =f1.listFiles();
for (File file : files) {
System.out.println(file.getAbsoluteFile());
}
方法递归 (算是一个先导知识)
直接或者间接的调用自己本身的方法
递归有三个要素
- 递归的公式 : f(n)=f(n-1)*n; //这里只是举了个例子 并非公式单一
- 递归的一个终结节点 f(1) //这里也只是举个例子 终结点根据具体情况而定
- 递归的方向必须是走向终结
特殊文件
properties文件(属性文件)
特点:都只是键对值
键不能重复
文件后缀一般是.properties
Propertise :一个Map集合,但是一般不当集合使用
核心作用:Properties是用来代表属性文件的,通过Properties可以读写属性文件里的内容
XML文件(EXtensible Markup Language,可扩展标记语言)
本质:是一种数据结构,可以用来存储复杂的数据结构,和数据关系
XML语法规则
XML的应用场景:经常用来作为系统的配置文件,或者作为一种特殊的数据结构,在网络中进行传输。
Dom4j是比较好用的解析XML的框架
但是在把数据写入到XML文件中 不用Dom4j框架。 推荐直接把程序里的数据拼接成XML格式,然后用IO流写出去。