• Java IO流对象、多线程


    Input(读) Output(写)操作
    File类
    import java.io.File;
    将操作系统中的文件、目录(文件夹)、路径、封装成File对象
    提供方法,操作系统中的内容。File与系统无关的类。
    String pathSeparator = File.pathSeparator;
    System.out.println(pathSeparator); // windows';' Linux ':' 路径分割符
    String separator = File.separator;
    System.out.println(separator); // 斜线 / 目录的名称分割符 linux:
     
    构造方法
    File(String pathName)
     
    绝对路径
    在系统中具有唯一性 如:c:usersaidaweidownloads
     
    相对路径
    表示的是路径之间的相对关系 如: /downloads/  不需要考虑根级目录具体盘符
     
    创建文件
    File file = new File("c:\Users\baidawei\Downloads\o.txt");
    if(!file.exists()){
        boolean result = file.createNewFile();
        System.out.println(result);
    }
    Mac:
    File file = new File("/Users/baidawei/Desktop/test.txt");
    boolean result = file.createNewFile();
    System.out.println(result);
     
    创建目录
    boolean result = file.mkdir();
     
    删除
    boolean result = file.delete();
     
    获取文件名或文件夹名
    String fileName = file.getName(); //test.txt
     
    获取文件路径
    file.getPath() // /Users/baidawei/Desktop/test.txt
     
    获取文件字节长度
    file.length()
     
    获取绝对路径 返回字符串
    file.getAbsolutePath() // /Users/baidawei/Desktop/test.txt
     
    获取绝对路径 返回file类
    file.getAbsoluteFile()  // /Users/baidawei/Desktop/test.txt
     
    获取父路径 返回字符串
    file.getParent() // /Users/baidawei/Desktop
     
    获取父路径 返回File类
    file.getParentFile() // /Users/baidawei/Desktop
     
    文件或目录是否存在
    file.exists() // boolean
     
    判断是否是目录
    file.isDirectory() // boolean
     
    获取路径中的文件和文件夹名 返回String[]
    for(String str : file.list()){
        System.out.println(str);
    }
     
    获取路径中的文件和文件夹名 返回File[]
    for(File f : file.listFiles()){
        System.out.println(f.getName());
    }
     
    过滤器 
    for (File f : file.listFiles(new myFilter())) {
        System.out.println(f.getName());
    }
     
    class myFilter implements FileFilter {
        @Override
        public boolean accept(File pathname) {
            if(pathname.isDirectory()){
                return true;
            }
            return false;
        }
    }
     
    递归获取全文件
    public static void main(String[] args) {
    File file = new File("F://");
    getAllDir(file);
    }
     
    public static void getAllDir(File dir) {
    if (dir.listFiles() != null) {
    for (File f : dir.listFiles()) {
    if (f.isDirectory()) {
    getAllDir(f);
    } else {
    System.out.println(f);
    }
    }
    }
    }
     
    字节流
    字节输出流 OutputStream 所有输出流父类
    常用方法:
    write(int b) 写入1个字节
    write(byte[] b) 写入字节数组
    write(byte[] b,int ,int) 写入字节数组,int 开始写入的索引, int 写几个
    close() 关闭流对象,释放与流相关的资源
     
    FileOutputStream 写入数据文件 OutputStream的子类
    FileOutputStream fos = new FileOutputStream("F://text.txt");
    fos.write(97);
    fos.write(98);
    fos.write(99);
    fos.close();
    没有就创建,有就覆盖 abc
     
    byte[] bytes = {65,66,67,68,69,70};
    fos.write(bytes);//ABCDEF
    fos.close();
     
    byte[] bytes = {65,66,67,68,69,70};
    fos.write(bytes,1,2);//BC
    fos.close();
     
    写字符串
    String strs = "Hello Word my name is david"; // 换行  
    byte[] bytes = strs.getBytes();
    fos.write(bytes);
    fos.close();
     
    续写文件,FileOutputStream构造方法第二个参数设置为true 就不会覆盖了
    FileOutputStream fos = new FileOutputStream("F://text.txt",true);
     
    字节输入流 InputStream 所有字节输入流的父类
    读取任意文件,每次只读取1个字节。
    read(int b) 读取1个字节
    read(byte[] b) 读取字节数组
    close() 关闭流对象
     
    FileInputStream 读取数据文件 InputStream子类
     
    读取字节:
    public static void main(String[] arg) throws IOException {
    FileInputStream fis = new FileInputStream("F://text.txt");
    int len = 0;
    while((len=fis.read()) != -1){ // -1就是没了
    System.out.println(len); //输出字节 len代表执行一次
    }
    fis.close();
    }
     
    读取字节数组(字符串):
     
    public static void main(String[] arg) throws IOException {
    FileInputStream fis = new FileInputStream("F://text.txt");
    byte[] b = new byte[1024];
    int len = 0;
    while((len=fis.read(b)) != -1){
    System.out.print(new String(b,0,len)); //调用String构造方法 参数 字节数组
    }
     
    fis.close();
    }
     
    复制文件
    字节复制 效率低
    FileInputStream fis = new FileInputStream("F:\text.txt");
    FileOutputStream fos = new FileOutputStream("F:\copy\text.txt");
     
    int len = 0;
    while((len=fis.read()) != -1){
    fos.write(len);
    }
    fis.close();
    fos.close();
     
    字节数组赋值 提高效率
    FileInputStream fis = null;
    FileOutputStream fos = null;
     
    try{
    fis = new FileInputStream("F:\text.txt");
    fos = new FileOutputStream("F:\copy\text.txt");
     
    int len = 0;
    byte[] b = new byte[1024];
    while((len=fis.read(b)) != -1){
    fos.write(len);
    }
    }catch(Exception ex){
    System.out.print(ex.getMessage());
    }finally {
    fis.close();
    fos.close();
    }
     
    FileWriter类 字符输出流 写文本
    write(int c) 写1个字符
    write(char[] c) 写字符数组
    write(char[] c,int ,int)字符数组,开始索引,多少个
    write(String s) 写字符串
     
    FileWriter fw = new FileWriter("F:\text.txt");
    //写1个字符
    fw.write(100);
    //最好写一次刷一次,释放内存
    fw.flush();
    //写1个字符数组
    fw.write(new char[]{99,98,97,96});
    //写1个字符数组 1开始 3个
    fw.write(new char[]{99,98,97,96},1,3);
    //写字符串
    fw.write("有一个姑娘,他有一些嚣张");
    //刷新 write一次 刷新一次
    fw.flush();
    //关闭
    fw.close();
    续写 构造方法第二个参数true
    FileWriter fw = new FileWriter("F:\text.txt",true);
     
    FileReader累 字符输入流 读取文本
    FileReader fr = new FileReader("F:\text.txt");
    //读1个字节
    int len = 0;
    while((len=fr.read()) != -1){
    System.out.print((char)len);
    }
    fr.close();
     
    读取字符数组
    char[] c = new char[1024];
    int len = fr.read(c);
    System.out.println(new String(c,0,len));
    fr.close();
     
    转换流
    解决乱码问题
    因为写文件时会默认本机编码表,GBK,美国机器打开就会乱码。
     
    使用OutputStreamWriter(OutputStream out) 读取文件可以指定编码类型
    FileOutputStream fos = new FileOutputStream("/Users/baidawei/Desktop/gbk.txt");
    //使用转换流指定编码表
    OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK"); //默认GBK可以不写
    osw.write("你好");
    osw.flush();
    osw.close();
     
    使用UTF-8编码表
    OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
     
    UTF-8 编码表中 一个汉字3个字节。
     
    使用InputStreamReader类写入文件指定编码类型。
    //如果编码格式不一致则会乱码
    public static void main(String[] args) throws IOException {
    FileInputStream fis = new FileInputStream("/Users/baidawei/Desktop/utf.txt");
    InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
    int len = 0;
    while((len=isr.read()) != -1){
    System.out.println((char)len);
    }
    fis.close();
    }
     
    缓冲流
    提高读写速度、效率。
     
    字节输出流的缓冲流 BufferedOutputStream(OutputStream out)
    FileOutputStream fos = new FileOutputStream("/Users/baidawei/Desktop/gbk.txt");
    //使用缓冲流
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    bos.write("加班中...".getBytes());
    bos.close();
     
    字节输入流的缓冲流 BufferedInputStream(InputStream input)
    FileInputStream fis = new FileInputStream("/Users/baidawei/Desktop/gbk.txt");
    //使用缓冲流
    BufferedInputStream bis = new BufferedInputStream(fis);
    int len = 0;
    byte[] b = new byte[1024];
    while((len=fis.read(b)) != -1){
    System.out.print(new String(b,0,len));
    }
     
    字符输出流缓冲流BufferedWriter
    public static void main(String[] args) throws IOException {
    String url = "/Users/baidawei/Desktop/test.txt";
    FileWriter fw = new FileWriter(url);
    BufferedWriter bfw = new BufferedWriter(fw);
    bfw.write("测试bufferedWriter输出流缓冲流");
    bfw.flush();
    //特有换行方法
    bfw.newLine();
    bfw.write("newline好使么?");
    bfw.flush();
    bfw.close();
    }
     
    字符输入流缓冲流BufferedReader
    public static void main(String[] args) throws IOException {
    String url = "/Users/baidawei/Desktop/test.txt";
    FileReader fr = new FileReader(url);
    BufferedReader br = new BufferedReader(fr);
     
    String line = null;
     
    while((line = br.readLine()) != null){
    //特有方法 读取一整行 返回字符串 不包含 换行符号
    System.out.println(line);
    }
    }
     
    复制
    public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader("/Users/baidawei/Desktop/test.txt"));
    BufferedWriter bw = new BufferedWriter(new FileWriter("/Users/baidawei/Desktop/test_bak.txt"));
     
    String line = null;
     
    while((line = br.readLine()) != null){
    bw.write(line);
    bw.newLine();
    }
    br.close();
    bw.close();
    }
     
    Properties类
    Properties类是Hashtable的子类,实现Map接口,Hashtable是线程不安全的被Hashmap替换。
    键值对 都是字符串,可以和IO对象结合使用,实现持久化存储(可以存储到硬盘、u盘、光盘)上。
    Properties pp = new Properties();
    //存入 等同于put 区别只能字符串
    pp.setProperty("key","value");
    pp.setProperty("yu","datou");
    System.out.println(pp);
     
    //通过key获取value
    String val = pp.getProperty("yu");
    System.out.println(val);
     
    //获取所有key
    for(String s :pp.stringPropertyNames()){
    System.out.println(pp.getProperty(s));
    }
     
    load() 加载方法
    Properties pp = new Properties();
    //.properties 后缀为 键值对配置文件
    FileReader fr = new FileReader("/Users/baidawei/desktop/test.properties");
    pp.load(fr);
    System.out.println(pp);
    fr.close();
     
    test.properties文件格式固定 必须这样 不能加空格 分号
    name=zhagnsan
    age=18
    #email=853020304@qq.com
    #后面是注视
     
    store() 保存方法
    Properties pp = new Properties();
    pp.setProperty("firstname","zhagn");
    pp.setProperty("lastname","san");
    pp.setProperty("email","83@qq.com");
    FileWriter fw = new FileWriter("/Users/baidawei/desktop/test.properties");
    pp.store(fw,"yuanyin buneng zhognwen"); //写中文会转换为unicode编码表存储
    fw.close();
    对象的序列化
    对象中的数据new Person();以流的形式写入到文件中保存的过程称为写出对象。
    ObjectOutputStream 写出对象 对象的序列化
    //类需要实现Serializable接口
    public class Person extends Object implements Serializable {
    private String name;
    private int age;
     
    Person(String name){
    this.name = name;
    }
     
    Person(String name,int age){
    this(name);
    this.age = age;
    }
     
    @Override
    public String toString(){
    return "Person[name" + name + ", age =" + age +"]";
    }
    }
     
    Person p = new Person("name",18);
    FileOutputStream fos = new FileOutputStream("/Users/baidawei/desktop/oos.text");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(p);
    oos.close();
    fos.close();
     
    ObjectInputStream 读取对象 对象的反序列化
    FileInputStream fis = new FileInputStream("/Users/baidawei/desktop/oos.text");
    ObjectInputStream ois = new ObjectInputStream(fis);
    Object obj = ois.readObject();
    System.out.println(obj);
    ois.close();
     
    属性值静态的 static 不能序列化
    属性值 加transient关键字 阻止序列化
     
    Serializable接口 没有抽象方法 只是一个标记
     
    打印流
    只负责数据目的输出
    PrintStream
    接收File类型,字符串文件名,OutputStream输出流
    PrintWriter
    //输出目的FIle
    public static void printStream_file() throws FileNotFoundException {
    File file = new File("/Users/baidawei/desktop/myTest.txt");
    PrintWriter pw = new PrintWriter(file);
    pw.println("啥意思啊"); //原样输出
    pw.println("啥意思啊嗯?");
    pw.flush();
    pw.close();
    }
     
    //输出String文件名
    public static void printWriter_fileName() throws FileNotFoundException{
    PrintWriter pw = new PrintWriter("/Users/baidawei/desktop/myTest2.txt");
    pw.println("hahahehehhe");
    pw.println("hahahhaha");
    pw.flush();
    pw.close();
    }
     
    //输出OutputStream 输出流对象可以 开启自动刷新
    public static void printWriter_outputStream() throws FileNotFoundException{
    PrintWriter pw = new PrintWriter(new FileOutputStream("/Users/baidawei/desktop/myTest3.txt"),true);
    pw.println("333");
    pw.println("444");
    pw.flush();
    pw.close();
    }
     
    commons-io工具类
    简化File操作类
    下载后 在Idea中选择File->Project Structure->Dependencies->加号->JARs or directories->ok->External Libraries中就出现了
    FilenameUtils类
    String url = "/Users/baidawei/Desktop/myTest.txt";
     
    //获取文件扩展名
    String ext = FilenameUtils.getExtension(url);
    System.out.println(ext); //txt
     
    //获取文件名
    String fileName = FilenameUtils.getName(url);
    System.out.println(fileName); ///myTest.txt
     
    //是否是txt文件
    boolean isExtens = FilenameUtils.isExtension(url,"txt");
    System.out.println(isExtens);
     
    FileUtils类
    String url = "/Users/baidawei/Desktop/haha.txt";
     
    //读取文件 返回String
    String s = FileUtils.readFileToString(new File(url));
    System.out.println(s);
     
    //写String到文件
    FileUtils.writeStringToFile(new File("/Users/baidawei/Desktop/haha.txt"),"字符串 要写的内容");
     
    //复制文件
    FileUtils.copyFile(new File("/Users/baidawei/Desktop/haha.txt"),new File("/Users/baidawei/Desktop/new.txt"));
     
    //复制文件夹 macnew
    FileUtils.copyDirectory(new File("/Users/baidawei/Downloads/mac"),new File ("/Users/baidawei/Downloads/macnew"));
     
    //复制到目标文件里面去 macnew/mac
    FileUtils.copyDirectoryToDirectory(new File("/Users/baidawei/Downloads/mac"),new File ("/Users/baidawei/Downloads/macnew"));
     
    多线程
    进程:当一个程序进入内存运行,就变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。 如 迅雷软件运行中
    线程:线程是进程的一个执行单元,负责当前继承中的程序执行,一个进程中至少有一个线程,可以有多个线程。 如迅雷软件中 同时下载3个任务
     
    程序运行原理
    分时调度:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间。
    抢占式调度:优先让优先级高的线程使用CPU,如果线程优先级相同,那么会随机选择一个,Java使用的为抢占式调度。
     
    Main方法是主线程
    public static void main(String[] args) {
    SayHi();
    System.out.println("===========================单线程======================");
    }
     
    public static void SayHi() {
    for (int i = 0; i < 100000; i++) {
    System.out.println(i);
    }
    }
    需要等待10万次执行结束后 才能执行 最下面的输出。
     
    Thread类
    Thread类是程序中的线程类,允许应用程序并发地运行多个执行线程。
    创建执行线程有两种方法,
    1:继承Thread类,重写run方法 创建对象,开启线程,run方法相当于其他线程的main方法。
    2:实现Runnable接口,重写run方法。创建runnable的子类对象,传入到某个线程的构造方法中,开启线程。
    方法一继承Thread类:
    public class SubThread extends Thread {
    @Override
    public void run() {
    for(int i = 1;i<50;i++){
    System.out.println(i+"A");
    }
    }
    }
    //并发执行 一起循环
    public class Main {
    public static void main(String[] args) {
    SubThread st = new SubThread();
    st.start();//运行子类 run方法
    for (int i = 0; i < 50; i++) {
    System.out.println(i);
    }
    }
    }
     
    获取线程的名字
    public class SubThread extends Thread {
    @Override
    public void run() {
    for(int i = 1;i<50;i++){
    //获取线程的名字 父类的方法
    System.out.println(getName());
    System.out.println(i+"A");
    }
    }
    }
     
    Thread.currentThread().getName() //当前线程的名字
    程序主线程名字:main,自定义的线程:Thread-0、Thread-1数字顺延 也可以使用setName()自定义线程名称
    sleep()方法 睡眠多少毫秒在执行
     
    方法二:实现Runnable接口
    public class SubThread implements Runnable {
    @Override
    public void run() {
    for(int i = 1;i<50;i++){
    System.out.println(i+"A");
    }
    }
    }
    public static void main(String[] args) {
    SubThread st = new SubThread();
    Thread th = new Thread(st);
    th.start();
    for (int i = 0; i < 50; i++) {
    System.out.println(i);
    }
    }
     
    线程池
    线程池是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。
    实现Runnable接口
    public class ThreadPoolRunnable implements Runnable {
    public void run(){
    System.out.println(Thread.currentThread().getName());
    }
    }
    //创建线程池对象 包含2个线程对象
    ExecutorService es = Executors.newFixedThreadPool(2);
    //从线程池创建对象
    es.submit(new ThreadPoolRunnable());
    es.submit(new ThreadPoolRunnable());
     
    多线程 安全问题
    //并发问题 同时判断为true 执行了多次
    SubThread st = new SubThread();
     
    Thread t0 = new Thread(st);
    Thread t1 = new Thread(st);
    Thread t2 = new Thread(st);
     
    t0.start();
    t1.start();
    t2.start();
     
    public class SubThread implements Runnable {
     
    private int count = 1;
     
    @Override
    public void run() {
    while(true){
    if(count > 0){
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + "出售第:" + --count);
    }
    }
    }
    }
     
    解决线程安全:
    1.同步代码块 synchronized(锁对象)
    用于解决线程安全问题,同步执行,第一个线程执行完后再执行下一个线程。多个线程时,使用同一个锁对象才能够保证线程安全。
    //lock是定义的一个object 对象
    synchronized (lock){
    if(count > 0){
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + "出售第:" + --count);
    }
    }
     
    2.同步方法 synchronized 不需要写锁对象 是本类对象this
    public synchronized void method(){
    //可能会产生线程安全问题的代码
    }
     
    Lock接口
    Lock实现了比使用synchronized方法和语句获得更广泛的锁定操作。
    实现类 ReentrantLock
    lock() 锁
    unlock() 释放锁
     
    public void run() {
    while (true) {
    lock.lock(); //锁住
    if (count > 0) {
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + "出售第:" + --count);
    }
    lock.unlock(); //释放
    }
    }
    }
     
    线程的死锁
    当线程任务出现了多个同步(多个锁)时,如果同步中潜逃了其他的同步,这时容易引发一种现象:程序出现无限等待,这种现象称之为死锁。
    synchronzied(A锁){
    synchronized(B锁){
     
    }
    }
     
    线程等待与唤醒
    wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。
    notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。
    notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。
    这些方法都是在 同步中才有效。同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程。
     
  • 相关阅读:
    git版本超前了N个版本且落后了N个版本的解决办法
    CSS3与动画有关的属性transition、animation、transform对比
    禁止选中文本JS
    页面加载中jquery逐渐消失效果实现
    localstorage和sessionstorage上手使用记录
    点击除元素以外的任意地方隐藏元素js
    js准确获取当前页面url网址信息
    301、404、200、304、500HTTP状态
    对事件委托绑定click的事件的解绑
    RabbitMQ的安装和使用Python连接RabbitMQ
  • 原文地址:https://www.cnblogs.com/baidawei/p/8778793.html
Copyright © 2020-2023  润新知