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:\users\baidawei\downloads   相对路径 表示的是路径之间的相对关系 如: /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 \r\n my name is david”; // 换行\r\n  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){ //特有方法 读取一整行 返回字符串 不包含\r\n换行符号 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() 线程都唤醒。 这些方法都是在 同步中才有效。同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程。  

    原文作者:海盗船长
    原文地址: https://www.cnblogs.com/baidawei/p/8778793.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞