Replacing a newline with an empty string joins the adjacent line contents directly. I’m intrigued that removing a separator can make two values mean something different.
As you consider the returned value, notice what text mode does to its line separators. Then decide whether those boundaries matter for your next task.
What it means to read a file as a string
A text file becomes one Python string when Python decodes its bytes. In text mode, Python keeps line separators in that value unless you explicitly replace or remove them.
A file object keeps a cursor that marks where the next read starts. Calling read() without a size consumes the remaining content, so a second call on the same object returns an empty string unless you move the cursor back.
| Operation | Result |
|---|---|
| read() in text mode | One decoded string |
| readlines() | A list of line strings |
| read() in binary mode | Bytes |
What you need before reading the file
Use the encoding the file was written with, and specify it explicitly when known, because Python’s default can vary by platform.
A relative path starts from the process’s current working directory, and a known encoding prevents the default from deciding how bytes become text.
- Use Python’s standard library, so no additional package is required.
- Keep the file path relative to the current working directory, or provide an absolute path.
- Read text in text mode and provide an explicit encoding when the file’s encoding is known.
Step 1: Read the complete file with open()
A context manager closes the file when the block ends, including when an exception interrupts the read.
The mode r opens the file for text reading, and read() starts at the current cursor position. The returned string contains the file’s text, including line separators that remain after text-mode newline handling.
with open("sample.txt", "r", encoding="utf-8") as file:
content = file.read()
print(repr(content))
For the fixture used here, the printed representation ends with a newline marker. I ran the example, and the final newline stayed in the string, so removing it should be a deliberate choice.
Use repr() while debugging when invisible separators are confusing, because it makes newline characters visible. For normal display, print(content) renders those separators as line breaks instead.
Step 2: Read a path with pathlib
Path.read_text() reads the complete file as text and closes it, so you do not manage an open file object yourself.
from pathlib import Path
content = Path("sample.txt").read_text(encoding="utf-8")
print(repr(content))
Its encoding and error options are documented in the official pathlib reference, and line breaks remain part of the returned string.
Choose open() when you need several operations on the same file object, such as reading incrementally. Choose read_text() when one complete text value is the goal.
Step 3: Change line breaks only when needed
Keep line breaks when the text represents paragraphs, source code, or records whose boundaries matter. Transform the string only if the next task needs joined lines.
| Transformation | Effect |
|---|---|
| Replace newline with a space | Retains a visible separator between lines |
| Replace newline with an empty string | Joins adjacent line contents directly |
| Keep the original string | Preserves the text-mode line boundaries |
from pathlib import Path
content = Path("sample.txt").read_text(encoding="utf-8")
one_line = content.replace("\n", " ").strip()
print(repr(one_line))
Use the string replace() method only when you know what should separate the original lines.
Removing a separator can join two values into text that means something different.
The example replaces newline characters with spaces and strips whitespace at the ends. If blank lines or leading spaces carry meaning, avoid strip() and choose the exact transformation your data needs.
When the result is not the string you expected
- FileNotFoundError means the path or current working directory needs checking. See the FileNotFoundError guide.
- UnicodeDecodeError means the selected encoding does not decode the file’s bytes. Use the encoding used to create the file.
- An empty second read means the cursor is at the end. Reopen the file or seek to the start before reading again.
- A list result comes from readlines(), while binary mode produces bytes rather than decoded text.
Text mode decodes bytes and can translate platform line endings. Python’s open() documentation describes encoding and newline controls, while binary mode skips text decoding and returns bytes.
When a file is too large to hold in memory as one string, process it line by line instead. A full-file read is appropriate only when the content size fits the memory available to your program.
Keep text reading separate from parsing
Reading a file into a string gives you its text, not structured records.
Use a format-aware parser for CSV, JSON, or XML when your next operation depends on fields rather than the original text.
from pathlib import Path
text = Path("sample.txt").read_text(encoding="utf-8")
print(type(text).__name__)
Read-file-as-string questions
Choose the read method from the value the next operation needs, and keep line-break removal separate from reading the file.
How do I read an entire text file into one string in Python?
Open it in text mode and call read(), or call Path.read_text() with the file’s encoding. Both return the decoded text as one string.
How can I remove newline characters from the string?
Replace each newline with the separator your task needs, or split the text into lines and join them. Keep the newlines when they carry meaningful boundaries.
Does readlines() return a string?
No. readlines() returns a list of line strings. Use read() when you want the remaining file contents as one string.
How do I read a CSV file as a string in Python?
Use read_text() if you need the raw file text. Use Python’s csv module when you need rows and fields parsed into records.

