Java学习笔记-IO
IO(Input Output)流,用来处理设备之间的数据传输
IO
IO概述
Java对数据的操作是通过流的方式
Java用于操作流的对象都在IO包中
流按操作数据分为两种:字节流与字符流
流按流向分为:输入流,输出流
最开始只有字节流,这符合计算机底层的存储原理,后来为了文本的操作方便开始引入字符流
IO流常用基类
字节流的抽象基类:
- InputStream
- OutputStream
字符流的抽象基类:
- Reader
- Writer
注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。如:InputStream的子类FileInputStream,Reader的子类FileReader,后缀名是父类名。 前缀名是该流对象的功能
IO程序的书写
- 导入IO包中的类
- 进行IO异常处理
- 在finally中对流进行关闭
字符流
字符流——创建文件(FileWriter)
FileWriter构造方法 |
---|
FileWriter(File file) 根据给定的 File 对象构造一个 FileWriter 对象 |
FileWriter**(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象 |
FileWriter(FileDescriptor fd) 构造与某个文件描述符相关联的 FileWriter 对象 |
FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象 |
FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象 |
- 创建流对象,建立数据存放文件
FileWriter fw = new FileWriter("Test.txt");
- 调用流对象的写入方法,将数据写入流
fw.write("text");
- 关闭流资源,并将流中的数据清空到文件中
fw.close();
FileWriter fw = null;
try{
fw = new FileWriter("Test.txt");
fw.write("text");
} catch (IOException e){
System.out.println(e.toString());
} finally{
If(fw != null)
try{
fw.close();
} catch (IOException e){
System.out.println(e.toString());
}
}
当需要在已有文件追加内容时,使用FileWriter(filename, true)来写入文件
注:
- 创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件,而且该文件会被创建到指定目录下
- 如果该目录下已有同名文件,将被覆盖
- 关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据,将数据刷到目的地中
- close和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭
字符流——读取文件(FileReader)
FileReader构造方法 |
---|
FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader |
FileReader(FileDescriptor fd) 在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader |
FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader |
read()
方法用于读取一个字符,每次读完会自动后移一位,当文件读取完成,返回-1read(buf)
方法用于将数组读入数组,返回读到的字符长度,如果一次没读取完,下一次再调用继续读取后面的字符,当返回-1代表文件读取完毕建立一个流对象,将已存在的一个文件加载进流
FileReader fr = new FileReader(“Test.txt”);
创建一个临时存放数据的数组
char[] ch = new char[1024];
调用流对象的读取方法将流中的数据读入到数组中
fr.read(ch);
FileReader fr = null;
try{
fr = new FileReader("c:\\test.txt");
char[] buf = new char[1024];
int len= 0;
while((len = fr.read(buf)) != -1){
System.out.print(new String(buf,0,len));
}
} catch (IOException e){
System.out.println("read-Exception :" + e.toString());
} finally{
if(fr != null){
try{
fr.close();
} catch (IOException e){
System.out.println("close-Exception :" + e.toString());
}
}
}
文件复制的实现
import java.io.*;
class Text {
public static void main(String[] args) throws IOException {
MyCopy();
}
public static void MyCopy() {
FileWriter fw = null;
FileReader fr = null;
try {
fw = new FileWriter("Demo_copy.txt");
fr = new FileReader("Demo.java");
char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1) {
fw.write(buf,0,len);
}
} catch (IOException e) {
throw new RuntimeException("读写失败");
} finally {
if(fr != null)
try {
fr.close();
} catch (IOException e) {
}
if(fw != null)
try {
fw.close();
} catch (IOException e) {
}
}
}
}
注意事项
- 定义文件路径时,可以用"
/
“或者”\\
" - 在创建一个文件时,如果目录下有同名文件将被覆盖
- 在读取文件时,必须保证该文件已存在,否则出异常
字符流的缓冲区
- 缓冲区的出现提高了对数据的读写效率
- 缓冲区要结合流才可以使用
- 在流的基础上对流的功能进行了增强
- 关闭缓冲区,就是在关闭缓冲区中的流对象
具备缓冲区的字符流
- BufferedWriter
用到缓冲区,就要使用flush()
刷新
该缓冲区中提供了一个跨平台的换行符:newLine();
- BufferedReader
该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取,当返回null时,表示读到文件末尾
readLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符 - LineNumberReader
继承自BufferedReader,可以实现行号的输出getLineNumber()
,还可以设置行号setLineNumber()
使用缓冲区复制文件
import java.io.*;
class Text {
public static void main(String[] args) {
BufferedReader bufr = null;
BufferedWriter bufw = null;
try {
bufr = new BufferedReader(new FileReader("Demo.java"));
bufw = new BufferedWriter(new FileWriter("Demo_copy.txt"));
String line = null;
while((line = bufr.readLine()) != null) {
bufw.write(line);
bufw.newLine();
bufw.flush();
}
} catch (IOException e) {
throw new RuntimeException("读写失败");
} finally {
try {
if(bufr != null)
bufr.close();
} catch (IOException e) {
throw new RuntimeException("读取关闭失败");
}
try {
if(bufw != null)
bufw.close();
} catch (IOException e) {
throw new RuntimeException("写入关闭失败");
}
}
}
}
字节流
基本操作与字符流类相同
但它不仅可以操作字符,还可以操作其他媒体文件
而字符流不可以操作媒体文件
- InputStream
- OutputStream
字节流示例
e.g.(复制图片)
import java.io.*;
class Test {
public static void main(String[] args) {
FileOutputStream fos = null;
FileInputStream fis = null;
try {
fos = new FileOutputStream("c:\\2.bmp");
fis = new FileInputStream("c:\\1.bmp");
byte[] buf = new byte[1024];
int len = 0;
while((len = fis.read(buf)) != -1) {
fos.write(buf,0,len);
}
} catch (IOException e) {
throw new RuntimeException("复制文件失败");
} finally {
try {
if(fis != null)
fis.close();
} catch (IOException e) {
throw new RuntimeException("读取关闭失败");
}
try {
if(fos!=null)
fos.close();
} catch (IOException e) {
throw new RuntimeException("写入关闭失败");
}
}
}
}
字节流的缓冲区
同样是提高了字节流的读写效率
- BufferedInputStream:类似于BufferedReader
- BufferedOutputStream:类似于BufferedWrite
public static void copy()throws IOException {
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));
int by = 0;
while((by = bufis.read()) != -1) {
bufos.write(by);
}
bufos.close();
bufis.close();
}
转换流
转换流
- InputStreamReader:字节流通向字符流的桥梁
- OutputStreamWriter:字符流通向字节流的桥梁
转换流的由来 - 字符流与字节流之间的桥梁
- 方便了字符流与字节流之间的操作
转换流的应用
- 字节流中的数据都是字符时,转成字符流操作更高效
标准输入输出流
System类中的字段:in,out
它们各代表了系统标准的输入和输出设备
默认输入设备是键盘,输出设备是显示器
System.in的类型是InputStream
System.out的类型是PrintStream是OutputStream的子类FilterOutputStream的子类
标准输入输出流示例
例:获取键盘录入数据,然后将数据流向显示器,那么显示器就是目的地
- 通过System类的setIn,setOut方法对默认设备进行改变
System.setIn(new FileInputStream(“1.txt”));
//将源改成文件1.txt
System.setOut(new FileOutputStream(“2.txt”));
//将目的改成文件2.txt - 因为是字节流处理的是文本数据,可以转换成字符流,操作更方便
BfferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
转换流示例
import java.io.*;
class Test {
public static void main(String[] args) throws IOException {
//获取键盘录入对象。
//InputStream in = System.in;
//将字节流对象转成字符流对象,使用转换流。InputStreamReader
//InputStreamReader isr = new InputStreamReader(in);
//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
//BufferedReader bufr = new BufferedReader(isr);
//键盘的最常见写法。
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while((line = bufr.readLine()) != null) {
if("over".equals(line))
break;
bufw.write(line);
bufw.newLine();
bufw.flush();
}
bufr.close();
}
}
字符流与字节流的使用明确
明确源和目的
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer操作的数据是否是纯文本
是:字符流
不是:字节流
File类
- 用来将文件或者文件夹封装成对象
- 方便对文件与文件夹的属性信息进行操作
- File对象可以作为参数传递给流的构造函数
构造方法
File(File parent, String child)
根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例File(String pathname)
通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例File(String parent, String child)
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例File(URI uri)
通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例
常用方法
- 创建
boolean createNewFile(); //在指定位置创建文件,如果该文件已经存在,则不创建,返回false
boolean mkdir(); //创建文件夹
boolean mkdirs(); //创建多级文件夹
- 删除
boolean delete(); //删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit(); //在程序退出时删除指定文件。
- 判断
boolean exists(); //文件是否存在
isFile();
isDirectory();
isHidden();
isAbsolute();
- 获取信息
getName();
getPath();
getParent();
getAbsolutePath();
long lastModified();
long length();
FILE的递归操作
import java.io.*;
class Test {
public static void main(String[] args) {
File dir = new File("d:\\testdir");
removeDir(dir);
}
public static void removeDir(File dir) {
File[] files = dir.listFiles();
for(int x = 0; x < files.length; x++) {
if(files[x].isDirectory())
removeDir(files[x]);
else
System.out.println(files[x].toString() + ":-file-:" + files[x].delete());
}
System.out.println(dir + "::dir::" + dir.delete());
}
}
打印流
该流提供了打印方法,可以将各种数据类型的数据都原样打印
字节打印流:PrintStream
构造函数可以接收的参数类型:
1,file对象。File
2,字符串路径。String
3,字节输出流。OutputStream字符打印流:PrintWriter
构造函数可以接收的参数类型:
1,file对象。File
2,字符串路径。String
3,字节输出流。OutputStream
4,字符输出流,Writer
import java.io.*;
class Test {
public static void main(String[] args) throws IOException {
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new FileWriter("a.txt"), true);
String line = null;
while((line = bufr.readLine()) != null) {
if("over".equals(line))
break;
out.println(line);
//out.flush();
}
out.close();
bufr.close();
}
}
序列流(合并流)
将多个流合并成一个流
import java.io.*;
import java.util.*;
class Test {
public static void main(String[] args) throws IOException {
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("c:\\1.txt"));
v.add(new FileInputStream("c:\\2.txt"));
v.add(new FileInputStream("c:\\3.txt"));
Enumeration<FileInputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("c:\\4.txt");
byte[] buf = new byte[1024];
int len = 0;
while((len = sis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
sis.close();
}
}
Properties
Properties概述
- Properties是hashtable的子类,也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串
- 是集合中和IO技术相结合的集合容器
- 该对象的特点:可以用于键值对形式的配置文件
- 那么在加载数据时,需要数据有固定格式:键 = 值
Properties使用示例
从文本中加载键值对
BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
Properties prop = new Properties();
String line = null;
while((line = bufr.readLine()) != null) {
String[] arr = line.split("=");
prop.setProperty(arr[0],arr[1]);
}
bufr.close();
System.out.println(prop);
Properties可以直接从流中获取数据,修改并存储
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("info.txt");
prop.load(fis); //将流中的数据加载进集合
prop.setProperty("testKey","testValue");
FileOutputStream fos = new FileOutputStream("info.txt");
prop.store(fos,"note");
prop.list(System.out);
fos.close();
fis.close();
打印对象
ObjectInputStream与ObjectOutputStream
被操作的对象需要实现Serializable(标记接口)
静态属不能被序列化
要使改变过后的类还能使用以前的序列化,就需要自定义序列ID
不想序列化的成员加上transient关键字
import java.io.*;
class Person implements Serializable {
public static final long serialVersionUID = 42L;
private String name;
transient int age;
static String country = "cn";
Person(String name, int age, String country) {
this.name = name;
this.age = age;
this.country = country;
}
public String toString() {
return name + ":" + age + ":" + country;
}
}
import java.io.*;
class Test {
public static void main(String[] args) throws Exception {
//writeObj();
readObj();
}
public static void readObj()throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object"));
Person p = (Person)ois.readObject();
System.out.println(p);
ois.close();
}
public static void writeObj()throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object"));
oos.writeObject(new Person("name",0,"cn"));
oos.close();
}
}
管道流
PipedInputStream和PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用
使用单线程时,容易造成死锁
import java.io.*;
class Read implements Runnable {
private PipedInputStream in;
Read(PipedInputStream in) {
this.in = in;
}
public void run() {
try {
byte[] buf = new byte[1024];
int len = in.read(buf);
String s= new String(buf, 0, len);
System.out.println(s);
in.close();
} catch (IOException e) {
throw new RuntimeException("管道读取流失败");
}
}
}
class Write implements Runnable {
private PipedOutputStream out;
Write(PipedOutputStream out) {
this.out = out;
}
public void run() {
try {
out.write("Test Datas".getBytes());
out.close();
} catch (Exception e) {
throw new RuntimeException("管道输出流失败");
}
}
}
class Test {
public static void main(String[] args) throws IOException {
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out); //连接管道
Read r = new Read(in);
Write w = new Write(out);
new Thread(r).start();
new Thread(w).start();
}
}
RandomAccessFile
该类不是算是IO体系中子类
而是直接继承自Object
但是它是IO包中成员。因为它具备读和写功能
内部封装了一个数组,而且通过指针对数组的元素进行操作
可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置
其实完成读写的原理就是内部封装了字节输入流和输出流
通过构造函数可以看出,该类只能操作文件
而且操作文件还有模式:只读r,读写rw等
如果模式为只读r:不会创建文件,会去读取一个已存在文件,如果该文件不存在,则会出现异常
如果模式rw:操作的文件不存在,会自动创建,如果存在则不会覆盖
构造方法
RandomAccessFile(File file, String mode) | 创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定 |
RandomAccessFile(String name, String mode) | 创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称 |
值 | 含意 |
"r" | 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException |
"rw" | 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件 |
"rws" | 打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备 |
"rwd" | 打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到底层存储设备 |
可以用来实现多线程的下载
import java.io.*;
class Test {
public static void main(String[] args) throws IOException {
writeFile();
//readFile();
}
public static void readFile()throws IOException {
RandomAccessFile raf = new RandomAccessFile("ran.txt","r");
//调整对象中指针。
//raf.seek(8*1);
//跳过指定的字节数
raf.skipBytes(8);
byte[] buf = new byte[4];
raf.read(buf);
String name = new String(buf);
int age = raf.readInt();
System.out.println("name=" + name);
System.out.println("age=" + age);
raf.close();
}
//实现在指定位置写入
public static void writeFile_2()throws IOException {
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.seek(8 * 3);
raf.write("王五".getBytes());
raf.writeInt(21);
raf.close();
}
public static void writeFile()throws IOException {
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.write("张三".getBytes());
raf.writeInt(20);
raf.write("李四".getBytes());
raf.writeInt(22);
raf.close();
}
}
常见数据类型的操作流
- 操作基本数据类型
DataInputStream
与DataOutputStream
存入与读取顺序要相对应
import java.io.*;
class Test {
public static void main(String[] args) throws IOException {
//writeData();
//readData();
}
public static void readData() throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream("data.data"));
int num = dis.readInt();
boolean b = dis.readBoolean();
double d = dis.readDouble();
System.out.println("num = " + num);
System.out.println("b = " + b);
System.out.println("d = " + d);
dis.close();
}
public static void writeData() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.data"));
dos.writeInt(123);
dos.writeBoolean(true);
dos.writeDouble(876.543);
dos.close();
}
}
- 操作字节数组
ByteArrayInputStream
与ByteArrayOutputStream
ByteArrayInputStream
包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪read
方法要提供的下一个字节
ByteArrayOutputStream
实现了一个输出流,其中的数据被写入一个byte
数组。缓冲区会随着数据的不断写入而自动增长。可使用toByteArray()
和toString()
获取数据
关闭ByteArrayInputStream
与ByteArrayOutputStream
无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何IOException
ByteArrayInputStream:在构造的时候,需要接收数据源,而且数据源是一个字节数组
ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组,
这就是数据目的地。
因为这两个流对象都操作的数组,并没有使用系统资源,所以,不用进行close关闭
import java.io.*;
class Test {
public static void main(String[] args) {
//数据源
ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEF".getBytes());
//数据目的
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int by = 0;
while((by = bis.read()) != -1) {
bos.write(by);
}
System.out.println(bos.size());
System.out.println(bos.toString());
}
}
操作字符数组
CharArrayReader
与CharArrayWrite
与操作字节数组类似操作字符串
StringReader
与StringWriter
与操作字节数组类似
Java学习笔记-IO的更多相关文章
- java学习笔记--IO流
第十二章大纲: I/O input/output 输入/输出 一.创建文件,借助File类来实现 file.createNewFile() : 创建文件 file.exists() : 判断文件是否存 ...
- java学习笔记——IO部分(遍历文件夹)
用File类写的一个简单的工具,遍历文件夹,获取该文件夹下的所以文件(含子目录下的文件)和文件大小: /** * 列出指定目录下(包含其子目录)的所有文件 * @author syskey * */ ...
- java学习笔记IO之字节输入输出流
IO字节输入输出流 OutputStream:字节输出流 该抽象类是所有字节输出流的超类: 定义了一些共性的成员方法: 1.写入一个字节 void write(int b);//b表示字节 2.写入字 ...
- java学习笔记IO之File类
File类总结 p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Times } p.p2 { margin: 0.0px 0.0px 0.0p ...
- Java 学习笔记 IO流与File操作
可能你只想简单的使用,暂时不想了解太多的知识,那么请看这里,了解一下如何读文件,写文件 读文件示例代码 File file = new File("D:\\test\\t.txt" ...
- java学习笔记 --- IO(3)
1.FileReader:读取字符流,默认GBK public class CharStreamDemo { public static void main(String[] args) throws ...
- java学习笔记 --- IO(2)
IO流的分类: 流向: 输入流 读取数据 输出流 写出数据 数据类型: 字节流 字节输入流 读取数据 InputStream 字节输出流 写出数据 OutputStream 字符流 字符 ...
- java学习笔记 --- IO(1)
1.File类:文件和目录(文件夹)路径名的抽象表示形式,把文件或者目录(文件夹)都封装成File对象 1.构造方法 File(String pathname):根据一个路径得到File对象 File ...
- Java学习笔记——IO操作之对象序列化及反序列化
对象序列化的概念 对象序列化使得一个程序可以把一个完整的对象写到一个字节流里面:其逆过程则是从一个字节流里面读出一个事先存储在里面的完整的对象,称为对象的反序列化. 将一个对象保存到永久存储设备上称为 ...
随机推荐
- SQL拼串--小问题大毛病
用字符串拼接SQL串实现动态SQL语句,经常使用. 不过在拼接SQL串中有许多技巧和小陷阱 1.遗漏""和'' 错误案例: 错误结果: 发现没有数据产生..我还以为是连接错了数据库 ...
- 【python爬虫】 爬云音乐我和xxx共同听过的歌曲
闲聊的时候,觉得,想写个爬虫,爬下2个人共同听过的歌曲有哪些,然后一鼓作气,花了一个多小时,写了一个.支持最近一周和所有时间,需要用户没有关闭听歌排行显示 How to start 使用到的工具是Se ...
- 自己编写一个Java监听器
Java监听器 1.原理: 当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法. 例如:创建一个“人”类Class Person 人拥有吃的方法public void eat(){},我 ...
- jQuery系列(三):jQuery动画效果
jQuery提供的一组网页中常见的动画效果,这些动画是标准的.有规律的效果:同时还提供给我们了自定义动画的功能. 1.显示动画 方式一: $("div").show(); 解释:无 ...
- C# Socket 编程 Sample
使用Socket通信的服务器端编程,熟悉了服务器端和客户端的通信流程,实现了收发信息.文件传送以及震动功能 服务器端先创建Socket,然后将其和本地ip地址以及端口号连接,也就是使用Bind方法,然 ...
- JS核心知识点:DOM\BOM\EVENT
1.DOM(Document Object Model) :文档对象模型2. DOM节点:页面中最基本的组成部分 3. childNodes:获取某个节点下所有的子节点 在标准及ie9以上 : 会获取 ...
- C#实现代码生成器
最近在用layui做后台管理,增删改查这些一成不变的东西写起来浪费大量时间,于是做了个简单的代码生成器快速生成 代码生成器的原理其实很简单,都是基于模板实现替换,Razor是个不错的选择(或者Nvel ...
- umei-spider
umei-spider 1 #!/usr/bin/python3 2 3 import requests 4 from bs4 import BeautifulSoup 5 from contextl ...
- 在iOS开发中使用icon font的方法
http://iconfont.cn/help/iconuse.html 在开发阿里数据iOS版客户端的时候,由于项目进度很紧,项目里的所有图标都是用最平常的背景图片方案来实现.而为了要兼容普通屏与R ...
- iscc2018-Reverse-writeup
RSA256 解析公钥 yafu质因数分解 p=325045504186436346209877301320131277983 q=3028255367440967415185462127611943 ...