The built in way to do this is with registers.
For instance use C-xrwa to save the current window configuration to register a.
Then you can use the built in binding C-x1 to run
after you're done looking at the single file, use C-xrja to pop back to the saved window configuration in register a.
C-xrwa (save config into register)
C-x1 (delete other windows)
C-xrja (reapply saved window config)
I do find registers to be unwieldy though, I use a custom window config stack to manage my configs.
I have two bindings that push the current config onto the stack, and pop and apply the top config.
So in your sceneario, I would perform my push binding, then C-x 1, then perform my pop binding.
Here is the code:
(defvar winstack-stack '()
"A Stack holding window configurations.
Use `winstack-push' and
`winstack-pop' to modify it.")
"Push the current window configuration onto `winstack-stack'."
(if (and (window-configuration-p (first winstack-stack))
(compare-window-configurations (first winstack-stack) (current-window-configuration)))
(message "Current config already pushed")
(progn (push (current-window-configuration) winstack-stack)
(message (concat "pushed " (number-to-string
(length (window-list (selected-frame)))) " frame config")))))
"Pop the last window configuration off `winstack-stack' and apply it."
(if (first winstack-stack)
(progn (set-window-configuration (pop winstack-stack))
(message "End of window stack")))
You can then bind
winstack-push to something like C-cC-u, and
winstack-pop to C-cC-o to easily jump around.