Separate io helpers from _libs.lib
Avoids overlap with #19360 where possible.

Moved functions are cut/paste verbatim.

I'm open to a better name than io_helpers, just wanted to avoid overlap with the stdlib name "io".

Besides refactoring for its own sake, part of the goal is to get lib down the point where we can merge src/inference back into it; the split file makes it tough to track dependencies, and AFAICT it makes the move towards using cythonize easier.
Closing to declog CI pipeline. # [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/19364?src=pr&el=h1) Report
> Merging [#19364](https://codecov.io/gh/pandas-dev/pandas/pull/19364?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/5fdb9c0edef57da4b29a437eca84bad5f20719b7?src=pr&el=desc) will **decrease** coverage by `<.01%`.
> The diff coverage is `91.66%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/19364/graphs/tree.svg?token=eZ4WkYLtcO&width=650&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/19364?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #19364      +/-   ##
==========================================
- Coverage   91.57%   91.56%   -0.01%     
==========================================
  Files         150      150              
  Lines       48705    48706       +1     
==========================================
- Hits        44600    44599       -1     
- Misses       4105     4107       +2
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `89.93% <83.33%> (-0.01%)` | :arrow_down: |
| #single | `41.72% <83.33%> (ø)` | :arrow_up: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/19364?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/io/parsers.py](https://codecov.io/gh/pandas-dev/pandas/pull/19364/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL3BhcnNlcnMucHk=) | `95.5% <100%> (ø)` | :arrow_up: |
| [pandas/io/json/normalize.py](https://codecov.io/gh/pandas-dev/pandas/pull/19364/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2pzb24vbm9ybWFsaXplLnB5) | `96.87% <100%> (ø)` | :arrow_up: |
| [pandas/io/formats/format.py](https://codecov.io/gh/pandas-dev/pandas/pull/19364/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2Zvcm1hdHMvZm9ybWF0LnB5) | `96.24% <100%> (ø)` | :arrow_up: |
| [pandas/io/pytables.py](https://codecov.io/gh/pandas-dev/pandas/pull/19364/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL3B5dGFibGVzLnB5) | `92.45% <83.33%> (ø)` | :arrow_up: |
| [pandas/util/testing.py](https://codecov.io/gh/pandas-dev/pandas/pull/19364/diff?src=pr&el=tree#diff-cGFuZGFzL3V0aWwvdGVzdGluZy5weQ==) | `84.24% <0%> (-0.22%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/19364?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/19364?src=pr&el=footer). Last update [5fdb9c0...3b273f0](https://codecov.io/gh/pandas-dev/pandas/pull/19364?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
