Skip to content

Commit 2ae01b5

Browse files
committed
Update open_qfile.py
1 parent c1c1e0f commit 2ae01b5

File tree

1 file changed

+61
-43
lines changed

1 file changed

+61
-43
lines changed

07-Packaging-资源管理与打包/01-资源管理/open_qfile.py

Lines changed: 61 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,44 @@
11
import locale
22
import os
3+
import pathlib
34
import warnings
45
from typing import Optional, Union
56

67
from PySide6.QtCore import QFile, QIODevice
78

89

9-
class OpenQFile:
10+
class QtFileOpen:
1011
"""
11-
用于以QFile形式打开文件的上下文管理器 \n
12-
使支持 Python 的 with 风格 \n
12+
通过 QFile 读写文件的上下文管理器 \n
13+
使与 Python 的 with 语句风格统一 \n
14+
15+
使用举例:
16+
17+
with QtFileOpen("./test.txt", "rt", encoding="utf-8") as f:
18+
print(f.read())
1319
"""
1420

15-
def __init__(self, file: Union[str, bytes, os.PathLike[str]],
16-
mode="r",
17-
encoding: Optional[str] = None):
21+
def __init__(
22+
self,
23+
file: Union[str, bytes, os.PathLike[str]],
24+
mode="r",
25+
encoding: Optional[str] = None,
26+
):
1827
"""
1928
:param file: 文件路径
2029
:param mode: 打开模式(暂时只支持文本读取)
2130
:param encoding: 文本文件编码
2231
"""
2332

33+
# 预处理文件路径,防止在 Windows 平台下 QFile 只能处理 '/' 导致的问题
34+
file_path = self.deal_path(file)
35+
print(file_path)
36+
2437
# 分析模式是否合法、返回正确的 FileIo 类实例
2538
# https://docs.python.org/zh-cn/3/library/functions.html#open
2639
if "b" not in mode:
2740
# 文本模式
28-
self.io_obj = PyQTextFileIo(file, mode, encoding)
41+
self.io_obj = PyQTextFileIo(file_path, mode, encoding)
2942
else:
3043
# 二进制模式(暂不支持)
3144
# self.io_obj = PyQByteFileIo(file, mode)
@@ -37,13 +50,44 @@ def __enter__(self):
3750
def __exit__(self, exc_type, exc_val, exc_tb):
3851
self.io_obj.close()
3952

53+
@classmethod
54+
def deal_path(cls, path) -> str:
55+
"""
56+
预处理文件路径,确保使用 / 风格
57+
:param path: 文件路径
58+
:return: 使用正斜杠(/)的路径字符串
59+
"""
60+
61+
# 若路径以字节串传入,则先处理成字符串
62+
if isinstance(path, bytes):
63+
path = str(path, encoding=locale.getencoding())
64+
65+
return str(pathlib.PurePath(path).as_posix())
66+
4067

4168
class PyQTextFileIo:
4269
"""
4370
将 QFile 中处理文本文件读写的部分封装成 Python的 io 风格
4471
目前只支持读取,不支持写入
4572
"""
4673

74+
def __init__(
75+
self,
76+
file: Union[str, bytes, os.PathLike[str]],
77+
mode,
78+
encoding: Optional[str] = None,
79+
):
80+
self._file = QFile(file)
81+
82+
if encoding is not None:
83+
self.encoding = encoding
84+
else:
85+
# 用户未指定编码,则使用当前平台默认编码
86+
self.encoding = locale.getencoding()
87+
88+
self.mode = self._parse_mode(mode)
89+
self._file.open(self.mode)
90+
4791
@classmethod
4892
def _parse_mode(cls, py_mode: str) -> QIODevice:
4993
"""
@@ -68,26 +112,12 @@ def _parse_mode(cls, py_mode: str) -> QIODevice:
68112

69113
return qt_mode
70114

71-
def __init__(self, file: Union[str, bytes, os.PathLike[str]],
72-
mode,
73-
encoding: Optional[str] = None):
74-
75-
self._file = QFile(file) # TODO 处理 QFile 只接受`/`风格路径可能导致 Windows 平台异常的问题
76-
77-
if encoding is not None:
78-
self.encoding = encoding
79-
else:
80-
# 用户未指定编码,则使用当前平台默认编码
81-
self.encoding = locale.getencoding()
82-
83-
self.mode = self._parse_mode(mode)
84-
self._file.open(self.mode)
85-
86115
def readable(self) -> bool:
87116
"""
88117
当前文件是否可读 \n
89118
:return: isReadable
90119
"""
120+
91121
return self._file.isReadable()
92122

93123
def read(self, size: int = -1) -> str:
@@ -112,7 +142,7 @@ def read(self, size: int = -1) -> str:
112142

113143
return text
114144

115-
def readline(self, size: int = - 1, /) -> str:
145+
def readline(self, size: int = -1, /) -> str:
116146
"""
117147
模仿 io.TextIOBase.readline 的行为,读取文件中的一行。 \n
118148
https://docs.python.org/3/library/io.html#io.TextIOBase.readline
@@ -124,7 +154,9 @@ def readline(self, size: int = - 1, /) -> str:
124154
raise OSError(f"File '{self._file.fileName()}' is not Readable.")
125155

126156
if self._file.atEnd():
127-
warnings.warn(f"Trying to read a line at the end of the file '{self._file.fileName()}'.")
157+
warnings.warn(
158+
f"Trying to read a line at the end of the file '{self._file.fileName()}'."
159+
)
128160
return ""
129161
else:
130162
if size == 0:
@@ -161,23 +193,9 @@ def readlines(self, hint: int = -1, /) -> list[str]:
161193

162194
return all_lines
163195

164-
def close(self):
165-
self._file.close()
166-
167-
168-
if __name__ == "__main__":
169-
with OpenQFile(b"./test.txt", "rt", encoding="gbk") as f:
170-
print(f.read(11))
171-
# print(f.readline())
172-
# lines = f.readlines()
173-
# print(lines)
174-
175-
print("-----------")
176-
177-
with open("./test.txt", "rt", encoding="gbk") as f:
178-
print(f.read(11))
179-
# print(f.readline())
180-
# lines = f.readlines()
181-
# print(lines)
196+
def close(self) -> None:
197+
"""
198+
关闭打开的文件对象
199+
"""
182200

183-
# f.read() # 离开 with 语句块后文件已经被关闭,无法再读
201+
self._file.close()

0 commit comments

Comments
 (0)