Fix open file leak

Previously, replay was calling `open` for every single line of input. On my device, it crashed after about 1000 events because it reached the open file limit. I fixed this by creating a fd lookup cache to reuse fds if they have already been opened, and then closing all opened fds at the end for good measure.