Read files in binary mode to simplify implementation

- adds null detection special case
- handles empty file edge case
- works entirely in binary mode