Java文件与IO流

java

  • java.io.File 类是文件和目录,路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作
  • File可以表示目录,也可以表示文件

构造方法

方法名作用
public File(String pathname)通过给定的路径名,字符串转换为抽象路径名来创建新的 File实例
public File(String parent, String child)从父路径名字符串和子路径名字符串创建新的 File实例,根据父路径加子路径的意思
public File(File parent, String child)从父抽象路径名和子路径名字符串创建新的 File实例

public class Demo {

public static void main(String[] args) {

File file = new File("F:/IdeaProjectTwo/IT6666-Web/vue.config.js");

System.out.println(file);

File fileTwo = new File("F:/IdeaProjectTwo/IT6666-Web", "/vue.config.js");

System.out.println(fileTwo);

File fileThree = new File(file, "/a.txt");

System.out.println(fileThree);

}

}

????注意事项

  • 一个 File 对象代表硬盘中实际存在的一个文件或者目录
  • 无论该路径下是否存在文件或者目录,都不影响 File 对象的创建

File类常用方法

方法名作用
public String getAbsolutePath()返回此 File 的绝对路径名字符串,返回绝对路径
public String getPath()将此 File 转换为路径名字符串获取路径
public String getName()返回由此 File 表示的文件或目录的名称
public long length()返回由此 File 表示的文件的长度

public class Demo {

public static void main(String[] args) {

File file = new File("F:/IdeaProjectTwo/IT6666-Web/vue.config.js");

System.out.println(file.getAbsolutePath());

File fileTwo = new File("F:/IdeaProjectTwo/IT6666-Web", "/vue.config.js");

System.out.println(fileTwo.getPath());

File fileThree = new File(file, "/a.txt");

System.out.println(fileThree.getName());

System.out.println(file.length());

}

}

绝对路径和相对路径

  • 绝对路径:从盘符开始的路径,这是一个完整的路径
  • 相对路径:相对于项目目录的路径,不是从盘符开始,从项目名称的位置开始,不带项目名称

public class Demo {

public static void main(String[] args) {

File file = new File("F:/IdeaProjectTwo/IT6666-Web/vue.config.js");

System.out.println(file);

File fileTwo = new File("src/a.text");

System.out.println(fileTwo);

}

}

判断相关方法

方法名作用
public boolean exists()用于判断此 File 表示的文件或目录是否实际存在
public boolean isDirectory()此 File 表示的是否为目录

public boolean isFile()此 File 表示的是否为文件

public class Demo {

public static void main(String[] args) {

File file = new File("F:/IdeaProjectTwo/IT6666-Web/vue.config.js");

System.out.println(file.exists());

System.out.println(file.isDirectory());

System.out.println(file.isFile());

File fileTwo = new File("F:/IdeaProjectTwo/IT6666-Web");

System.out.println(fileTwo.exists());

System.out.println(fileTwo.isDirectory());

System.out.println(fileTwo.isFile());

}

}

创建删除相关方法

方法名作用
public boolean createNewFile()当且仅当具有该名称的文件尚不存在时,创建一个新的空文件
public boolean delete()删除由此 File 表示的文件或目录
public boolean mkdir()创建由此 File 表示的目录

public boolean mkdirs()创建由此 File 表示的目录,包括任何必需但不存在的父目录

public class Demo {

public static void main(String[] args) throws Exception {

File file = new File("BNTang.txt");

System.out.println(file.exists());

System.out.println(file.createNewFile());

System.out.println(file.exists());

File fileTwo = new File("newDir");

System.out.println(fileTwo.exists());

System.out.println(fileTwo.mkdir());

System.out.println(fileTwo.exists());

File fileThree = new File("newDira\\newDirb");

System.out.println(fileThree.mkdir());

System.out.println(fileThree.mkdirs());

System.out.println(file.delete());

System.out.println(fileTwo.delete());

System.out.println(fileThree.delete());

}

}

目录遍历

方法名作用
public String[] list()返回一个 String数组,表示该 File 目录中的所有子文件或目录
public File[] listFiles()返回一个 File 数组,表示该 File 目录中的所有的子文件或目录

public class Demo {

public static void main(String[] args) throws Exception {

File dir = new File("F:\\upload");

String[] names = dir.list();

for (String name : names) {

System.out.println(name);

}

File[] files = dir.listFiles();

for (File file : files) {

System.out.println(file);

}

}

}

????注意事项

  • 调用 listFiles 方法的 File 对象,表示的必须是实际存在的目录,否则返回null,无法进行遍历

递归

  • 指在当前方法内调用自己的这种现象
  • 调用时,要有一个退出的条件,否则会死循环,一直调用
  • 就是一种方法的调用,方法自己调用自己,如果没有出口的话,就变成了死循环了

public class Demo {

static int num = 10;

public static void main(String[] args) throws Exception {

System.out.println("main");

num--;

if (num == 0) return;

main(args);

}

}

????计算1 - n的和

public class Demo {

public static void main(String[] args) throws Exception {

int sum = getSum(3);

System.out.println(sum);

}

/**

* 传入一个数返回1到这个数的和

* @param num n

* @return 1 - n的结果

*/

private static int getSum(int num) {

if (num == 1){

return 1;

}

return num + getSum(num-1);

}

}

????文件搜索

  • 搜索指定目录下指定扩展名的文件
  • 例如:D盘下 aaa目录中所有的 .txt文件

public class Demo {

public static void main(String[] args) throws Exception {

printDir(new File("F:\\IdeaProjectTwo\\IT6666-Web"));

}

public static void printDir(File dir) {

File[] files = dir.listFiles();

for (File file : files) {

if (file.isFile()) {

if (file.getName().endsWith(".txt")) {

System.out.println("文件名:" + file.getAbsolutePath());

}

} else {

printDir(file);

}

}

}

}

????多级目录树形结构显示

public class Demo {

public static void main(String[] args) throws Exception {

printDir(new File("F:\\upload"), 0);

}

public static void printDir(File dir, int level) {

if (level != 0) {

printSpace(level);

for (int i = 0; i < level; i++) {

if (i == 0) {

System.out.print("|-");

} else {

System.out.print("-");

}

}

}

File[] files = dir.listFiles();

for (File file : files) {

if (file.isFile()) {

if (file.getName().endsWith(".txt")) {

System.out.println("文件名:" + file.getAbsolutePath());

}

} else {

printDir(file, level + 1);

}

}

}

private static void printSpace(int level) {

StringBuilder str = new StringBuilder();

for (int i = 0; i < level; i++) {

str.append(" ");

}

System.out.print(str);

}

}

????递归求阶乘

public class Demo {

public static void main(String[] args) throws Exception {

int num = getJieCheng(4);

System.out.println(num);

}

private static int getJieCheng(int num) {

if (num == 1) {

return 1;

}

return num * getJieCheng(num - 1);

}

}

????斐波那契数列

  • 斐波那契数列:又称黄金分割数列、因数学家列昂纳多 • 斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为兔子数列

  • 指的是这样一个数列:1、1、2、3、5、8、13、21、34、…
  • 求数列的第6位的值是多少

递归分析

  • 当位数为1和2时,当前返回的值应该是1
  • 当位数为3时,返回值应该是2=1+1
  • 当位数为4时,返回值是3=2+1
  • 当位数为5时,返回值是5=3+2
  • 大于等于3的情况下,当前位数(n)的数值是 f(n - 1) + f(n - 2)

public class Demo {

public static void main(String[] args) {

int f = f(3);

System.out.println(f);

for (int i = 1; i <= 15; i++) {

System.out.print(f(i) + "\t");

}

}

public static int f(int n) {

if (n == 1 || n == 2)

return 1;

else

return f(n - 1) + f(n - 2);

}

}

IO流

  • 与计算机之间数据的传输,可以看做是一种数据的流动
  • 以内存为基准,分为 输入input 和 输出 output ,流向内存是输入流,内存流出是的输出流
  • 可以理解把程序当中的数据保存到电脑磁盘,为输出流,把电脑磁盘当中的数据加载到程序当中为输入流

IO流的分类

  • 根据数据的流向分

    • 输入流:把数据从 其他设备 上读取到 内存 中
    • 输出流:把数据从 内存 中写出到 其他设备 上

  • 根据数据的类型分

    • 字节流:以字节为单位,读写数据
    • 字符流:以字符为单位,读写数据

顶级父类

  • 字节输入流:InputStream
  • 字节输出流:OutputStream
  • 字符输入流:Reader
  • 字符输出流:Writer

字节流

  • 一切文件数据(文本、图片、视频等)在存储时,都是以二进制的数字的形式保存的,都一个一个的字节
  • 在传输时也是使用字节进行传输,我们称之为字节流

  • 字节流可以传输任意文件数据
  • 无论使用什么样的流对象,底层传输的始终为二进制数据

字节输出流

  • OutputStream:字节输出流

    • java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地

方法名作用
public void close()关闭此输出流并释放与此流相关联的任何系统资源,close方法,当完成流的操作时,必须调用此方法,释放系统资源
public void flush()刷新此输出流,并强制任何缓冲的输出字节被写出
public void write(byte[] b)将 b.length 字节从指定的字节数组写入此输出流
public void write(byte[] b, int off, int len)从指定的字节数组写入 len 字节,从偏移量 off 开始输出到此输出流
public abstract void write(int b)将指定的字节输出流

  • OutputStream 有很多子类,以上方法子类都可以调用

  • FileOutputStream类

    • java.io.FileOutputStream 类是文件输出流,用于将数据写出到文件,继承自OutputStream

构造方法

方法名作用
public FileOutputStream(File file)创建文件输出流写入到指定的 File 对象表示的文件
public FileOutputStream(String name)创建文件输出流以指定的名称写入文件

public class Demo {

public static void main(String[] args) throws FileNotFoundException {

File file = new File("a.txt");

FileOutputStream fos = new FileOutputStream(file);

FileOutputStream fos2 = new FileOutputStream("b.txt");

}

}

????注意事项

  • 当你创建一个流对象时,必须传入一个文件路径
  • 该路径下,如果没有这个文件,会创建该文件。如果有这个文 件,会清空这个文件的数据,写入新的信息

write(int b)

  • 写出字节
  • 每次只可以写出一个字节数据

public class Demo {

public static void main(String[] args) throws IOException {

File file = new File("a.txt");

FileOutputStream fos = new FileOutputStream(file);

fos.write(97);

fos.write(98);

fos.write(99);

fos.close();

}

}

????注意事项

  1. 虽然参数为 int 类型四个字节,但是只会保留一个字节的信息写出
  2. 流操作完毕后,必须释放系统资源,调用 close 方法,千万记得

write(byte[] b)

  • 写出字节数组
  • 可以通过 getBytes 方法把汉字转成字节数组

public class Demo {

public static void main(String[] args) throws IOException {

File file = new File("a.txt");

FileOutputStream fos = new FileOutputStream(file);

byte[] b = "灰灰".getBytes();

fos.write(b);

fos.close();

}

}

write(byte[] b, int off, int len)

  • 写出指定长度的字节数组
  • 每次写出从 off 索引开始,len个字节

public class Demo {

public static void main(String[] args) throws IOException {

File file = new File("a.txt");

FileOutputStream fos = new FileOutputStream(file);

byte[] b = "abcde".getBytes();

fos.write(b, 2, 2);

fos.close();

}

}

数据追加续写

  • 每次程序运行,创建输出流对象,都会清空目标文件中的数据

方法名作用
public FileOutputStream(File file, boolean append)创建文件输出流写入到指定的 File对象表示的文件
public FileOutputStream(String name, boolean append)创建文件输出流以指定的名称写入文件

  • 参数介绍

    • 参数中都需要传入一个 boolean类型 的值
    • true 表示追加数据
    • false 表示清空原有数据

public class Demo {

public static void main(String[] args) throws IOException {

File file = new File("a.txt");

FileOutputStream fos = new FileOutputStream(file, true);

byte[] b = "abcde".getBytes();

fos.write(b, 2, 2);

fos.close();

}

}

写出换行

  • Windows系统里,换行符号是\r\n

public class Demo {

public static void main(String[] args) throws IOException {

File file = new File("a.txt");

FileOutputStream fos = new FileOutputStream(file, true);

byte[] b = "abcde".getBytes();

fos.write(b, 2, 2);

fos.write("\r\n".getBytes());

fos.write(b, 2, 2);

fos.close();

}

}

字节输入流

  • java.io.InputStream

    • java.io.InputStream 抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入 流的基本共性功能方法

基本方法

方法名作用
public void close()关闭此输入流并释放与此流相关联的任何系统资源
public abstract int read()从输入流读取数据的下一个字节
public int read(byte[] b)从输入流中读取一些字节数,并将它们存储到字节数组 b 中

FileInputStream

  • java.io.FileInputStream 类是文件输入流,从文件中读取字节

构造方法

方法名作用
FileInputStream(File file)file 是需要读取的文件路径或者是文件对象
FileInputStream(String name)可以传入一个字符串的路径创建字节输入流

public class Demo {

public static void main(String[] args) throws IOException {

File file = new File("a.txt");

FileInputStream fileInputStream = new FileInputStream(file);

FileInputStream fileInputStream1 = new FileInputStream("a.txt");

}

}

????注意事项

  • 当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出 FileNotFoundException 异常

读取字节数据

  • read()方法:每次可以读取一个字节的数据,提升为 int 类型,读取到文件末尾,返回-1

public class Demo {

public static void main(String[] args) throws IOException {

FileInputStream fis = new FileInputStream("a.txt");

int read = fis.read();

System.out.println((char) read);

int read2 = fis.read();

System.out.println((char) read2);

int read3 = fis.read();

System.out.println((char) read3);

int read4 = fis.read();

System.out.println((char) read4);

int read5 = fis.read();

System.out.println(read5);

}

}

循环的方式优化

public class Demo {

public static void main(String[] args) throws IOException {

FileInputStream fis = new FileInputStream("a.txt");

int b;

while ((b = fis.read()) != -1) {

System.out.println((char) b);

}

}

}

  • read(byte[] b)方法:每次读取 b 个长度到字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1

public class Demo {

public static void main(String[] args) throws Exception {

FileInputStream fis = new FileInputStream("a.txt");

int len;

byte[] b = new byte[2];

while ((len = fis.read(b)) != -1) {

System.out.println(new String(b));

}

fis.close();

}

}

  • 复制图片

public class Demo {

public static void main(String[] args) throws Exception {

FileInputStream fis = new FileInputStream("D:\\logo.jpg");

FileOutputStream fos = new FileOutputStream("copyLogo.jpg");

byte[] b = new byte[1024];

int len;

while ((len = fis.read(b)) != -1) {

fos.write(b, 0, len);

}

fos.close();

fis.close();

}

}

字符流

  • 当使用字节流读取文本文件时,可能会有一个小问题
  • 就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储
  • 所以 Java 提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件

Reader类

  • java.io.Reader 抽象类是表示用于读取,字符流的所有类的超类,可以读取字符信息到内存中
  • 它定义了字符输入流的基本共性功能方法

基本方法

方法名作用
public void close()关闭此流并释放与此流相关联的任何系统资源
public int read()从输入流读取一个字符
public int read(char[] cbuf)从输入流中读取一些字符,并将它们存储到字符数组 cbuf 中

FileReader类

  • java.io.FileReader 类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区

构造方法

方法名作用
FileReader(File file)传入一个文件对象创建一个字符读取流
FileReader(String fileName)传入一个字符串路径创建一个字符读取流

????注意事项

  • 当你创建一个流对象时,必须传入一个文件路径。类似于 FileInputStream

读取字符数据

  • read方法:每次可以读取一个字符的数据,提升为 int 类型,读取到文件末尾,返回-1

public class Demo {

public static void main(String[] args) throws Exception {

FileReader fr = new FileReader("a.txt");

int b;

while ((b = fr.read()) != -1) {

System.out.println((char) b);

}

fr.close();

}

}

  • read(char[] cbuf):每次读取 b 个长度字符到数组中,返回读取到的有效字符个数, 读取到末尾时,返回-1

public class Demo {

public static void main(String[] args) throws Exception {

FileReader fr = new FileReader("a.txt");

int len;

char[] chars = new char[2];

while ((len = fr.read(chars)) != -1) {

System.out.println(new String(chars));

}

fr.close();

}

}

  • 使用上面这种方法会发现,如果是5个字符的时候会多读取一个,是因为 chars数组中内容没有被清空
  • 指定有效个数

public class Demo {

public static void main(String[] args) throws Exception {

FileReader fr = new FileReader("a.txt");

int len;

char[] chars = new char[2];

while ((len = fr.read(chars)) != -1) {

System.out.println(new String(chars, 0, len));

}

fr.close();

}

}

FileWriter类

  • java.io.FileWriter 类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区

构造方法

方法名作用
FileWriter(File file)传入一个文件对象创建一个字符输出流
FileWriter(String fileName)传入一个字符串路径创建一个字符输出流

  • 当你创建一个流对象时,必须传入一个文件路径,类似于 FileOutputStream
  • write(int b):每次可以写出一个字符数,如果不关闭也就是释放资源,数据只是保存到缓冲区,并未保存到文件

public class Demo {

public static void main(String[] args) throws Exception {

FileWriter fw = new FileWriter("a.txt", true);

fw.write(97);

fw.write('b');

fw.write(30000);

fw.close();

}

}

  • 关闭和刷新

    • 刷新:因为内置缓冲区的原因,如果不关闭输出流,无法将字符写到文件中。但是关闭了流对象,还想在写入就无法继续写出数据了,如果我们既想写出数据,又想继续使用流,就需要 flush 方法了
    • flush:刷新缓冲区,流对象可以继续使用
    • close:关闭流,释放系统资源。关闭前会刷新缓冲区

public class Demo {

public static void main(String[] args) throws Exception {

FileWriter fw = new FileWriter("a.txt", true);

fw.write(97);

fw.write('b');

fw.write(30000);

fw.flush();

fw.write('d');

fw.close();

}

}

  • write(char[] cbuf):每次可以写出字符数组中的数据

public class Demo {

public static void main(String[] args) throws Exception {

FileWriter fw = new FileWriter("a.txt");

String msg = "IT6666灰灰";

char[] chars = msg.toCharArray();

fw.write(chars);

fw.close();

}

}

  • write(String str, int off, int len):每次可以写出字符数组中的数据

public class Demo {

public static void main(String[] args) throws Exception {

FileWriter fw = new FileWriter("a.txt");

String msg = "灰灰";

char[] chars = msg.toCharArray();

fw.write(chars, 2, 2);

fw.close();

}

}

异常处理

JDK7之前异常处理中释放资源的是需要自己手动来释放的

public class Demo {

public static void main(String[] args) throws Exception {

FileWriter fw = null;

try {

fw = new FileWriter("a.txt");

} catch (IOException e) {

e.printStackTrace();

} finally {

if (fw != null) {

try {

fw.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

JDK7之后就不用自己来手动释放了,JDK7之后的异常处理会自动帮我们释放只需要把需要释放的资源写在try()的括号中即可

格式

try(创建流对象语句,如果多个使用 ; 隔开){

代码

} catch(IOException e){

e.printStackTrace();

}

  • 该语句确保了每个资源在语句结束时自动关闭释放资源

public class Demo {

public static void main(String[] args) throws Exception {

try (FileWriter fw = new FileWriter("a.txt"); FileReader fr = new FileReader("a.txt")) {

fw.write("it6666.top");

int read = fr.read();

} catch (IOException e) {

e.printStackTrace();

}

}

}

缓冲流

  • 缓冲流,也叫高效流,是对4个基本的 File*** 流的增强
  • 所以也是4个流,按照数据类型分类

    • 字节缓冲流: BufferedInputStream , BufferedOutputStream
    • 字符缓冲流: BufferedReader,BufferedWriter

基本原理

  • 缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组
  • 通过缓冲区读写,减少系统 IO 次数,从而提高读写的效率

字节缓冲流

构造方法

方法名作用
public BufferedInputStream(InputStream in)创建一个 新的缓冲输入流
public BufferedOutputStream(OutputStream out)创建一个新的缓冲输出流

public class Demo {

public static void main(String[] args) throws Exception {

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("a.txt"));

}

}

效率测试

直接使用 FileInputStream 与 FileOutStream 复制文件

public class Demo {

public static void main(String[] args) throws Exception {

long start = System.currentTimeMillis();

FileInputStream fis = new FileInputStream("D:\\view.mp4");

FileOutputStream fos = new FileOutputStream("newView.mp4");

int len;

byte[] b = new byte[1024];

while ((len = fis.read(b)) != -1) {

fos.write(b);

}

fis.close();

fos.close();

long end = System.currentTimeMillis();

System.out.println("时间:" + (end - start));

}

}

使用缓冲流复制文件

public class Demo {

public static void main(String[] args) throws Exception {

long start = System.currentTimeMillis();

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\view.mp4"));

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("newView.mp4"));

int len;

byte[] b = new byte[1024];

while ((len = bis.read(b)) != -1) {

bos.write(b);

}

bis.close();

bos.close();

long end = System.currentTimeMillis();

System.out.println("时间:" + (end - start));

}

}

字符缓冲流

构造方法

方法名作用
public BufferedReader(Reader in)创建一个 新的缓冲字符输入流
public BufferedWriter(Writer out)创建一个新的缓冲字符输出流

public class Demo {

public static void main(String[] args) throws Exception {

BufferedReader br = new BufferedReader(new FileReader("a.txt"));

BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));

}

}

特有方法

方法名作用
public String readLine()读一行文字
public void newLine()写一行分隔符,由系统属性定义符号

public class Demo {

public static void main(String[] args) throws Exception {

BufferedReader br = new BufferedReader(new FileReader("a.txt"));

String line = null;

while ((line = br.readLine()) != null) {

System.out.println(line);

}

br.close();

}

}

public class Demo {

public static void main(String[] args) throws Exception {

BufferedWriter br = new BufferedWriter(new FileWriter("a.txt"));

br.write("灰灰");

br.newLine();

br.write("IT6666.top");

br.newLine();

br.close();

}

}

转换流

字符编码

  • 计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制 数转换之后的结果
  • 按照某种规则,将字符存储到计算机中,称为编码
  • 反之,将存储在计算机中的二进制数按照以某种规则解析显示出来,称为解码
  • 按照A规则存储,同样按照A规则解析,那么就能显示正确的文本符号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象

字符集

  • 字符集 Charset:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等
  • 计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码
  • 常见字符集有ASCII字符集、GBK字符集、Unicode字符集等

????常见字符集

  • ASCII字符集:ASCII编码
  • GBK字符集:GBK编码
  • Unicode字符集:UTF8编码、UTF16编码、UTF32编码
  • 当指定了编码,它所对应的字符集自然就指定了,所以编码才是我们最终要关心的

????字符集介绍

ASCII字符集

  • ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)
  • 是基于拉丁字母的一套电脑编码系统,用于显示现代英语
  • 主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)
  • 基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符
  • ASCII的扩展字符集使用8位(bits) 表示一个字符,共256字符,方便支持欧洲常用字符

ISO-8859-1字符集

  • 拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等
  • ISO-5559-1使用单字节编码,兼容ASCII编码

GBxxx字符集

  • GB就是国标的意思,是为了显示中文而设计的一套字符集
  • GB2312

    • 简体中文码表。一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字
    • 这样大约可以组合了包含7000多个简体汉字
    • 此外数学符号、罗马希腊的字母、日文的假名们都编进去了
    • 在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码
    • 这就是常说的全角字符,而原来在127号以下的那些就叫半角字符了

  • GBK

    • 最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案
    • 共收录了 21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等

  • GB18030

    • 新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成
    • 支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等

Unicode字符集

  • Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国码
  • 它最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码方案
  • UTF-8、UTF-16和UTF32,最为常用的UTF-8编码
  • UTF-8编码,可以用来表示Unicode标准中任何字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码

UTF8编码规则

  • 128个US-ASCII字符,只需一个字节编码
  • 拉丁文等字符,需要二个字节编码
  • 大部分常用字(含中文),使用三个字节编码
  • 其他极少使用的Unicode辅助字符,使用四字节编码

编码引出的问题

  • 在IDEA中,使用 FileReader 读取项目中的文本文件。由于IDEA的设置,都是默认的 UTF-8 编码,所以没有任何问题
  • 但是,当读取Windows系统中创建的文本文件时,由于Windows系统的默认是GBK编码,就会出现乱码

public class Demo {

public static void main(String[] args) throws Exception {

FileReader fileReader = new FileReader("d:/demo.txt");

int read;

while ((read = fileReader.read()) != -1) {

System.out.println((char) read);

}

fileReader.close();

}

}

????解决乱码

InputStreamReader

  • 转换流 java.io.InputStreamReader,是Reader的子类,是从字节流到字符流的桥梁
  • 它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集

构造方法

方法名作用
InputStreamReader(InputStream in)创建一个使用默认字符集的字符流
InputStreamReader(InputStream in, String charsetName)创建一个指定字符集的字符流

public class Demo {

public static void main(String[] args) throws Exception {

InputStreamReader isr = new InputStreamReader(new FileInputStream("d://demo.txt"), "gbk");

int read;

while ((read = isr.read()) != -1) {

System.out.println((char) read);

}

isr.close();

}

}

OutputStreamWriter

  • 转换流 java.io.OutputStreamWriter,是Writer的子类,是从字符流到字节流的桥梁
  • 使用指定的字符集将字符编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集

构造方法

方法名作用
OutputStreamWriter(OutputStream in)创建一个使用默认字符集的字符流
OutputStreamWriter(OutputStream in, String charsetName)创建一个指定字符集的字符流

public class Demo {

public static void main(String[] args) throws Exception {

String fileName1 = "d://demo.txt";

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(fileName1));

osw.write("灰灰");

osw.close();

String fileName2 = "d://demoTwo.txt";

OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream(fileName2), "gbk");

osw2.write("灰灰");

osw2.close();

}

}

序列化

  • 用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息
  • 字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息
  • 字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

序列化必须满足两个条件

  • 该类必须实现 java.io.Serializable 接口
  • Serializable 是一个标记接口,不实现此接口的类将不会被序列化或反序列化,会抛出 NotSerializableException
  • 该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用 transient 关键字修饰

ObjectOutputStream类

  • 将Java对象的原始数据类型写出到文件,实现对象的持久存储

构造方法

方法名作用
public ObjectOutputStream(OutputStream out)创建一个指定 OutputStream 的 ObjectOutputStream

写出对象方法

  • public final void writeObject (Object obj)
  • 创建Person类

public class Person implements java.io.Serializable {

public String name;

public String age;

public transient String address;

public void show() {

System.out.println("myName is " + name);

}

}

  • 写到文件当中

public class Demo {

public static void main(String[] args) throws Exception {

Person person = new Person();

person.name = "IT6666";

person.age = "23";

person.address = "上海";

FileOutputStream fos = new FileOutputStream("person.txt");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(person);

oos.close();

fos.close();

}

}

ObjectInputStream类

  • ObjectInputStream 反序列化流,将之前使用 ObjectOutputStream 序列化的原始数据恢复为对象

构造方法

方法名作用
public ObjectInputStream(InputStream in)创建一个指定 InputStream 的 ObjectInputStream

读取对象方法

  • readObject()

public class Demo {

public static void main(String[] args) throws Exception {

FileInputStream fileIn = new FileInputStream("person.txt");

ObjectInputStream in = new ObjectInputStream(fileIn);

Person p = (Person) in.readObject();

System.out.println(p.name);

System.out.println(p.age);

System.out.println(p.address);

p.show();

fileIn.close();

in.close();

}

}

注意事项

  • 对于 JVM 可以反序列化对象,它必须是能够找到 class 文件的类
  • 如果找不到该类的 class 文件,则抛出一个 ClassNotFoundException 异常

打印流

  • 我们在控制台打印输出,是调用 print 方法和 println 方法完成的
  • 这两个方法都来自于 java.io.PrintStream 类
  • 该类能够方便地打印各种数据类型的值,是一种便捷的输出方式

使用指定的文件名创建一个新的打印流

  • public PrintStream(String fileName)
  • System.out 就是 PrintStream 类型的,只不过它的流向是系统规定的,打印在控制台上

public class Demo {

public static void main(String[] args) throws Exception {

System.out.println("it6666.top");

PrintStream os = new PrintStream("demo.txt");

System.setOut(os);

System.out.println("it6666.top");

}

}

以上是 Java文件与IO流 的全部内容, 来源链接: utcz.com/z/390236.html

回到顶部