流与文件
1.1 流
- 读写字节
InputStream类:
abstract int read() 读入一个字节,并返回读入的字节,或者在遇到输入源结尾返回-1.
OutputStream类:
bstract void write(int b) 向某个位置写出一个字节。
close()方法关闭流
flush() 方法刷新流输出。 - 完整的流家族
Reader层次:
Writer层次:
- 组合流过滤器
流分别具有单独的功能,将不同的流组装套一起以实现复杂的功能。
####1.2 文本输入与输出
OutputStreamWriter 按照选定的编码方式,把Unicode字符流转换成字节流。
InputStreamReader 将指定编码的字节输入流转换成Unicode字符流。
- 如何写出文本输出
以二进制格式写出:DataOutputStream
以文本格式写出:PrintWriter
PrintWriter out = new PrintWriter("d://aaa.txt"); //创建输出流
String name = "Harry Hacker";
double salary = 75000;
out.print(name);
out.print(" ");
out.println(salary);
out.flush();
PrintWriter out = new PrintWriter(new FileWriter(“d:/aaa.txt”),true); 自动冲刷模式。
2. 如何读入文本输入
new BufferedReader(new InputStreamReader(inputStream));
3. 字符集
字符串和编码字节转换
Charset charset = Charset.forName("ISO-8859-1");
String s = "aaa";
ByteBuffer byteBuffer = charset.encode(s);
byte[] bytes = byteBuffer.array();
ByteBuffer buffer = byteBuffer.wrap(bytes, offset, length);
1.3 读写二进制数据
DataOutput 用于以二进制方式写数据。
RandomAccessFile 可以在文件中的任意位置查找或写入数据。
1.4 ZIP文档
读zip文件:
ZipInputStream zin =new ZipInputStream(new FileInputStream("d://aaa.zip"));
ZipEntry entry;
while ((entry = zin.getNextEntry()) != null) {
//
zin.closeEntry();
}
zin.close();
写zip文件:
FileOutputStream out = new FileOutputStream("d://aaa.zip");
ZipOutputStream zout = new ZipOutputStream(out);
//for all files
{
ZipEntry ze = new ZipEntry(filename);
zout.putNextEntry(ze);
zout.closeEntry();
}
zin.close();
1.5 对象流与序列化
ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("d://aa.txt"));
Employee e = new Employee("哈哈", 75000, 1987, 12, 15);
objOut.writeObject(e);
对象必须实现Serializable
某些数据域是不可序列化的,需要用transient 标记。
序列化可以实现克隆对象,把对象写到输出流,然后再读回。
1.6 操作文件
- Path
get方法,接收字符串返回路径。
p.resolve(q):如果q是绝对路径,结果就是q。否则将p后面紧跟q作为结果。
p.relativize(q): - 读写文件
Files类
Files.readAllBytes(path) 读取
Files.write(path, bytes,count.getByde(charset)) 读取。
1.7内存映射文件
首先创建缓冲通道:
FileChannel.open(path, FileChannel.MapMode.READ_ONLY);
FileChannel 的map方法获得一个ByteBuffer,有了缓冲区就可以读写数据。
- 缓冲区数据结构
Buffer类是一个抽象类:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer 和 ShortBuffer。
每个缓冲区都具有:
容量(Capacity):缓冲区能够容纳的数据元素的最大数量。这一容量在缓冲区创建时被设定,并且永远不能被改变。
上界(Limit):缓冲区的第一个不能被读或写的元素。缓冲创建时,limit 的值等于 capacity 的值。假设 capacity = 1024,我们在程序中设置了 limit = 512,说明,Buffer 的容量为 1024,但是从 512 之后既不能读也不能写,因此可以理解成,Buffer 的实际可用大小为 512。
位置(Position):下一个要被读或写的元素的索引。位置会自动由相应的 get() 和 put() 函数更新。 这里需要注意的是positon的位置是从0开始的。
标记(Mark):一个备忘位置。标记在设定前是未定义的(undefined)。使用场景是,假设缓冲区中有 10 个元素,position 目前的位置为 2(也就是如果get的话是第三个元素),现在只想发送 6 - 10 之间的缓冲数据,此时我们可以 buffer.mark(buffer.position()),即把当前的 position 记入 mark 中,然后 buffer.postion(6),此时发送给 channel 的数据就是 6 - 10 的数据。发送完后,我们可以调用 buffer.reset() 使得 position = mark,因此这里的 mark 只是用于临时记录一下位置用的。
2. 文件加锁机制
try(FileLock lock = chanel.lock())
{
dosomething
}