IO流总结

IO这章的知识在上面一篇博客也说过一点,主要要体会一下装饰者设计模式和适配器设计模式,这样更利于我们理解复杂的IO体系结构。今天就让我们看一看。不过在讲IO
之前,我们先把文件(File)的知识简单过一下。

一、文件File

文件大家都不陌生,查看JDK帮助文档,我们知道File的定义——文件和目录(文件夹)路径名的抽象表示形式。

1、构造方法

File(String pathname):根据一个路径得到File对象
File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象

2、创建功能

public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来
举例:
         //需求1:我要在e盘目录下创建一个文件demo
File file = new File("e:\\a.txt");
大家可能会认为这里用了关键字new,那么文件File就会出来了,其实不是,因为File的定义是:文件和目录(文件夹)路径名的抽象表示形式。它仅仅是文件的表示
形式,不是真实的文件。 所以需要调用这样一句代码file.createNewFile()

//需求2:我要在e盘目录test下创建一个文件b.txt

File file = new File("e:\\test\\b.txt");
System.out.println("createNewFile:" + file3.createNewFile());
运行之后可以看到控制台打印出:
Exception in thread "main" java.io.IOException: 系统找不到指定的路径。

所以注意:要想在某个目录下创建内容,该目录首先必须存在。我们可以这么做:File file1=new File("e:\\test);file1.mkdir();//先把文件夹(目录)创建出来然后在:

File file2=new   File(e:\\test\\b.txt);file2.createNewFile();//在创建文件

//看下面这行代码
        File file = new File("e:\\liuyi\\a.txt");
System.out.println("mkdirs:" + file8.mkdirs());
你会看到a.txt是个目录,不要认为指定了.txt后缀就是文件了,要看它调用的是creatNewFile()还是mkdir();

3、删除功能

public boolean delete()
这个方法比较简单,注意:
A:如果你创建文件或者文件夹忘了写盘符路径,那么,默认在项目路径下。
B:Java中的删除不走回收站。
C:要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹,所以delete一次只能删除一个文件,如果想删除一个文件夹,那必须要循环遍历了。

4、重命名功能

public boolean renameTo(File dest)
如果路径名相同,就是改名。
        如果路径名不同,就是改名并剪切。

需求:将G盘所有视频文件该名成“0?-网络编程(概述).avi”,原来视频文件名称为:黑马程序员_毕向东_Java基础视频教程第23天-0?-网络编程(概述).avi

<span style="font-size:18px;">public class FileDemo {
private static File dest;
public static void main(String[] args) {
//封装目录
File  file=new File("G:\\黑马入学\\网络编程1");
File[] sorcFolder = file.listFiles();
for (File f : sorcFolder) {
String name = f.getName();
//黑马程序员_毕向东_Java基础视频教程第23天-01-网络编程(概述).avi
//System.out.println(name);
int index = name.indexOf('-');
String string = name.substring(index+1);
//再次封装新的文件目录
dest = new File(file,string);
f.renameTo(dest);
}
}
}</span>

执行结果:

一看全部改名成功,哈哈。。。

5、判断功能

public boolean isDirectory():判断是否是目录
  public boolean isFile():判断是否是文件
  public boolean exists():判断是否存在
  public boolean canRead():判断是否可读
  public boolean canWrite():判断是否可写
  public boolean isHidden():判断是否隐藏

6、简单获取功能

public String getAbsolutePath():获取绝对路径
 public String getPath():获取相对路径
 public String getName():获取名称
 public long length():获取长度。字节数
 public long lastModified():获取最后一次的修改时间,毫秒值

示例代码:

<span style="font-size:18px;"> public class FileDemo {
public static void main(String[] args) {
// 创建文件对象
File file = new File("demo\\test.txt");
System.out.println("getAbsolutePath:" + file.getAbsolutePath());
System.out.println("getPath:" + file.getPath());
System.out.println("getName:" + file.getName());
System.out.println("length:" + file.length());
System.out.println("lastModified:" + file.lastModified());
// 1432518063391
Date d = new Date(1432518063391L);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s = sdf.format(d);
System.out.println(s);
}
}</span>

执行结果是:

7、高级获取功能

public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组
后者功能更为强大一点,因为返回的是File对象,所以可以得到File的各种属性。

8.文件名称过滤器——FilenameFilter

需求:判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出此文件名称
public String[] list(FilenameFilter filter)
public File[] listFiles(FilenameFilter filter)

示例代码:

<span style="font-size:18px;">public class FileDemo {
public static void main(String[] args) {
//封装e盘
File file=new File("e:\\");
// 获取该目录下所有文件或者文件夹的String数组
String[] list = file.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
//如果是文件并且是以.jpg结尾的,返回true,一旦返回true,name就会被放进String数组中,
return new File(dir, name).isFile() && name.endsWith(".jpg");
}
});
for (String string : list) {
System.out.println(string);
}
}
}</span>

虽然普通的方式也能实现,这样看起来,代码更加优雅,现在我们来看看list(FilenameFilter filter)的源码

<span style="font-size:18px;">public String[] list(FilenameFilter filter) {
String names[] = list();
if ((names == null) || (filter == null)) {
return names;
}
List<String> v = new ArrayList<>();
for (int i = 0 ; i < names.length ; i++) {
if (filter.accept(this, names[i])) {
v.add(names[i]);
}
}
return v.toArray(new String[v.size()]);
}</span>

二、IO相关操作

IO因为体系过于庞大,这里并不面面俱到,捡其重点来说。上面简单说了一下File的使用,File的读取,写入,复制。相信都是我们经常使用的功能。谈起IO流,首先我们要对它有个大致的认识,也就是IO的分类,请看下面:
A:按流向分
输入流 读取数据
输出流 写出数据
B:按数据类型
字节流
字节输入流
字节输出流
字符流
字符输入流
字符输出流

如果你不知道什么是字节流,什么是字符流,我告诉你,如果电脑记事本可以打开的并且可以看得懂的,那就是可以用字符流操作的文件,当然也可以用字节流来操作,如果电脑记事本能打开,但是我们看不懂的,那就是用字节流来操作的文件,比如MP3文件、JPG文件等,现在我们来看看IO是怎么来操作File的。

1、字节流操作文件

1.1、FileOutputStream写出数据

A:操作步骤
a:创建字节输出流对象
b:调用write()方法
c:释放资源

B:示例代码:
FileOutputStream fos = new FileOutputStream("fos.txt");
fos.write("hello".getBytes());
fos.close();

1.2、FileInputStream读取数据

FileInputStream读取数据
A:操作步骤
a:创建字节输入流对象
b:调用read()方法
c:释放资源

B:代码体现:
FileInputStream fis = new FileInputStream("fos.txt");
//方式1,我们一次读取一个字节
int by = 0;
while((by=fis.read())!=-1) {
System.out.print((char)by);
}
//方式2  我们一次读取一个字节数组
byte[] bys = new byte[1024];
int len = 0;
while((len=fis.read(bys))!=-1) {
System.out.print(new String(bys,0,len));
}
fis.close();

1.3、四种方式复制文件效率比较

FileInputStream、FileOutputStream这两个类我们称之为基本字节流,相对于基本字节流,IO中还有高效字节流BufferedInputStream、BufferedOutputStream 
看完了这个,那么问题来,哪种方式好呢?
下面我们来看一个例子:
需求:把G:\IO流(IO流小结图解).avi复制到当前项目目录下的copy.avi中
 字节流四种方式复制文件:
 * 基本字节流一次读写一个字节
 * 基本字节流一次读写一个字节数组
 * 高效字节流一次读写一个字节
 * 高效字节流一次读写一个字节数组
G:\IO流(IO流小结图解).av的信息如下:


示例代码:

<span style="font-size:18px;">public class CopyAVI {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
method1("G:\\IO流(IO流小结图解).avi", "copy1.avi");
//method2("G:\\IO流(IO流小结图解).avi", "copy2.avi");
//method3("G:\\IO流(IO流小结图解).avi", "copy3.avi");
//method4("G:\\IO流(IO流小结图解).avi", "copy4.avi");
long end = System.currentTimeMillis();
System.out.println("共耗时:" + (end - start) + "毫秒");
}
// 高效字节流一次读写一个字节数组:
public static void method4(String srcString, String destString)throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destString));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
}
// 高效字节流一次读写一个字节:
public static void method3(String srcString, String destString)throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destString));
int by = 0;
while ((by = bis.read()) != -1) {
bos.write(by);
}
bos.close();
bis.close();
}
// 基本字节流一次读写一个字节数组
public static void method2(String srcString, String destString)throws IOException {
FileInputStream fis = new FileInputStream(srcString);
FileOutputStream fos = new FileOutputStream(destString);
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
fos.close();
fis.close();
}
// 基本字节流一次读写一个字节
public static void method1(String srcString, String destString)throws IOException {
FileInputStream fis = new FileInputStream(srcString);
FileOutputStream fos = new FileOutputStream(destString);
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}
fos.close();
fis.close();
}
}</span>

执行结果:

方法一执行:

方法二执行:

方法三执行:

方法四执行:

四种方式的性能差异,通过这个执行结果,想必大家也知道了 ,所以在实际开发中选择哪一个来操作文件,相信大家已经有了选择了,反正我是喜欢用方法四!!

2、字符流操作文件

大家可能会问,操作文件已经有了字节流,为什么还要说字符流呢,哎,谁叫咱们是中国人呢,汉字比较复杂,一个汉字站了两个字节,所以直接用字符流操作不够方便所以就有了字符流。我们来看看字符流的体系结构。

2.1字符流体系结构

|--字符流
|--字符输入流
Reader
int read():一次读取一个字符
int read(char[] chs):一次读取一个字符数组

|--InputStreamReader
|--FileReader
|--BufferedReader
String readLine():一次读取一个字符串
|--字符输出流
Writer
void write(int ch):一次写一个字符
void write(char[] chs,int index,int len):一次写一个字符数组的一部分

|--OutputStreamWriter
|--FileWriter
|--BufferedWriter
void newLine():写一个换行符
void write(String line):一次写一个字符串

字符流的读写是由基类Reader和Writer来完成的,它们各有两个子类来帮助我们来操作文件。Reader类的子类BufferedReader与Writer的子类BufferedWriter,我们一定可以猜到这是高效字符流操作文件使用的!那么,Reader类的子类InputStreamReader与Writer的子类OutputStreamWriter是干什么的呢?从类的名称来来看,前面是字节的,后面是字符的,我告诉你,这两个类就是转换流,把字节流转换成字符流,那么这有什么用呢?-----键盘录入!!!一会你们就知道了。。。。。注意OutputStreamWriter还有子类FileWriter,InputStreamReader还有子类FileReader。

2.1、字符流操作文件

我们先看一个字符流操作文件的例子。
需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中

数据源:
a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader -- BufferedReader
 目的地:
b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter -- FileWriter -- BufferedWriter

示例代码:

<span style="font-size:18px;">public class CopyFileDemo {
public static void main(String[] args) throws IOException {
// 封装数据源
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 封装目的地
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
// 两种方式其中的一种一次读写一个字符数组,当然此处你也可以一次读取一个字节的方法
// char[] chs = new char[1024];
// int len = 0;
// while ((len = br.read(chs)) != -1) {
//  bw.write(chs, 0, len);
//  bw.flush();
// }
// 还有一种方式读写数据,这就是BufferedWriter、BufferedReader的强大之处。。。。
String line = null;
//下面三句话,我习惯连着写,写入、换行、刷新,动作相当连贯有木有啊!!!!!!
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
// 释放资源
bw.close();
br.close();
}
}</span>

代码解读: bw.newLine();这句话的意思是换行,调用的效果和我们写“\r\n”是一样的,但是newLine可以夸平台的,这就是区别!
           readLine()这个方法有点厉害,因为它一次读一行!!!
博客写到这里,我们发现,复制文件文件起码有5种方式,前面所讲的1.基本字节流一次读写一个字节、2.基本字节流一次读写一个字节数组、3.高效字节流一次读写一个字节、4.高效字节流一次读写一个字节数组共4种,再加上上面的一种,共5种,而且第五种是最好的,个人感觉。。。。

3、IO编程实战

3.1、复制单级文件夹

/*
 * 需求:复制指定目录下的指定文件,并修改后缀名。
 * 指定的文件是:.java文件。
 * 指定的后缀名是:.txt
 * 指定的目录是:txt
 * 数据源:G:\designModel
 * 目的地:G:\txt
 * 
 * 分析:
 * A:封装目录
 * B:获取该目录下的java文件的File数组
 * C:遍历该File数组,得到每一个File对象
 * D:把该File进行复制
 * E:在目的地目录下改名
 */

* 数据源:G:\designModel如下图所示:

示例代码:

<span style="font-size:18px;">public class CopyFolder {
public static void main(String[] args) throws IOException {
//A:封装目录
File srcFolder=new File("G:\\designModel");
//封装目的地
File destFolder=new File("G:\\myNote");
//如果目的地文件不存在,就创建一个
if(!destFolder.exists()){
destFolder.mkdir();
}
//B:获取该目录下的java文件的File数组
File[] srcFiles = srcFolder.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
// 文件过滤器,得到.java文件,去除其他类型的文件
return new File(dir,name).isFile()&&name.endsWith(".java");
}
});
// C:遍历该File数组,得到每一个File对象
for (File file : srcFiles) {
String name = file.getName();
File newFile=new File(destFolder,name);
copyFile(file,newFile);
}
//E:在目的地目录下改名
for (File file :destFolder.listFiles()) {
String name = file.getName();
String newName = name.replace(".java", ".txt");
File newFile=new File(destFolder,newName);
file.renameTo(newFile);
}
}
//  D:把该File进行复制
private 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();
}
}</span>

执行结果:

3.2、复制多级文件夹

思路分析
  数据源:G:\\
  目的地:G:\\

A:封装数据源File
    B:封装目的地File
    C:判断该File是文件夹还是文件
  a:是文件夹
                 就在目的地目录下创建该文件夹
         获取该File对象下的所有文件或者文件夹File对象
         遍历得到每一个File对象
           回到C
           b:是文件
          复制(字节流)

示例代码:

<span style="font-size:18px;">public class CopyFolders{
public static void main(String[] args) throws IOException {
// 封装数据源File
File srcFile = new File("G:\\");
// 封装目的地File
File destFile = new File("E:\\");
// 复制文件夹的功能
copyFolder(srcFile, destFile);
}
private static void copyFolder(File srcFile, File destFile)throws IOException {
// 判断该File是文件夹还是文件
if (srcFile.isDirectory()) {
// 文件夹
File newFolder = new File(destFile, srcFile.getName());
newFolder.mkdir();
// 获取该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();
}
}</span>

3.3 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件

思路分析:
A:创建学生类
B:创建集合对象
    因为要排序,所以用TreeSet<Student>
C:键盘录入学生信息存储到集合
D:遍历集合,把数据写到文本文件

<span style="font-size:18px;">public class Student {
// 姓名
private String name;
// 语文成绩
private int chinese;
// 数学成绩
private int math;
// 英语成绩
private int english;
//构造方法和setter/getter方法省去了。。。。。。。。
}</span>
<span style="font-size:18px;">public class StudentIO {
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.getName().compareTo(s2.getName()): num3;
return num4;
}
});
// 键盘录入学生信息存储到集合
for (int x = 1; x <= 5; 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("students.txt"));
//以下三行代码连写
bw.write("学生信息如下:");
bw.newLine();
bw.flush();
bw.write("姓名\t语文成绩\t数学成绩\t英语成绩");
bw.newLine();
bw.flush();
for (Student s : ts) {
StringBuilder sb = new StringBuilder();
sb.append(s.getName()).append("\t").append(s.getChinese())
.append("\t").append(s.getMath()).append("\t")
.append(s.getEnglish());
bw.write(sb.toString());
bw.newLine();
bw.flush();
}
// 释放资源
bw.close();
System.out.println("学习信息存储完毕");
}
}</span>

输入:


执行结果:

好啦,如果上面的例子可以弄懂,IO就基本没有什么问题啦,哈哈。。。

IO流总结(基础知识)相关推荐

  1. WinCE流驱动基础知识小结

    WinCE流驱动基础知识小结 1.基础知识: 1)系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口.设备驱动程序为应用程序屏蔽了硬件细节,在应用程序看来硬件只 ...

  2. java程序运行必须得三个io类_Java基础知识(三)

    一.hashCode 与 equals (重要) 面试官可能会问你:"你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?" 1 ...

  3. java io 对象_JAVA基础知识之IO——对象序列化

    对象序列化 Java对象序列化(Serialize)是指将Java对象写入IO流,反序列化(Deserilize)则是从IO流中恢复该Java对象. 对象序列化将程序运行时内存中的对象以字节码的方式保 ...

  4. java中IO流的相关知识

    目录 一.背景 二.IO流的分类 三.字符流操作相关代码示例 1.FileReader读取文件内容 2.FileWriter向文件写数据 3.实现文件内容复制 4.注意事项 5.利用try-catch ...

  5. java byte char io流_Java基础进阶 IO流之字节流

    1.IO流 1.1.概述 之前学习的File类它只能操作文件或文件夹,并不能去操作文件中的数据.真正保存数据的是文件,数据是在文件中.而File类它只是去对文件本身做操作,不能对文件中的数据进行操作. ...

  6. java boolean io流_java基础入门-day22-IO流

    (1)I/O:Input/Output(了解) java中对数据的输入输出问题是通过io技术解决的. java提供的对象都在java.io包下. (2)IO的分类(掌握) A:按照数据的流向 输入流 ...

  7. feed流和瀑布流_基础知识讲解:什么是feed流?(图文)

    feed是将用户主动订阅的若干消息源组合在一起形成内容聚合器,帮助用户持续地获取最新的订阅源内容.feed流即持续更新并呈现给用户内容的信息流. 最近常听朋友说中了抖音的毒,一有时间就刷抖音,根本停不 ...

  8. feed流和瀑布流_基础知识讲解:什么是feed流?

    feed是将用户主动订阅的若干消息源组合在一起形成内容聚合器,帮助用户持续地获取最新的订阅源内容.feed流即持续更新并呈现给用户内容的信息流. 最近常听朋友说中了抖音的毒,一有时间就刷抖音,根本停不 ...

  9. java.io.file()_JAVA基础知识之IO-File类

    File类介绍 File是java.io包下面的一个类,代表与平台无关的文件或者目录.JAVA中,无论文件还是目录,都可以看作File类的一个对象.File类能对文件或目录新建,删除,获取属性等操作, ...

  10. linux命令基础知识 管道流,linux基础知识-I/O重定向,管道(示例代码)

    系统设定 默认输出设备:标准输出,STDOUT, 1 默认输入设备:标准输入, STDIN, 0 标准错误输出:STDERR, 2 标准输入:键盘 标准输出和错误输出:显示器 I/O重定向: Linu ...

最新文章

  1. mysql 存储过程插入慢_mysql存储过程太慢怎么办
  2. 结合PE格式对linker分析1
  3. 后序遍历的非递归算法python_Python非递归实现二叉树的后续遍历
  4. 再测Golang JSON类库
  5. 闪修侠、极客修、千机网,手机维修选哪家?
  6. Golang (Go语言) Mac OS X下环境搭建 环境变量配置 开发工具配置 Sublime Text 2 【转】...
  7. iOS 使用ZipArchive压缩文件
  8. 鸿蒙系统是华容网格吗,鸿蒙上手机还在迟疑,国内对手却已悄然来到
  9. 读书感受 之 《反脆弱 · 做一个内心强大的人》
  10. 查看Win10是否永久激活
  11. dsp和通用计算机的区别,DSP处理器与通用处理器的比较
  12. 网易云音乐虚化图片html,CSS之高斯模糊—(网易云歌单)
  13. java 银联支付_java服务器端移动银联支付的流程
  14. matlab小数分数互换
  15. 友盟社会化分享+第三方登录 2022.03.28 最新版
  16. 了解寄存器: EBP寄存器
  17. 对接钉钉审批_钉钉审批对接是什么-和钉钉审批对接相关的问题-阿里云开发者社区...
  18. ubuntu20.04显卡1080ti安装cuda和cudnn
  19. ASP社群直播/聊天室/分销/系统源码
  20. excel字符串拆分为行

热门文章

  1. java 直角坐标系_直角坐标系(Java)
  2. mac 安装qemu的方法
  3. 在creo中,如何在轴上画一个键槽?
  4. taobao.itemprops.get( 获取标准商品类目属性 )
  5. 项目管理高手常用的10种图表!
  6. 纪念谢尔盖·科尔塔科夫
  7. 锐安信sslTrus 5年期证书订阅套餐 简化SSL证书管理
  8. macbook python文件路径_mac下python目录
  9. 盘点“PayPal黑帮”成员的传奇创业故事
  10. Android Studio Arctic Fox | 2020.3.1、Gradle 7.0升级记录