java io 多线程_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() 线程都唤醒。

这些方法都是在 同步中才有效。同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值