Java基础进阶篇-第三天

93 阅读5分钟

File文件类

// 相对路径或绝对路径 \\ 或 /
File f1 = new File("C:/Users/LXQ/Desktop/itcast_study/JavaSEPlus_study/gzjavaseproject/readme.txt");
File f2 = new File("readme.txt"); // 相对路径是从当前项目目录开始找

boolean b1 = f1.isFile(); // 判断file对象是文件吗
boolean b2 = f1.isDirectory(); // 判断file对象是目录吗
boolean b3 = f1.exists(); // 判断文件是否存在

System.out.println(f1.getName()); // 获取文件名称
System.out.println(f2.getAbsolutePath()); // 获取文件绝对路径
System.out.println(f2.getPath()); // 获取定义file对象时,使用的路径
System.out.println(f1.length()); // 返回文件中字节个数
System.out.println(f1.lastModified()); // 获取文件最后操作的时间

// 创建与删除
File f4 = new File("test1");
System.out.println(f4.mkdir()); // 新建目录
File f3 = new File("test1/test.txt");
System.out.println(f3.createNewFile()); // 新建文件
File f5 = new File("test2/one");
System.out.println(f5.mkdirs()); // 新建多级目录

删除的注意事项

  1. 可以删除文件、空文件夹
  2. 默认不能删除非空文件夹
System.out.println(f3.delete()); // 删除文件目录/文件
System.out.println(f4.delete());
System.out.println(f5.delete());

new File("test2/one").mkdir();
new File("test2/two").mkdir();
new File("test2/three").mkdir();

// 文件目录的遍历
System.out.println(Arrays.toString(new File("test2").list())); // 获取目录文件名称,返回一个String类型数组
File[] f = new File("test2").listFiles(); // 获取一级目录对象数组,返回一个File类型数组
for (File file : f) {
    System.out.println(file.getAbsolutePath());
}

方法递归实现文件搜索

public class Demo {
    public static boolean mark = false;
    public static void main(String[] args) {
        File f = new File("C:\\");
        selectFile(f,"Maven1.png");
    }
    public static void selectFile(File dir,String fileName) {
        if(mark) return;
        if(!dir.exists()) return;
        if(dir.isDirectory()){
            File[] files = dir.listFiles();
            if(files == null) return;
            for (File f : files) {
                selectFile(f,fileName);
            }
        }else {
            if(dir.getName().equals(fileName)) {
                mark = true;
                System.out.println(dir.getAbsolutePath());
            }
        }
    }
}

常见字符集

标准ASCII:使用一个字节存储一个字符,二进制中首位为0

GBK:一个中文编码集,两个字节表示汉字(首位为1),一个字节表示数字、字母等(首位为0)

Unicode字符集(规则)

  • UTF-32:无论什么字符,都用四个字节存储(不可变),通信效率低。
  • UTF-8(开发使用):可变长编码方案,共分为四个长度分区:1个字节、2个字节、3个字节(汉字)、4个字节

UTF-8编码方式.png

编码/解码方式

// idea 默认为 utf-8 字符集编码
String str = "我爱中国123afg";

// 编码方式
byte[] b1 = str.getBytes(); // 默认为utf-8字符集
byte[] b2 = str.getBytes("GBK"); // 参数为字符集名称

// 解码方式
String s1 = new String(b1);
System.out.println(s1);
String s2 = new String(b1,"GBK"); // 字符集不同,结果乱码
System.out.println(s2);

输入/输出流

io体系.png

流区别

  • 字节输入输出流适用于数据文件的复制和转移。
  • 字符输入输出流比较适用于读写纯文本文件。
  • 输入流将数据读取到内存中。
  • 输出流将内存中的数据写出去。

字节输入流

InputStream is = new FileInputStream("C:/***/test1.txt");

// read 每次读一个字节,读取效率低下,无法读取汉字
// 若是数据则返回一个int类型数据,字符以Ascll存储;若是无数据,则返回 -1
int b;
while((b = is.read()) != -1){
    System.out.print((char)b);
}

// read([]) 每次读取数组,效率提高,但是还是会造成乱码的问题
int len;
byte[] buffer = new byte[4];
while((len = is.read(buffer)) != -1){
    // 0,len 取数组中的从0开始的len长度的字节
    String s = new String(buffer,0,len);
    System.out.print(s);
}

// 文件太大,则会引起内存溢出
byte[] b1 = is.readAllBytes(); // 一次性读取数据
String s1 = new String(b1);
System.out.println(s1);

is.close();

字节输出流

// 覆盖管道
OutputStream os = new FileOutputStream("C:\\***\\test2.txt");
// 追加管道
//OutputStream os = new FileOutputStream("C:\\***\\test2.txt",true);

os.write('a');os.write('b'); // 输出一个字节,字母数字为一个字节大小

os.write("我爱中国".getBytes()); // 输出字节数组
os.write("\t\n".getBytes()); // 文件中换行
os.write("我爱中国".getBytes(),1,11); // 从1开始的11个字节内容

// 刷新,将缓冲区中的数据同步到硬盘中
os.flush();
// 关闭包含了刷新
os.close();

文件复制

File f = new File("C:/***/1.png");
if(!f.exists()) f.createNewFile(); // 创建文件
try(
    InputStream is = new FileInputStream(f);
    BufferedInputStream bis = new BufferedInputStream(is);

    OutputStream os = new FileOutputStream("test\\test4.png");
    BufferedOutputStream bos = new BufferedOutputStream(os);
){
    byte[] buffer = new byte[1024];
    int len;
    while((len = bis.read(buffer)) != -1){
        bos.write(buffer,0,len);
    }
    System.out.println("复制成功");
}catch(Exception e){
    e.printStackTrace();
}

字符输入流

try (
    // 定义资源,出现任何问题都会自动关闭资源
    Reader is = new FileReader("C:\\***\\test1.txt");
){
    // read 每次读一个字符
    int b; // int类型四个字节,可以表示任意字符
    while((b = is.read()) != -1){
        System.out.print((char)b);
    }

    // read([]) 每次读取字符数组
    int len;
    char[] buffer = new char[4];
    while((len = is.read(buffer)) != -1){
        // 0,len 取数组中的从0开始的len长度的字节
        String s = new String(buffer,0,len);
        System.out.print(s);
    }
} catch (Exception e) {
    e.printStackTrace();
}

字符输出流

 try (
     // 覆盖管道
     //Writer os = new FileWriter("C:\\***\\test2.txt");
     // 追加管道
     Writer os = new FileWriter("C:\\***\\test2.txt",true);
 ) {
     os.write('a');
     os.write('b');

     os.write("我爱中国");
     os.write("\t\n"); // \t\n 换行作用,加上\t主要是解决一些兼容性问题,加上\t任何系统的适用。
     os.write("我爱中国",0,2);
 } catch (Exception e) {
     e.printStackTrace();
 }

缓冲流(带有缓冲为高级流)

  • 字节缓冲输入流: BufferedInputStream
  • 字节缓冲输出流:BufferedOutputStream
  • 字符缓冲输入流:BufferedReader
  • 字符缓冲输出流:BufferedWriter

缓冲流为什么提高了读写数据的性能

  • 缓冲流自带8KB缓冲区
  • 可以提高原始字节流、字符流读写数据的性能

缓冲流与普通的字节/字符流使用方法相同

public BufferedOutputStream(OutputStream os)
public BufferedInputStream(InputStream is)

// 字符流的缓冲流新增了新的功能
public BufferedReader(Reader r)
ublic String readLine() // 读取一行数据

public BufferedWriter(Writer w)
public void newLine() // 写一行数据

字符输入转换流

InputStreamReader

解决字符流读取文本内容乱码的问题,例如读取文件为GBK,Reader默认读取字符集为UTF-8

// 把原始的字节输入流,按照指定字符集编码转成字符输入流(重点)
public InputStreamReader(InputStream is ,String charset);

try (
    InputStream s = new FileInputStream("C:\\***\test1.txt");
    Reader isr = new java.io.InputStreamReader(s,"GBK");
    BufferedReader bs = new BufferedReader(isr);
){
    String line;
    while((line = bs.readLine()) != null){
        System.out.print(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}

打印流

PrintStreamPrintWriter的区别

  • 打印数据的功能上是一模一样的:都是使用方便,性能高效(核心优势)
  • PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法。
  • PrintWriter继承自字符输出流Writer,因此支持写字符数据出去。
try (
    //PrintStream stdout = new PrintStream("test3.txt");
    PrintWriter stdout = new PrintWriter("test3.txt");
    // 打印流内部包含了缓冲流,打印效率高效,两者打印功能相同
){
    stdout.println(90);
    stdout.println("名师出高徒");
    stdout.println('9');
}catch(Exception e){
    e.printStackTrace();
}

数据输入/输出流

// 数据输入流
try (
    DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
){
    dos.writeInt(1234);
    dos.writeDouble(4.56);
    dos.writeBoolean(true);
    dos.writeChar('a');
    dos.writeUTF("我爱中国");
}catch(Exception e) {
    e.printStackTrace();
}
// 数据输出流
try (
    DataInputStream dos = new DataInputStream(new FileInputStream("data.txt"));
){
    // 数据输入流数据输出流如何
    int i = dos.readInt();
    double v = dos.readDouble();
    boolean b = dos.readBoolean();
    char c = dos.readChar();
    String s = dos.readUTF();
    System.out.println(i);
    System.out.println(v);
    System.out.println(b);
    System.out.println(c);
    System.out.println(s);
}catch(Exception e) {
    e.printStackTrace();
}