快速Get-JAVA-IO流
第四阶段 IO
IO流
前言:
前面的学习我们只能够在已有的一定封闭范围内进行一些操作,但是这显然是无趣的,也是不支持我们实现一些复杂的需求,所以Java提供IO流这样一种概念,方便我们对数据进行操作
而使用IO流我们可以实现一些强大的功能,例如针对文件的移动复制等操作,又或者程序与外部文件之间的数据存储或者读取,又或者实现一个实时的聊天程序(网络编程),其中数据的传输也用到了我们的IO流,这些内容我们都会在后面设计,下面我就开始IO流的正式学习
(一) IO流的概述及分类
(1) 概念
IO 即 input/output(输入/输出),流的概念还是有一些陌生的
“流”从字面看来就是类似水流的概念,其具有方向性,流动性,连续性、并且可以承载一些事物,而在我们计算机中,“流”是对一种有序连续具有方向性的数据的抽象描述。其本质就是数据的传输,而根据其特点将其抽象封装为各种类,更加方便了用户的操作
(2) 分类
A:流向
- 输入流——读取数据
- 输出流——写出数据
B:数据类型
- 字节流
- 字节输入流——InputStream
- 字节输出流——OutputStream
- 字符流
- 字符输入流——Reader
- 字符输出流——Writer
注意:
a: 如果我们没有明确说明按照什么分,默认按照数据类型分。
b: 除非文件用windows自带的记事本打开我们能够读懂,才采用字符流,否则建议使用字节流。
(二) 字节流
(1) FileOutputStream 写出数据
A:操作步骤
- 创建字节输出流对象
- 调用writer()方法
- 释放资源
B:代码体现
FileOutputStream fos = new FileOutputStream("fos.txt");
for.write("hello".getBytes());
fos.close;
换行操作
因为不同的系统针对不同的换行符号识别是不一样的
windows:\r\n linux:\n Mac:\r
而一些常见的高级记事本是可以识别任意换行符号的
如何实现数据的追加写入 ?
用构造方法带第二个参数是true的情况即可
FileOutputStream fos = new FileOutputStream("fos.txt", true);
(2) FileInputStream 读取数据
A:操作步骤
- 创建字节输入流对象
- 调用writer()方法
- 释放资源
B:代码体现
FileInputStream fis = new FileInputStream("fos.txt");
//使用FileInputStream对指定路径下内容进行读取,可以结合FileOutputStream实现对文件的操作
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("F:\\fos.txt");
//方式一
int by = 0;
while ((by = fis.read()) != -1){
System.out.print((char)by);
}
//方式二(这种方式更加快,推荐)
//数组长度一般是1024或者1024的整数倍
byte[] bys = new byte[1024];
int len = 0;
while((len = fis.read(bys))!=-1){
System.out.print(new String(bys,0,len));
}
//释放资源
fis.close();
}
}
(3) 字节缓冲流
//统计这段程序运行时间
long start = System.currentTimeMillis();
//受测试代码
long end = System.currentTimeMillis();
System.out.println("共耗时" + (end - start) + "毫秒");
字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流
//字节缓冲输出流
BuffereOutputStream
//字节缓冲输入流
BufferedInputStream
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferedOutputStreamDemo {
public static void main(String[] args) throws IOException {
// FileOutputStream fos = new FileOutputStream("F:\\fos.txt");
// BufferedOutputStream bos = new BufferedOutputStream(fos);
//简单写法
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\fos.txt"));
//写数据
bos.write("hello".getBytes());
//释放资源,注意不需要fos.close
bos.close();
}
}
为什么不传递一个具体的文件或者文件路径,而是传递一个OutputStream对象呢?
原因很简单,字节缓冲区流仅仅提供缓冲区,为高效而设计的。但是呢,真正的读写操作还得靠基本的流对象实现。
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
method1("E:\\夜曲.mp3", "F:\\Test1.mp3");
method2("E:\\夜曲.mp3", "F:\\Test2.mp3");
method3("E:\\夜曲.mp3", "F:\\Test3.mp3");
method4("E:\\夜曲.mp3", "F:\\Test4.mp3");
long end = System.currentTimeMillis();
System.out.println("共耗时" + (end - start) + "毫秒");
}
//基本字节流一次读写一个字符
public static void method1(String srcString, String deskString) throws IOException {
FileInputStream fis = new FileInputStream(srcString);
FileOutputStream fos = new FileOutputStream(deskString);
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}
fis.close();
fos.close();
}
//基本字节流一次读写一个字节数组
public static void method2(String srcString, String deskString) throws IOException {
FileInputStream fis = new FileInputStream(srcString);
FileOutputStream fos = new FileOutputStream(deskString);
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
fis.close();
fos.close();
}
//高效字节流一次读写一个字节
public static void method3(String srcString, String deskString) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString));
BufferedOutputStream bos = new
BufferedOutputStream(new FileOutputStream(deskString));
int by = 0;
while ((by = bis.read()) != -1) {
bos.write(by);
}
bis.close();
bos.close();
}
//高效字节流一次读写一个字节数组
public static void method4(String srcString, String deskString) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString));
BufferedOutputStream bos = new
BufferedOutputStream(new FileOutputStream(deskString));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
}
}
//运行结果
共耗时125961毫秒
共耗时143毫秒
共耗时1356毫秒
共耗时29毫秒
由此可见在上述四种方式中,效率最高的还是最后一种——高效字节流一次读写一个字节数组!
(三) 字符流
我们在开发中,如果想要对我们所能识别的文本内容进行数据的传输,如果我们继续使用我们上面所学习的字节流,我们就会发现显示出来的内容是乱码,这是因为编码出现了问题,而这个时候我们就会用到我们的字符流,我们可以先简单的认识 字符流 = 字节流 + 编码
(1) 编码解码
字节流我们前面已经有了一定的认识,那么什么是编码和解码呢?
编码是信息从一种形式或格式转换为另一种形式的过程;解码则是编码的逆过程。
我们先通过一个例子来了解一下它的流程
//通过指定的字符集解码字节数组
String(byte[] bytes, String charsetName)
//使用指定的字符集合把字符串编码为字节数组
byte[] getBytes(String charsetName)
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class EncodingDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
String s = "理想";
//String - byte[] - 编码
byte[] bys = s.getBytes(); //[-25, -112, -122, -26, -125, -77]
// byte[] bys = s.getBytes("UTF-8"); //[-25, -112, -122, -26, -125, -77]
// byte[] bys = s.getBytes("GBK"); //[-64, -19, -49, -21]
System.out.println(Arrays.toString(bys));
//byte[] - String - 解码
String string = new String(bys); //理想
// String string = new String(bys,"UTF-8"); //理想
// String string = new String(bys,"GBK"); //鐞嗘兂
System.out.println(string);
}
}
发送过程:“理想” —— 数字 —— 二进制 —— 发送
接收过程:接收 —— 二进制 —— 十进制 —— 数值 —— 字符 —— “理想”
其实简单的总结就是:
编码:把看得懂的变成看不懂的
解码:把看不懂的变成看得懂的
(2) 字符输入输出流
OutputStreamWriter 字符输出流(写出)
public OutputStreamWriter(OutputStream out)
public OutputStreamWriter(OutputStream out,String charsetName)
InputStreamReader 字符输入流(读取)
public InputStreamReader(InputStream in)
public InputStreamReader(InputStream in,String charsetName)
OutputStreamWriter写数据方法
//写一个字符
public void write(int c)
//写一个字符数组
public void write(char[] cbuf)
//写一个字符数组的一部分
public void write(char[] cbuf,int off,int len)
//写一个字符串
public void write(String str)
//写一个字符串的一部分
public void write(String str,int off,int len)
OutputStreamWriter读数据方法
//读一个字符
public int read()
//第一个字符数组
public int read(char[] cbuf)
字符流操作要注意的问题
flush()和close()的区别 ?
close:关闭流对象,但是先刷新一次缓冲区,关闭之后,流对象就不能继续使用了
flush:仅仅刷新缓冲区,刷新之后,流对象还可以继续使用
(2) 字符流的简单写法
转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对应的子类
//输出流
FileWriter
//输入流
FileReader
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"))
//等价
FileWriter fw = new FileWriter("b.txt"); (写出)
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"))
//等价
FileReader fr = new FileReader("a.txt"); (读取)
(3) 字符缓冲流
BufferedWriter:字符缓冲输出流
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
BufferedReader:字符缓冲输入流
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
特殊功能
BufferedWriter:
//根据系统来决定换行符
public void newLine()
BufferedReader:
//一次读取一行数据,包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
public String readLine()
(四) IO流案例
字节流案例
案例一:复制单级文件夹
import java.io.*;
/*
* 需求:复制单级文件夹
*
* 数据源:f:\\demo
* 目的地:f:\\test
*
* 分析:
* A:封装目录
* B:获取该目录下的所有文本的File数组
* C:遍历该File数组,得到每一个File对象
* D:把该File进行复制
*/
public class CopyFolderDemo {
public static void main(String[] args) throws IOException {
File srcFloder = new File("F:\\demo");
File deskFloder = new File("F:\\test");
if (!deskFloder.exists()) {
deskFloder.mkdirs();
}
File[] fileArray = srcFloder.listFiles();
for (File file : fileArray) {
String name = file.getName();
//拼凑出每一个文件的路径
File newFile = new File(deskFloder, name);
copyFloder(file, newFile);
}
}
public static void copyFloder(File file, File newFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream(newFile));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read()) != -1) {
bos.write(bys, 0, len);
}
bis.close();
bos.close();
}
}
案例二:复制指定目录下的指定文件,并修改后缀名
import java.io.*;
/*
* 需求:复制指定目录下的指定文件,并修改后缀名。
* 指定的文件是:.txt文件。
* 指定的后缀名是:.bat
* 指定的目录是:test
*
* 数据源:f:\\demo\\A.txt
* 目的地:f:\test\\A.bat
*
* 分析:
* A:封装目录
* B:获取该目录下的java文件的File数组
* C:遍历该File数组,得到每一个File对象
* D:把该File进行复制
* E:在目的地目录下改名
*/
public class CopyFolderDemo2 {
public static void main(String[] args) throws IOException {
File srcFloder = new File("F:\\demo");
File destFloder = new File("F:\\test");
if (!destFloder.exists()) {
destFloder.mkdirs();
}
File[] fileArray = srcFloder.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isFile() && name.endsWith(".txt");
}
});
for (File file : fileArray) {
String name = file.getName();
File newFile = new File(destFloder, name);
copyFile(file, newFile);
}
File[] deskFileArray = destFloder.listFiles();
for (File destFile : deskFileArray) {
String name = destFile.getName();
String newName = name.replace(".txt", ".bat");
File newFile = new File(destFloder, newName);
destFile.renameTo(newFile);
}
}
public static void copyFile(File file, File newFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream(newFile));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bis.close();
bos.close();
}
}
案例三:复制多级文件夹
import java.io.*;
/*
* 需求:复制多极文件夹
*
* 数据源:F:\\admin
* 目的地:E:\\
*
* 分析:
* A:封装数据源File
* B:封装目的地File
* C:判断该File是文件夹还是文件
* a:是文件夹
* 就在目的地目录下创建该文件夹
* 获取该File对象下的所有文件或者文件夹File对象
* 遍历得到每一个File对象
* 回到C
* b:是文件
* 就复制(字节流)
*/
public class CopyFloderDemo3 {
public static void main(String[] args) throws IOException {
File srcFile = new File("F:\\admin");
File destFile = new File("E:\\");
copyFolder(srcFile, destFile);
}
private static void copyFolder(File srcFile, File destFile) throws IOException {
if (srcFile.isDirectory()) {
File newFolder = new File(destFile, srcFile.getName());
newFolder.mkdirs();
//获取该File对象下的所有文件或者文件夹File对象
File[] fileArray = srcFile.listFiles();
for (File file : fileArray) {
//递归,继续判断
copyFolder(file, newFolder);
}
} else {
File newFile = new File(destFile, srcFile.getName());
copyFile(srcFile, newFile);
}
}
private static void copyFile(File srcFile, File newFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream(newFile));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
}
}
字符流案例
案例一:随机获取文本文件中的姓名案例
import java.io.*;
import java.util.ArrayList;
import java.util.Random;
/*
* 随机获取文本文件中的姓名案例
* 需求:我有一个文本文件中存储了几个名称
* 请大家写一个程序实现随机获取一个人的名字。
*
* 分析:
* A:把文本文件中的数据存储到集合中
* B:随机产生一个索引
* C:根据该索引获取一个值
*/
public class GetRandName {
public static void main(String[] args) throws IOException {
String path = "F:\\test.txt";
// BufferedReader br = new BufferedReader(new FileReader(path));
//默认记事本以ansi编码保存,但是使用FileReader默认使用UTF-8输出,所以使用上面语句会乱码
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path), "gb2312"));
ArrayList<String> array = new ArrayList<>();
String line = null;
while ((line = br.readLine()) != null) {
array.add(line);
}
br.close();
Random r = new Random();
int index = r.nextInt(array.size());
String name = array.get(index);
System.out.println("该幸运儿是:" + name);
}
}
案例二:键盘录入学生信息按照总分排序并写入文本文件案例
//Student类自行补充
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
public class StudentDemo {
public static void main(String[] args) throws IOException {
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s2.getSum() - s1.getSum();
int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;
int num4 = num3 == 0 ? s1.getEnglish() - s2.getEnglish() : num3;
int num5 = num4 == 0 ? s1.getName().compareTo(s2.getName()) : num4;
return num5;
}
});
for (int x = 1; x <= 3; x++) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入第" + x + "个学生成绩信息");
System.out.println("姓名:");
String name = sc.nextLine();
System.out.println("语文成绩:");
int chinese = sc.nextInt();
System.out.println("数学成绩:");
int math = sc.nextInt();
System.out.println("英语成绩:");
int english = sc.nextInt();
Student s = new Student();
s.setName(name);
s.setChinese(chinese);
s.setMath(math);
s.setEnglish(english);
ts.add(s);
BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\students.txt"));
bw.write("学生成绩信息如下");
bw.newLine();
bw.flush();
bw.write("姓名-语文成绩-数学成绩-英语成绩");
bw.newLine();
bw.flush();
for (Student stu : ts) {
StringBuilder sb = new StringBuilder();
sb.append(stu.getName() + "-" + stu.getChinese() + "-" + stu.getMath() + "-" + stu.getEnglish());
bw.write(sb.toString());
bw.newLine();
bw.flush();
}
bw.close();
System.out.println("学生成绩信息录入完毕");
}
}
}
案例三:登陆注册案例(使用IO)
在前几篇中集合实现的基础上,其余文件不变,只需要对 UserDaoImpl.java 文件进行重写
由于篇幅较长,其余dao、pojo、test层代码请翻阅前几篇中 集合框架——List篇
package cn.bwh_05_LoginDemo.dao.impl;
import cn.bwh_05_LoginDemo.dao.UserDao;
import cn.bwh_05_LoginDemo.pojo.User;
import java.io.*;
/**
* 这是用户操作的具体实现类 (IO)
*
* @author BWH_Steven
* @version v1.1
*/
public class UserDaoImpl implements UserDao {
private static File file = new File("User.txt");
static {
try {
file.createNewFile();
} catch (IOException e) {
System.out.println("创建文件失败");
e.printStackTrace();
}
}
@Override
public boolean isLogin(String username, String password) {
boolean flag = false;
BufferedReader br = null;
String path = "user.txt";
try {
br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null) {
//用户名--密码
String[] datas = line.split("--");
if (datas[0].equals(username) && datas[1].equals(password)) {
flag = true;
break;
}
}
} catch (FileNotFoundException e) {
System.out.println("找不到登录所需要的信息文件");
e.printStackTrace();
} catch (IOException e) {
System.out.println("用户登录失败");
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
System.out.println("用户登录释放资源失败");
e.printStackTrace();
}
}
}
return flag;
}
@Override
public void regist(User user) {
/*
* 为注册的数据定义一个规则: 用户名--密码
*/
BufferedWriter bw = null;
String path = "user.txt";
try {
//为了保证数据是追加写入,所以必须加true
bw = new BufferedWriter(new FileWriter(file, true));
//bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path,true),"gb2312"));
bw.write(user.getUsername() + "--" + user.getPassword());
bw.newLine();
bw.flush();
} catch (IOException e) {
System.out.println("用户注册失败");
e.printStackTrace();
} finally {
try {
bw.close();
} catch (IOException e) {
System.out.println("用户注册释放资源失败");
e.printStackTrace();
}
}
}
}
结尾:
如果内容中有什么不足,或者错误的地方,欢迎大家给我留言提出意见, 蟹蟹大家 !_
如果能帮到你的话,那就来关注我吧!(系列文章均会在公众号第一时间更新)
在这里的我们素不相识,却都在为了自己的梦而努力 ❤
一个坚持推送原创Java技术的公众号:理想二旬不止
快速Get-JAVA-IO流的更多相关文章
- Java:IO流与文件基础
Java:IO流与文件基础 说明: 本章内容将会持续更新,大家可以关注一下并给我提供建议,谢谢啦. 走进流 什么是流 流:从源到目的地的字节的有序序列. 在Java中,可以从其中读取一个字节序列的对象 ...
- java IO流详解
流的概念和作用 学习Java IO,不得不提到的就是JavaIO流. 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...
- Java IO流学习总结
Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...
- 揭开Java IO流中的flush()的神秘面纱
大家在使用Java IO流中OutputStream.PrintWriter --时,会经常用到它的flush()方法. 与在网络硬件中缓存一样,流还可以在软件中得到缓存,即直接在Java代码中缓存. ...
- java io流 对文件夹的操作
java io流 对文件夹的操作 检查文件夹是否存在 显示文件夹下面的文件 ....更多方法参考 http://www.cnblogs.com/phpyangbo/p/5965781.html ,与文 ...
- Java IO流题库
一. 填空题 Java IO流可以分为 节点流 和处理流两大类,其中前者处于IO操作的第一线,所有操作必须通过他们进行. 输入流的唯一目的是提供通往数据的通道,程序可以通过这个通道读取数 ...
- Java IO流总结
Java IO流分类以及主要使用方式如下: IO流 |--字节流 |--字节输入流 InputStream: int read();//一次读取一个字节 int read(byte[] bys);// ...
- java io流 运行错误时,保存异常到文件里面
java io流 运行错误时,保存异常到文件里面 下面这个实例,运行后,输入数字,为正确,如果输入字符串,则报错,保存错误信息 //运行错误时,保存异常到文件里面 //下面这个实例,运行后,输入数字, ...
- java io流 创建文件、写入数据、设置输出位置
java io流 创建文件 写入数据 改变system.out.print的输出位置 //创建文件 //写入数据 //改变system.out.print的输出位置 import java.io.*; ...
- java io流 数据流传输
java io流 数据流传输 把这段当公式用就可以了 //数据流传输 import java.io.*; public class Index{ public static void main(Str ...
随机推荐
- ArrayBuffer、TypedArray、DataView二进制数组
三个是处理二进制数据的接口.都是类数组. 1.ArrayBuffer是什么? ArrayBuffer是一个二进制对象(文件,图片等).它指向固定长度的,连续的内存区域. const buffer = ...
- Linux配置Tomcat8080端口 远程无法访问解决办法
是因为Linux的防火墙没有开放8080端口 解决办法: /sbin/iptables -I INPUT -p tcp --dport 8080 -j ACCEPT #开启8080端口 /sbin/ ...
- c语言 指针数组
指针数组指针数组是数组,指针数组每个元素是一个指针指针数组的定义:type* parray[n]; type* 是数组中每个元素的类型parray 为数组名n为大小 例子:float* a[3] // ...
- Ubuntu 14.04 tar 打包系统安装到新机器
制作Ubuntu14.04 的u启动盘,重启电脑进入要克隆的系统,打包整个根目录 su cd / tar -cvpzf /media/cdrom/backup.tar.gz / --exclude=/ ...
- intel官方的手册
最近在学习汇编语言,需要用到intel的手册,无论是csdn还是其他的,都要下载币,还不便宜,也很老的资料了. 直接到这个地址:https://software.intel.com/en-us/art ...
- PyTricks-How to Sort a Python dict
字典的键值排序 import operator # 1表示按照值排序 xs = {"a": 4, "b": 3, "c": 2, " ...
- pwn学习日记Day7 基础知识积累
知识杂项 strncpy(char s1,const char s2,int n); 其中有三个参数分别表示目标字符串s1,源字符串s2,拷贝长度.意思是将s2指向的字符串的前n个长度的字符放到s1指 ...
- Linux设备驱动程序 之 中断和锁
中断和锁 1. 硬中断和软中断(包括tasklet和timer)共享数据,硬中断中使用spin_lock/spin_unlock,软中断中使用spin_lock_irq/spin_unlock_irq ...
- java 设计模式 之 装饰器模式
装饰器模式的作用 在不修改原先对象核心的功能的情况下,对功能进行增强. 增强对象的功能的途径 通过类继承的方式,对父对象进行增强操作,例如造车是父类,改装跑车,跑车加大灯,改装房车,房车加私人电影院. ...
- 获得数据源和路径desc.catalogPath
workspace:C:\Users\dell\Documents\ArcGIS\Default.gdb\ddf inPath:c:\users\dell\documents\arcgis\defau ...