IO
1.回顾
Collection vs Map 区别?
Collection: 无序 单列
Map: 无序 键值对 key: 唯一 value: 可以重复
List vs Set 区别?
List: 元素可重复 有序(元素有索引)
Set: 元素唯一 无序
List集合实现类: ArrayList
ArrayList: 查询速度最快 增加 删除较慢 动态数组 线程不安全
LinkedList: 增删快 查询慢 双向链表 Node 线程不安全
Vector: 一般 动态数组 线程安全 synchronized
CopyonWriteArrayList: 数组 Lock
Set集合实现类:
HashSet: 元素可以null 线程不安全 底层HashMap维护 元素无序
LinkedHashSet: 元素可以null 线程不安全 底层HashMap维护(哈希表和链表) 插入顺序与遍历顺序一致
TreeSet: 元素不可以null 底层TreeMap维护 线程不安全 元素有序(按照自然顺序排列)
CopyonWriteArraySet: 元素可以null 线程安全 Lock
Map集合实现类: 重点掌握HashMap底层put get resize
底层是如何保证HashMap的key的唯一性的? 解决Hash冲突的?
HashMap: 数组(Node[])+链表(Node)+红黑树(TreeNode) K v 都可以为null 线程不安全
LinkedHashMap: 哈希表和链表 K v 都可以为null 线程不安全
TreeMap: 红黑树 K不可以为null v可以为null 线程不安全
HashTable: 哈希表 K v 都不可以为null 线程安全 synchronized
ConcurrentHashMap: 哈希表 K v 都不可以为null 线程安全 CAS 读场景
可以将线程不安全的集合类转换成线程安全的? Collections.synchronizedList()
有哪些方式可以对List集合元素去重?
1.List转 Set
2.Stream.distinct()
IO
File
- 文件和目录路径名的抽象表示。java.io.*
数据肯定要持久化保存 (磁盘文件+缓存)
常用构造
File(String pathname) 根据指定的文件路径或者目录路径创建对象
File(String parent, String child) 根据父级目录路径以及子级文件路径创建文件对象
File(File parent, String child) 根据父级目录对象以及子级文件路径创建文件对象
常用属性
static String pathSeparator 代表不同系统里面的路径分隔符 unix: : windows: ;
static char pathSeparatorChar
static String separator 代表不同系统里面的盘符分隔符 unix: / windows: \
static char separatorChar
常用方法
当File是文件时:
boolean exists() 文件是否存在
String getName() 获得文件名称
boolean isFile() 是否是文件
boolean delete() 删除文件
String getAbsolutePath() 获得文件绝对路径
String getPath() 获得文件相对路径
boolean createNewFile() 创建文件
long lastModified() 获得上一次修改文件的时间(好描述)
long length() 获得文件大小(字节数)
boolean renameTo(File dest) 文件重命名或者复制
文件执行权限操作:
boolean canExecute()
boolean canRead()
boolean canWrite()
boolean isHidden()
boolean setReadOnly()
当文件是目录时:
boolean exists() 目录是否存在
String getName() 获得目录名称
boolean isDirectory() 是否是目录
boolean mkdir() 创建目录
boolean mkdirs()
String[] list() 获得当前目录下一级资源文件名称
String[] list(FilenameFilter filter) 获得当前目录下满足条件的一级资源文件名称
File[] listFiles() 获得当前目录下一级资源文件或者目录对象
File[] listFiles(FileFilter filter)
File[] listFiles(FilenameFilter filter)
递归
案例: 查询当前文件下所有的子目录以及子文件 , 打印以下形状:
|-src
| |-com
| | |-javasm
| | | |-exercise
| | | | |- HelloWorld.java
|-test
| |-com
| | |-javasm
| | | |-test
| | | | |- StudentTest.java
public static void main(String[] args) {
File directory = new File("day17/src");
demo7(directory, "|-");
}
private static void demo7(File directory, String str) {
File[] files = directory.listFiles();
for (File file1 : files) {
//当file是目录 在进行遍历
System.out.println(str + file1.getName());
if (file1.isDirectory()) {
//调用当前自己的逻辑(自己调用自己) 递归
demo7(file1, "| " + str);
}
}
}
IO
持久化将变量的数据保存到文件中, 通过程序将数据写入磁盘。读取磁盘数据。
Input Output 输入输出流 从流向上区分:
程序 数据 磁盘
输入流:
通过程序读取磁盘文件内容 read 简称输入流。
输出流:
通过程序将数据写入磁盘文件中 write 简称输出流。
所有计算机的文件都属于二进制文件 以字节存储。
从操作内容: 字节流 字符 流 读写
字节流
2个字节流父类: InputStream OutputStream 抽象类。
字节输入流 InputStream—read
public abstract class InputStream
extends Object
implements Closeable 代表资源需要释放(finally)
常用子类:
public class FileInputStream extends InputStream
public class BufferedInputStream extends FilterInputStream
public class DataInputStream extends FilterInputStream implements DataInput
public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants
常用方法:
void close()
abstract int read() 一次读取一个字节内容 返回-1
int read(byte[] b)
一次读取b.length个字节内容(存储到字节数组中)
返回值: 读取到的有效的字节个数 -1
int read(byte[] b, int off, int len)
一次读取len个字节内容(从off索引位置上开始 存储到字节数组中)
返回值: 读取到的有效的字节个数 -1
int available() 获得输入流中有效的字节个数 file.length()
FileInputStream(String name) 推荐
FileInputStream(File file)
private static void demo2(String path) {
// try...with...resources 提供一种更加优雅的方式来处理流对象的关闭
// 类一定实现Closeable接口
//100
//read() 读100次 写100次
//read(byte[] bytes) 分成2次处理: 读100次 写2次(写的时候 提升效率的)
try (
//1.创建流对象
InputStream inputStream = new FileInputStream(path);
) {
//2.循环读取文件数据
byte[] bytes = new byte[50];//1024的整数倍 缓冲 适应于大文件读写
int result = inputStream.read(bytes);
//一次读取1024个字节 存储到bytes数组
// result:读取到的真实的有效的字节数量
System.out.println(Arrays.toString(bytes));
System.out.println(result);
//字节数组转换成字符串
// for (int i = 0; i < result; i++) {
// System.out.print((char) bytes[i]);
// }
String s = new String(bytes, 0, result);
System.out.println(s);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
字节输出流 OutputStream—write
public abstract class OutputStream
extends Object
implements Closeable, Flushable
常用方法:
void close()
void flush()
void write(byte[] b)
void write(byte[] b, int off, int len)
abstract void write(int b)
常用子类:
public class FileOutputStream extends OutputStream
public class BufferedOutputStream extends FilterOutputStream
public class DataOutputStream extends FilterOutputStream implements DataOutput
public class ObjectOutputStream extends OutputStream
implements ObjectOutput, ObjectStreamConstants
FileOutputStream(File file)
FileOutputStream(File file, boolean append)
FileOutputStream(String name)
FileOutputStream(String name, boolean append)
文件复制
public class BufferedInputStream extends FilterInputStream
public class BufferedOutputStream extends FilterOutputStream
byte[] byf = new byte[8192];
模拟用户头像上传:
/**
* 文件上传
*
* @param sourceFile 源文件
* @return 上传成功之后的 文件路径
*/
public static String upload(File sourceFile) {
Objects.requireNonNull(sourceFile);
//循环读写
//目标文件(路径):
// sourceFile.getName()
// day17/upload/user/2020-10-29/???
StringBuilder targetFilePath = new StringBuilder(TARGET_PATH);
//获得当前的日期: LocalDate.now()
String localDate = LocalDate.now().toString();
targetFilePath.append(localDate);
//存在这样的目录: day17/upload/user/2020-10-29/
File parent = new File(targetFilePath.toString());
if (!parent.exists()) {
parent.mkdirs();
}
targetFilePath.append(File.separatorChar);
//保证文件名称唯一性
targetFilePath.append(UUID.randomUUID().toString().replace("-", ""));
targetFilePath.append("_");
targetFilePath.append(sourceFile.getName());
System.out.println("targetFilePath:" + targetFilePath);
try (
BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(targetFilePath.toString()));
) {
byte[] bytes = new byte[1024];
int len = 0;
while ((len = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return targetFilePath.toString();
}
###字符流
二进制文件。 操作文本文件 doc ppt xls POI
在字节流的基础之上 + 编码格式 UTF-8 gbk 网络协议: ISO8859-1
字符输入流 Reader—read
public abstract class Reader
extends Object
implements Readable, Closeable
abstract void close()
int read()
int read(char[] cbuf)
abstract int read(char[] cbuf, int off, int len)
常用子类:
public class FileReader extends InputStreamReader
public class BufferedReader extends Reader
public class InputStreamReader extends Reader
字符输出流 Writer----write
public abstract class Writer
extends Object
implements Appendable, Closeable, Flushable
Writer append(CharSequence csq) 将内容追加到文件末尾
Writer append(char c)
void write(char[] cbuf)
abstract void write(char[] cbuf, int off, int len)
void write(String str)
void write(int c)
public class FileWriter extends OutputStreamWriter
public class OutputStreamWriter extends Writer
public class BufferedWriter extends Writer
高效字符流
BufferedReader
BufferWriter
BufferedReader(Reader in)
String readLine()
private static void demo1(String path) {
//读取文件数据: InputStream Reader
try (
BufferedReader bufferedReader = new BufferedReader(new FileReader(path));
// BufferedWriter bufferedWriter = new BufferedWriter()
) {
// String readLine = bufferedReader.readLine();// null 代表读到末尾
// System.out.println(readLine);//1-jim-1234
String content = "";
List<User> users = new ArrayList<>(10);
while ((content = bufferedReader.readLine()) != null) {
//content: 就是一个用户的完整的信息 转换成用户对象
String[] userInfo = content.split("-");
//将String转换成Integer
users.add(new User(Integer.parseInt(userInfo[0]), userInfo[1], userInfo[2]));
}
users.forEach(System.out::println);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
其它流
也是字节流或者字符流的子类 只是有特定的功能以及使用场景。
数据流(先写再读)
属于字节流。
public interface DataOutput
public class DataOutputStream extends FilterOutputStream implements DataOutput
通过程序可以利用 DataOutputStream 将字面量类型的数据以指定的字节写入文件中
public interface DataInput
public class DataInputStream extends FilterInputStream implements DataInput
通过程序可以利用 DataInputStream 读取指定字节的字面量类型的数据
####对象流(先写再读)
又称为序列化流(写)和反序列化流(读) 主要执行对象序列化以及反序列化操作
前提: 实现Serializable接口
public interface ObjectOutput extends DataOutput, AutoCloseable
public class ObjectOutputStream extends OutputStream
implements ObjectOutput, ObjectStreamConstants
ObjectOutput扩展了DataOutput接口,包括写入对象
void writeObject(Object obj)
将对象写入底层存储或流。
public interface ObjectInput extends DataInput, AutoCloseable
public class ObjectInputStream extends InputStream
implements ObjectInput, ObjectStreamConstants
ObjectInput扩展了DataInput接口以包含对象的读取。
Object readObject()
读取并返回一个对象。
java.io.NotSerializableException: com.javasm.io1.UserInfo
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dAIOac2z-1605082309423)(pic\serizal_id .png)]
转换流
字符流的子类,
字节流转字符流的桥梁 InputStreamReader 网络资源的读取。
它读取字节,并使用指定的charset将其解码为字符.
InputStreamReader(InputStream in)
InputStreamReader(InputStream in, Charset cs)
InputStreamReader(InputStream in, String charsetName)
需求:
下载某个小说平台某个小说某个章节内容 写入本地指定的文件中
private static void readNovel(String url) {
//将小说内容 写入指定的文件中 write ---> 输出流 OutPutStream Writer
//<div class="read-content j_readContent ">
// InputStream inputStream = ;
//inputStream: 要获得的资源
try (
//FileReader:计算机磁盘里面的文件
//Reader:
BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(url).openStream(), "utf-8"));
BufferedWriter writer = new BufferedWriter(new FileWriter("day18/src/novel.txt"));
) {
String content = "";
while ((content = reader.readLine()) != null) {
if (content.contains("<div class=\"read-content j_readContent \">")) {
content = reader.readLine();
content = content.replaceAll("[<p>]", "\n");
writer.write(content);
break;
}
}
System.out.println("success");
} catch (IOException e) {
e.printStackTrace();
}
}
字符流转字节流的桥梁 OutputStreamWriter
Properties
加载配置文件内容。 属性集合。 HashTable的子类。 java.util.*
public class PropsUtil {
//加载properties 加载1次
private PropsUtil() {
}
private static Properties properties;
private final static String PATH = "day18/src/admin.properties";
static {
properties = new Properties();
try (
InputStream inputStream = new FileInputStream(PATH);
) {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getValue(String key) {
Objects.requireNonNull(key);
return properties.getProperty(key).trim();
}
}
public class PropsUtil {
//加载properties 加载1次
private PropsUtil() {
}
private static Properties properties;
private final static String PATH = "day18/src/admin.properties";
static {
properties = new Properties();
try (
InputStream inputStream = new FileInputStream(PATH);
) {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getValue(String key) {
Objects.requireNonNull(key);
return properties.getProperty(key).trim();
}
}