10. IO

IO(BIO)

Blocking IO 同步 阻塞的io Scannner Socket

NIO 同步非阻塞 tomcat netty

AIO 异步非阻塞

1. File

很多功能 用户注册 的数据存储在内存中(jvm运行内存) 程序停止 数据就消失不见 需要将数据持久化保存

数据永久存储在物理内存—> 磁盘 —> 目录—>文件

java.io.*

static String pathSeparator  
static char pathSeparatorChar  代表不同系统里面环境变量分隔符   windows: ;  unix:  :
    
static String separator  代表不同系统里面路径分割:  windows: \   unix:  /
static char separatorChar  
File(String pathname) 根据指定(存在或者不存在)文件/目录路径创建File对象
    
File(String parent, String child) 根据指定的父级目录路径 以及指定子目录或者子文件创建File对象
File(File parent, String child)             

1.1 文件

private static void demo1() {
        //File类充当文件
        //路径:
        //1.绝对路径: C:\Users\dn\Desktop\笔记\pic\a.txt.txt   http://www.baidu.com
        //2.相对路径:  ./a.txt/b/c.txt   相对于项目

        String filePath = "E:\\workspace\\one\\day16\\src\\a.txt.txt";
        filePath = "day16/src/b.txt";
        File file = new File(filePath);

        //获得文件属性信息
        System.out.println(file.getName());
        System.out.println(file.getPath());//获得文件相对路径
        System.out.println(file.getAbsolutePath());
        System.out.println(file.length());//获得文件内容大小  字节数

        System.out.println(file.getParent());//获得父级目录路径

        System.out.println(file.lastModified());//获得上一次操作文件时间   毫秒数
        System.out.println(new Date(file.lastModified()));

        //文件权限(几乎不操作)
        System.out.println(file.canRead());
        System.out.println(file.canWrite());
        System.out.println(file.isFile());//判断File对象是否是一个文件
        System.out.println(file.exists());
        System.out.println(file.isHidden());

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

        //删除文件
//        System.out.println(file.delete());
        System.out.println(file.renameTo(new File("day16", "c.txt")));
        //剪切功能+改名

    }
  //一定要保证父级目录存在的  不然无法创建文件成功
//        File file1 = new File("day16/demo/demo1/demo2.txt");
//        System.out.println("创建文件成功!"+file1.createNewFile());

1.2 目录

private static void demo2() {
        //File类充当目录/文件夹
        File directory = new File("day16/src");
        directory = new File("day16","src");
        //获得目录属性信息
        System.out.println(directory.getName());
        System.out.println(directory.getPath());//获得文件相对路径
        System.out.println(directory.getAbsolutePath());
        System.out.println(directory.getParent());//获得父级目录路径

        System.out.println(directory.exists());
        System.out.println(directory.isDirectory());
    }

创建目录

 File file1 = new File("day16/demo");
//        System.out.println(file1.mkdir());//创建1级目录

//        System.out.println(file1.mkdirs());
        file1.delete();//只能删除一个空目录

1.3 递归

查询指定目录下所有的子目录和子文件

//|-src
//| |-com
//| | |-javasm
//| | | |-exercise
//| | | | |-Account.java
//| | | | |-Employee.java
//| | | | |-PM.java
//| | | | |-SE.java
//| | | |-file
//| | | | |-FileDemo.java
//| | | |-stream
//| | | | |-StreamDemo.java
//| | | | |-User.java
//|-test
//| |-com
//| | |-javasm
//| | | |-test
//| | | | |-AccountTest.java
//.......
//File充当目录
String[] list()  //获得当前目录下所有子级目录或者子文件名称
String[] list(FilenameFilter filter)  
    
File[] listFiles() //获得当前目录下所有子级目录或者子文件对象
File[] listFiles(FileFilter filter)  
File[] listFiles(FilenameFilter filter)  
private static void demo4(File directory, String s) {
        Objects.requireNonNull(directory);
        if (!directory.exists()) {
            System.out.println("目录不存在");
            return;
        }
       /* String[] fileName = directory.list();
        System.out.println(Arrays.toString(fileName));*/
        File[] files = directory.listFiles();//获得当前目录下的1级资源
        for (File child : files) {
            System.out.println(s + child.getName());
            if (child.isDirectory()) {
                //是目录  继续寻找子级资源
                //当子级属于目录的时候 再一次listFile
                demo4(child, "| " + s);
                //自己调用自己方法
            }
        }
    }
    private static void demo5(File directory, String s) {
        String[] fileName = directory.list();获得当前目录下的1级资源名称
        for (String childName : fileName) {
            File childFile = new File(directory, childName);
            System.out.println(s + childName);
            if (childFile.isDirectory()) {
                demo5(childFile, "| " + s);
            }
        }
    }

2. IO

输入/输出流。 Input/OutPut 实现不同设备之间的数据的交互(传输)。 键盘 网络 读写数据

流的分类:
 从操作内容:
    字节流
    字符流(纯文本文件  txt  java)
 计算机里面所有的文件二进制的文件   以字节内容存储。 程序/计算机/虚拟机查看   音频  视频  图片 
 字符集(编码格式)---> 将字节内容转换文本文件里面的字符数据。
                
 从流向上:
   输入流
   输出流      
 磁盘文件   程序   数据
 通过java程序读取了磁盘文件中数据:   read  输入流   InputStream
 通过java程序将数据写入磁盘文件中:   write  输出流  OutputStream       

2.1 字节流

可以处理计算机里面任意类型的文件。万能流

1. 字节输入流 InputStream

public abstract class InputStream
extends Object
implements Closeable  资源需要释放
abstract int read()  一次读取一个字节  读到文件末尾 -1
int read(byte[] b)  一次读取b.length个字节内容 将字节内容存储到b数组中   
     返回值: 读到的有效的字节个数   读到文件末尾 -1
int read(byte[] b, int off, int len)  一次读取len个字节内容  将字节内容存储到b数组中 (从指定的off索引位置)
     返回值: 读到的有效的字节个数   读到文件末尾 -1
int available()  --->File.length() 流里面有效的字节个数
void close()  
FileInputStream: 文件输入流
BufferedInputStream: 高效字节输入流
DataInputStream: 数据输入流
ObjectInputStream: 反序列化流
1.1 FileInputStream
FileInputStream(File file) 
FileInputStream(String name) name: 文件路径

read() 一次读取一个字节

private static void testRead1() {
        //读取某个文件内容(文件必须存在)
        String filePath = "day17/src/a.txt";
        InputStream inputStream = null;
        try {
            //1.创建字节输入流对象(打开资源)
            inputStream = new FileInputStream(filePath);
            //2.读取文件内容
           /* int read = inputStream.read();//一次读取一个字节内容
            System.out.println((char)read);
            System.out.println((char)inputStream.read());*/

            //字节流读取字符内容(文本文件)  有可能会出现乱码   UTF-8  一个汉字 3个字节
            //不想出现乱码(读完文件中所有字节内容)

            //循环读取文件中所有字节内容(很少使用read())
//            int read = inputStream.read();
//            while (read != -1) {
//                System.out.print((char)read);
//                read = inputStream.read();
//            }

            int result = 0;
            while ((result = inputStream.read()) != -1) {
                System.out.print((char) result);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //释放资源
            try {
                if (inputStream != null) inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

以上的功能很多都是处理异常的,jdk1.7+ 提供了更加方便的方式去释放流对象

 private static void testRead2() {
        //try...with...resource 1.7+ 提供了更加优雅的方式释放流
        try (
                //流对象的创建
                //实现Closeable接口的类的对象的创建
                InputStream inputStream = new FileInputStream("day17/src/a.txt")) {
            //2.读取文件内容
            int len = 0;
            while ((len = inputStream.read()) != -1) {
                System.out.print((char) len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //流对象到底有没释放?  默认自动执行close方法
    }

read(byte[] by) 一次读取b.length个字节内容 将字节内容存储到b数组中

private static void testRead3() {

        try (
                InputStream inputStream = new FileInputStream("day17/src/a.txt")) {

//            System.out.println(inputStream.available());
//            byte[] bytes = new byte[inputStream.available()];//1024的整数倍

           /* byte[] bytes = new byte[10];

            int availableByteNum = inputStream.read(bytes);//一次读取bytes.length个字节  返回的是有效的字节个数

            System.out.println("availableByteNum:" + availableByteNum);

            //读取的文件内容存储到了byte数组
            //循环遍历字节数组 转成一个个的字符数据
            //字节数组转换成字符串
            //String(byte[] bytes, int offset, int length)
            System.out.println(Arrays.toString(bytes));//

            System.out.println(new String(bytes,0,availableByteNum));*/

            //循环读取
            byte[] bytes = new byte[10];
//            System.out.println(inputStream.read(bytes));
            int len = 0;
            while ((len = inputStream.read(bytes)) != -1) {
                System.out.print(new String(bytes, 0, len));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

int read(byte[] b, int off, int len) 一次读取len个字节内容 将字节内容存储到b数组中 (从指定的off索引位置)
返回值: 读到的有效的字节个数 读到文件末尾 -1

private static void testRead4() {

        try (
                InputStream inputStream = new FileInputStream("day17/src/a.txt")) {

            byte[] bytes = new byte[3];
           /* int len = inputStream.read(bytes,0,bytes.length);//len: 读多少个字节   off: 从指定索引位置存储到字节数组中

            System.out.println(Arrays.toString(bytes));
            System.out.println(len);*/

           int len = 0;
           while((len=inputStream.read(bytes,0,bytes.length))!=-1){//很少用
               System.out.print(new String(bytes,0,len));
           }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //100个字节
    //read()  读了100次  写100次、
    //read(byte[10]) 读了100次     写10次 (写的时候  提升了)   推荐

2. 字节输出流 OutputStream

public abstract class OutputStream
extends Object
implements Closeable, Flushable 
abstract void write(int b)  一次写一个字节
void write(byte[] b)  一次写b.length个字节内容
void write(byte[] b, int off, int len)  
void flush()  
FileOutStream: 文件输出流
BufferedOutStream: 高效字节输出流  自带一个缓冲区  byte[] 8192
DataOutStream: 数据输出流
ObjectOutStream: 序列化流
2.1 FileOutStream
FileOutputStream(File file) 
FileOutputStream(File file, boolean append) 
    
FileOutputStream(String name) 
FileOutputStream(String name, boolean append)  append: 是否在文件末尾追加数据  false
private static void demo1(String path) {

        //通过程序将数据写入文件: 文件不存在  会自动创建文件
        try (
                //1.创建字节输出流对象
                FileOutputStream outputStream = new FileOutputStream(path,false);
        ) {

            //2.写数据
//            outputStream.write(97);
//            outputStream.write('a');
//
//            outputStream.write('\n');
//
//            byte[] bytes = {98,99,100};
//            outputStream.write(bytes);

            outputStream.write("写数据".getBytes());
            outputStream.write('\n');
            outputStream.write("写数据".getBytes(),0,9);
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2 文件复制

文件上传/下载 (读写过程)----> 用户头像上传 商品图片上传 数据导入导出—> 一个方法

将一个磁盘的文件 复制到另外一个路径里面

 //边读边写 不会出现中文的乱码
    public static void copyFile2(String sourceFilePath) {

        if (sourceFilePath == null || "".equals(sourceFilePath)) {
            throw new NullPointerException("参数不能为null");
        }
        long start = System.currentTimeMillis();
        String targetFilePath = PARENT_DIRECTORY + sourceFilePath.substring(sourceFilePath.lastIndexOf(File.separator) + 1);
        try (
                //创建输入流对象
                InputStream inputStream = new FileInputStream(sourceFilePath);
                //创建输出流对象
                OutputStream outputStream = new FileOutputStream(targetFilePath);

        ) {
            //读取原文件数据  read InputStream
            int len = 0;
            //自定义一个缓冲
            byte[] bytes = new byte[1024 * 10];
            while ((len = inputStream.read(bytes)) != -1) {
                //写入目标文件 write  OutPutStream
                outputStream.write(bytes, 0, len);
            }
            long end = System.currentTimeMillis();
            System.out.println("success:" + (end - start));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

高效流

BufferedInputStream(InputStream in) 将基本字节输入流对象构建成高效字节输入流对象
BufferedOutputStream(OutputStream out) 将基本字节输出流对象构建成高效字节输出流对象    
//使用高效字节输出/入流实现文件复制
    public static void copyFile4(String sourceFilePath) {

        if (sourceFilePath == null || "".equals(sourceFilePath)) {
            throw new NullPointerException("参数不能为null");
        }
        long start = System.currentTimeMillis();
        String targetFilePath = PARENT_DIRECTORY + sourceFilePath.substring(sourceFilePath.lastIndexOf(File.separator) + 1);
        try (

                //创建高效的字节输入流对象
                //装饰者设计模式
                BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(sourceFilePath));
                BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(targetFilePath))

        ) {
            //读取原文件数据  read InputStream
            int len = 0;
            byte[] bytes = new byte[1024 * 10];
            //10240>8192  就不使用底层buf  就使用了自定义bytes
            // <8192 效率更快
            while ((len = inputStream.read(bytes)) != -1) {
                //写入目标文件 write  OutPutStream
                outputStream.write(bytes, 0, len);
                //将1个字节写入底层buf  当缓冲满的时候  输出到文件中
            }
            long end = System.currentTimeMillis();
            System.out.println("success:" + (end - start));

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2.3 模拟用户头像上传


    //模拟用户头像上传
    private static final String TARGET_UPLOAD_PATH = "day17/upload/user/";

    public static void fileUpload(String sourceFile) {

        Objects.requireNonNull(sourceFile);
        String sourceFileName = sourceFile.substring(sourceFile.lastIndexOf(File.separator) + 1);//1.png
        //解决文件名称重名
        String randomStr = UUID.randomUUID().toString().replaceAll("-", "");
        String targetFileName = randomStr + "-" + sourceFileName;

        //获得当前时间
        File parentDirectory = new File(TARGET_UPLOAD_PATH, LocalDate.now().toString());
        if (!parentDirectory.exists()) {
            parentDirectory.mkdirs();
        }
        //每一天用户都要执行上传
        //day17/upload/user/2020-12-16

        try (
                BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
                BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(new File(parentDirectory, targetFileName)))
        ) {
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
            }
            System.out.println("success");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

2.4 字符流

字节+编码格式(字符集) UTF-8 gbk 操作纯文本文件 txt java

1. 字符输入流 Reader

public abstract class Reader
extends Object
implements Readable, Closeable
int read()  一次读取一个字符
int read(char[] cbuf)  
abstract int read(char[] cbuf, int off, int len)      
FileReader:
BufferedReader:
InputStreamReader:
1.1 FileReader
FileReader(File file) 
FileReader(String fileName) 
private static void demo1() {

        try (
                Reader reader = new FileReader("day17/src/b.txt");
        ) {
//            int read = reader.read();// -1
//            System.out.println((char) read);
//            int len = 0;
//            while ((len = reader.read()) != -1) {
//                System.out.print((char) len);
//            }

           /* char[] chars = new char[100];
            int len = reader.read(chars);
            System.out.println(len);

            //字符数组转换字符串
            System.out.println(new String(chars,0,len));*/
            char[] chars = new char[100];
            int read = reader.read(chars, 0, chars.length);
            System.out.println(new String(chars,0,read));
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
1.2 BufferedReader

装饰了基本的字符输入的功能。 一次读取一行

BufferedReader(Reader in) 
String readLine()  文件末尾: null
public static void main(String[] args) {
        String path = "day17/src/a.txt";
        List<User> userList = new ArrayList<>(10);
        //读取文件数据: 将每一行数据都转换用户对象
        //输入流: InputStream   Reader
        //id-name-age-pass
        try (
                BufferedReader reader = new BufferedReader(new FileReader(path))
        ) {
            String info = "";
            while ((info = reader.readLine()) != null) {

                String[] infoArray = info.split("-");
                String idStr = infoArray[0];
                String ageStr = infoArray[2];
                userList.add(new User(Integer.parseInt(idStr), infoArray[1], Integer.parseInt(ageStr), infoArray[3]));
            }
            userList.forEach(System.out::println);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2. 字符输出流 Writer

public abstract class Writer
extends Object
implements Appendable, Closeable, Flushable
void write(int c)  
void write(char[] cbuf)
abstract void write(char[] cbuf, int off, int len)  
void write(String str) 
Writer append(char c)  
Writer append(CharSequence csq)  
FileWriter:
BufferedWriter:
OutputStreamWriter:
2.1 FileWriter
FileWriter(File file, boolean append) 
FileWriter(String fileName, boolean append) 
FileWriter(String fileName) 
FileWriter(File file) 
public static void main(String[] args) {

        try (
                Writer writer = new FileWriter("day17/src/c.txt", false)
        ) {
            writer.write('我');

            writer.write("我们".toCharArray());//很少用

            writer.write("尚马教育");
            writer.write("\n");

            writer.write("abc".toCharArray(),0,3);

            writer.append("hdfgr");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
2.2 BufferedWriter
BufferedWriter(Writer out) 
private static void testBufferedWriter() {

        //模拟用户注册  永久保存用户的信息
        Scanner input = new Scanner(System.in);
        String answer;
        String path = "day17/src/a.txt";
        try (
//                    Writer writer = new FileWriter(path,true)
                BufferedWriter writer = new BufferedWriter(new FileWriter(path, true))
        ) {
            do {
                System.out.println("请录入用户name:");
                String name = input.nextLine();//读取到用户在控制台录入的数据   流  输入流
                System.out.println("请录入用户age:");
                String age = input.nextLine();
                System.out.println("请录入用户pass:");
                String pass = input.nextLine();

                //id-name-age-pass
                String userInfo = String.join("-", String.valueOf(idIndex++), name, age, pass);
                writer.write(userInfo);
                writer.newLine();
                writer.flush();//将缓冲区数据刷出到文件中

                System.out.println("是否继续?y/n");
                answer = input.nextLine();
            } while ("y".equals(answer));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2.5 其它流

1. 数据流(字节流)

装饰了基本字节流的功能 提供一些功能方法 可以操作字面量类型的数据。 (基本+string)

前提: 必须先写 再去读

DataInputStream
DataOutputStream
public class DataOutputStream
extends FilterOutputStream
implements DataOutput
    
DataOutputStream(OutputStream out) 
DataInputStream
 public class DataInputStream
extends FilterInputStream
implements DataInput   

2. 序列化流(对象(字节)流)

先写再读 装饰了数据流的功能

序列化: writeObj 当需要将一个对象存储到文件中 写一个对象

反序列化: readObj 将磁盘文件中对象的字节数据转成程序里面对象

1. 需要将对象存储文件中
2. RMI(远程接口调用)---> 访问第三方的接口 ---> 传参+返回数据
    
    以后咱们项目中: 尤其实体类  可以被序列化  实现标识性接口: Serializable
ObjectOutputStream
ObjectInputStream   
public class ObjectOutputStream
extends OutputStream
implements ObjectOutput, ObjectStreamConstants
    
ObjectOutputStream(OutputStream out)     
writeObject(Object obj) 
public class ObjectInputStream
extends InputStream
implements ObjectInput, ObjectStreamConstants
 
Object readObject()  
 
ObjectInputStream(InputStream in) 
private static void testWriteObj() {
        //创建用户对象
        User user = new User(1001, "jim", "1234", 20, null);
        System.out.println("user:" + user);//user:com.javasm.io.User@74a14482
        try (
                //创建对象输出流  将对象写入文件中
                ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream("day18/src/user.ini"));
        ) {
            objectOutput.writeObject(user);

            System.out.println("序列化对象成功");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
private static void testReadObj() {
        //创建对象输入流  读取流里面的字节数据  将字节数据转换成对象
        try (
                ObjectInput objectInput = new ObjectInputStream(new FileInputStream("day18/src/user.ini"));
        ) {
            //反序列化 新的对象---> jvm底层的实现(并没有调用类的构造方法)
            User newUser = (User) objectInput.readObject();
            System.out.println("newUser:" + newUser);
            //newUser:com.javasm.io.User@3941a79c
            System.out.println(newUser.getId());
            System.out.println(newUser.getName());
            System.out.println(newUser.getPass());
            System.out.println(newUser.getAge());
            //克隆:
            //浅克隆:
            //深克隆: ===> 反序列化
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
//标识类对象可以被序列化成功
public class User implements Serializable {
    //自动生成的(结合工具提示)
    private static final long serialVersionUID = 6479438762319294602L;

    //对于一些安全性级别比较高的数据  不想反序列的时候  看到这些数据 可以添加transient修饰   数据就是默认值了
    //RMI:

    private Integer id;
    private String name;
    private transient String pass;
    private Integer age;
    private String cardNo;

    //只要我们修改了源代码  肯定需要再一次编译  javac
    //产生新的class文件 都有一个版本号  标识class文件唯一性
    //java.io.InvalidClassException: 序列化的时候 class版本的id  与重新编译生成的版本号id 不一致

    //1.只能先序列化  然后再反序列化
    //2.不管类升级迭代多少次  都能反序列化成功   创建类的时候  给类固定一个版本号
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fgUB8jyj-1608214020159)(pic\版本号id .png)]

3. 转换流(字符流)

使用转换流 必须结合高效字符流处理。

字节转字符(常用)

需要抓取一些网络一些小说的章节内容:
   http://book.zongheng.com/chapter/907701/59100292.html
   https://read.qidian.com/chapter/YuM01v2tgLmdkflPPo43eA2/TF8tp5RUeaS2uJcMpdsVgA2
将数据存入本地文件:(万维网的资源    所有的数据都是字节内容)
InputStreamReader(InputStream in, Charset cs)   使用指定的编码格式将字节转换成对应的字符 
private static void testZhuanHuan(String novelPath) {

        //获得路径资源
        //将资源写入文件里面:  write  输出流  用字符流更加快  Writer--->BufferedWriter
        //网络资源: 万维网资源(统一资源定位符)---> java.net.URL

//        try {
//            InputStream inputStream = new URL(novelPath).openStream();
//        } catch (MalformedURLException e) {
//            e.printStackTrace();
//        }

        //需要Reader一个对象  资源在inputStream  需要将字节输入流转换成字符流对象
        //需要使用转换流:
        try (
//                BufferedReader reader = new BufferedReader(new FileReader(novelPath));
                BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(novelPath).openStream(),Charset.forName("utf-8")));
                BufferedWriter writer = new BufferedWriter(new FileWriter("day18/novel.txt"));
        ) {

            String content = "";
            while ((content = reader.readLine()) != null) {
//                writer.write(content);
//                writer.newLine();
//                System.out.println(content);
                if(content.contains("<div class=\"read-content j_readContent\" id=\"\">")){
                    content = reader.readLine();
                    content = content.replaceAll("[<p>]","\n");
                    writer.write(content);
                    break;
                }
            }
            //<div class="read-content j_readContent" id="">
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

字符转字节(了解)

 private static void testZhuanHuan2() {
        //字符转字节
        //OutputStreamWriter
//        System.out.println("学习");//将内容写到控制台  write
        //使用字符流将数据打印输出到控制台上
        String str = "使用字符流将数据打印输出到控制台上";
        try (
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
        ) {
            writer.write(str);
            //写的是字符的数据, 但是目的地是控制台 System.out(PrintStream)
            //字符转字节   OutputStreamWriter
        } catch (IOException e) {
            e.printStackTrace();
        }
   }

4. Properties

map集合的实现类 里面的数据也是键值对 key—value 属性集 属性名称----属性值

public class Properties
extends Hashtable<Object,Object>  
public class PropUtil {
    //有且只加载一次资源数据
    private PropUtil() {
    }
    
    private static Properties properties;

//    private static final String FILE_PATH = "day18/src/user.properties";
    private static final String FILE_PATH = "user.properties";

    //整个项目运行在服务器里面的 服务器里面没有src目录的
    //服务器部署的是编译之后的资源的内容(class+配置+静态资源)
    //加载的是编译路径下的资源文件
    //jvm加载class文件的流程: 类加载器加载器  ClassLoader(双亲委派机制) ===>编译路径的根路径
    
    //只要找到(自定义的java)项目里面class了  等同于找到资源文件的位置 了
   //等同于找到某个class文件所对应的Class类对象

    static {
        properties = new Properties();
        try {
//            properties.load(new FileInputStream(FILE_PATH));
//            Class<PropUtil> utilClass = PropUtil.class;//PropUtil.class 找到了他的位置
//            properties.load(PropUtil.class.getResourceAsStream(FILE_PATH));

            properties.load(PropUtil.class.getClassLoader().getResourceAsStream(FILE_PATH));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static String getValue(String key) {
        Objects.requireNonNull(key);
        return properties.getProperty(key,"");
    }
}

() {
}

private static Properties properties;

// private static final String FILE_PATH = “day18/src/user.properties”;
private static final String FILE_PATH = “user.properties”;

//整个项目运行在服务器里面的 服务器里面没有src目录的
//服务器部署的是编译之后的资源的内容(class+配置+静态资源)
//加载的是编译路径下的资源文件
//jvm加载class文件的流程: 类加载器加载器  ClassLoader(双亲委派机制) ===>编译路径的根路径

//只要找到(自定义的java)项目里面class了  等同于找到资源文件的位置 了

//等同于找到某个class文件所对应的Class类对象

static {
    properties = new Properties();
    try {

// properties.load(new FileInputStream(FILE_PATH));
// Class utilClass = PropUtil.class;//PropUtil.class 找到了他的位置
// properties.load(PropUtil.class.getResourceAsStream(FILE_PATH));

        properties.load(PropUtil.class.getClassLoader().getResourceAsStream(FILE_PATH));
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public static String getValue(String key) {
    Objects.requireNonNull(key);
    return properties.getProperty(key,"");
}

}




















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值