常用流文件处理

时间:2022-11-03 07:18:20


使用byte,按照字节读取   使用character,按照字符读取 使用reader,按照行读取 使用buffer,缓存读取 使用channel,通道读取 使用内存映射,读取文件

* FileChnel flip --> buffer的三個属性

1. 重放数据 -> 从生成的临时文件(page cache 脏页)变成数据文件

2. 按行读取文件

3. mmap不足如何在生成一个mmap映射文件

* FileChnel flip --> buffer的三個属性

     byte[] buff  //buff即内部用于缓存的数组。

     position //当前读取的位置或者下一次写入的位置

     mark //为某一读过的位置做标记,便于某些时候回退到该位置。

     capacity //初始化时候的容量。

     limit //当写数据到buffer中时,limit一般和capacity相等,当读数据时,

     limit代表buffer中有效数据的长度。

netty中对ByteBuf的增强:

● 简化了缓冲区的读写操作(减少filp操作)

● 动态扩展(倍增+平滑)

● 引用计数,内存回收

public class ByteBuffTest {
2
3 public static void main(String[] args){
4 /*******************初始阶段**********************/
5 ByteBuf buf = Unpooled.buffer(100, 200);
6 System.out.println("writable bytes " + buf.writableBytes());
7 System.out.println("readable bytes " + buf.readableBytes());
8
9 /*******************写入数据**********************/
10 String str = "write test";//UTF-8 英文字符占一个字节
11 int length = str.getBytes().length;//因此得到的字节长度为10
12 buf.writeBytes(str.getBytes());
13 System.out.println("writable bytes " + buf.writableBytes());
14 System.out.println("readable bytes " + buf.readableBytes());
15
16 /*******************读取数据*********************/
17 char c = (char)buf.readByte();//读取第一个字节,并转换成字符打印
18 System.out.println("c:" + c);
19 System.out.println("writable bytes " + buf.writableBytes());
20 System.out.println("readable bytes " + buf.readableBytes());
21
22 /*******************丢弃已读*********************/
23 buf.discardReadBytes();
24 System.out.println("writable bytes " + buf.writableBytes());
25 System.out.println("readable bytes " + buf.readableBytes());
26
27 }
28 }

1. 重放数据 -> 从生成的临时文件(page cache 脏页)变成数据文件

public static void recoverVLog(String path, int shardId) {
// 根据文件的父路径和子路径获取文件
File vlogTmpFile = new File(path, Filename.vlogTmpFileName(shardId));
if (!vlogTmpFile.exists()) {
return;
}
// 读取文件流
try (FileChannel vlogTmpChannel = new FileInputStream(vlogTmpFile).getChannel();
FileChannel vLogWriter = new FileOutputStream(new File(path, Filename.vlogFileName(shardId)), true).getChannel()) {
// 4个字节的bytebuffer
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
// 循环读取4个字节到buffer
while (vlogTmpChannel.read(buffer) > 0) {
// 对同一块区域不断擦写
buffer.flip(); // 读取buffer的数据limit = position;position = 0;mark = -1;
vLogWriter.write(buffer); // 写入到新文件
buffer.clear();
}

// safe deletion
vlogTmpFile.delete();
} catch (IOException e) {
e.printStackTrace();
Throwables.propagate(e);
}
}

// 这里的size包括重放的和插入的
long vLogFileSize = vLogWriter.getFileSize();

vlogSequence = (int) (vLogFileSize / 8);

2. 按行读取文件

/**
* InputStreamReader 按行读取25M内容约9319ms
* @param path
* @param results
* @return
*/
public static List<LocationBean> test(String path, List<LocationBean> results ) {
FileInputStream fis = null;
BufferedReader br = null;
try {
File file = new File(path);
fis = new FileInputStream(file);
br = new BufferedReader(new InputStreamReader(fis));

String line = null;

while ((line = br.readLine()) != null) {

msgAction(line, results);
}
return results;
}catch (IOException e) {
e.printStackTrace();
}finally {
try {
fis.close();
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}

3. mmap不足如何在生成一个mmap映射文件

// 初始化一个mmap
public MmapLogWriter(File file) throws IOException {
requireNonNull(file, "file is null");
this.file = file;
this.fileChannel = new RandomAccessFile(file, "rw").getChannel();
//TODO append position should be file size mmap
mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, PAGE_SIZE);
}

// 追加数据-》此缓冲区中剩余的元素数不足,就ummap重新再分配map
private void ensureCapacity(int bytes) throws IOException {
// 此缓冲区中剩余的元素数不足,就ummap重新再分配map
if (mappedByteBuffer.remaining() < bytes) {
fileOffset += mappedByteBuffer.position();
MMapUtil.unmap(mappedByteBuffer);
mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, fileOffset, PAGE_SIZE);
}
}