Skip to content

Commit d671176

Browse files
committed
Support automatically adapting to set the encoding format according to the IO stream when performing IO operations on file; Update file:Add encoding data to property<info> of class<File>.
1 parent 58e542d commit d671176

File tree

4 files changed

+62
-29
lines changed

4 files changed

+62
-29
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pip install easierfile
2121
## 🔗Dependencies
2222

2323
- [Dynoptimdict - A dynamic data dict class that inherits and overrides the built-in dict class for special purposes. That provides real-time access to dynamic data, while still allowing the option to get only the specified data without calculating all. It adheres to the concept of program optimization which avoids loading if not used, saving both memory and time](https://github.com/leoweyr/Python-Dynoptimdict)
24+
- [Chardet - The universal character encoding detector](https://github.com/chardet/chardet)
2425

2526
## ⚖️License
2627

doc/API reference.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,14 @@ File(file_path, is_auto_create, is_occupy)
2121
</tr>
2222
<tr>
2323
<td><code>File().info</code></td>
24-
<td>Return a dict of file attribute information.</br>● path: the absolute path of the file</br>● dir_path: the absolute path of the directory where the file is located</br>● full_name: the name of the file</br>● name: the name of the file without file extension</br>● ext: the extension of the file</td>
24+
<td>Return a dict of file attribute information.</br>● path: the absolute path of the file</br>● dir_path: the absolute path of the directory where the file is located</br>● full_name: the name of the file</br>● name: the name of the file without file extension</br>● ext: the extension of the file</br>● encoding: the encoding of the file</td>
2525
</tr>
2626
<tr>
2727
<td><code>File().status</code></td>
2828
<td>Return a dict of file status information.</br>● file_lock: whether file lock is on</br>● exist: whether the file exist</td>
2929
</tr>
3030
</table>
3131

32-
33-
3432
### Operation
3533

3634
#### File().create()

easierfile/file.py

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,19 @@ def _unlock_file(file):
2121

2222

2323
import os
24-
from dynoptimdict import DynamicDataDict as Dict
24+
from dynoptimdict import DynamicDict
25+
import chardet
26+
2527

2628
class File:
2729
def __init__(self, file_path, is_auto_create=True, is_occupy=True):
2830
# Get static file information.
29-
self.__m_info = {}
30-
self.__m_info["path"] = os.path.abspath(file_path)
31-
self.__m_info["dir_path"] = os.path.dirname(self.__m_info["path"])
32-
self.__m_info["full_name"] = os.path.basename(self.__m_info["path"])
33-
self.__m_info["name"], self.__m_info["ext"] = os.path.splitext(self.__m_info["full_name"])
34-
self.__m_info["ext"] = self.__m_info["ext"].split(".")[-1] # Format ext of info to remove str<.>.
31+
self.__m_static_info = {}
32+
self.__m_static_info["path"] = os.path.abspath(file_path)
33+
self.__m_static_info["dir_path"] = os.path.dirname(self.__m_static_info["path"])
34+
self.__m_static_info["full_name"] = os.path.basename(self.__m_static_info["path"])
35+
self.__m_static_info["name"], self.__m_static_info["ext"] = os.path.splitext(self.__m_static_info["full_name"])
36+
self.__m_static_info["ext"] = self.__m_static_info["ext"].split(".")[-1] # Format ext of info to remove str<.>.
3537

3638
self.__m_is_occupy = is_occupy
3739
self.__m_is_lock = False # Initialize file lock state.
@@ -56,7 +58,7 @@ def __del__(self):
5658
def __lock(self, is_lock):
5759
if self.status["exist"]:
5860
if is_lock:
59-
self.__m_file = open(self.__m_info["path"])
61+
self.__m_file = open(self.__m_static_info["path"])
6062
_lock_file(self.__m_file)
6163
self.__m_is_lock = is_lock
6264
else:
@@ -65,70 +67,101 @@ def __lock(self, is_lock):
6567
self.__m_is_lock = is_lock
6668
else:
6769
if is_lock:
68-
raise FileNotFoundError("File was about to be occupied, but not found: " + self.__m_info["path"])
70+
raise FileNotFoundError("File was about to be occupied, but not found: " + self.__m_static_info["path"])
6971
else:
70-
raise FileNotFoundError("File was about to be unoccupied, but not found: " + self.__m_info["path"])
72+
raise FileNotFoundError("File was about to be unoccupied, but not found: " + self.__m_static_info["path"])
7173

7274
def create(self):
7375
if not self.status["exist"]:
74-
if not os.path.exists(self.__m_info["dir_path"]): # Create the file directory if it doesn't exist, so that code<open()> doesn't throw the exception.
75-
os.mkdir(self.__m_info["dir_path"])
76+
if not os.path.exists(self.__m_static_info["dir_path"]): # Create the file directory if it doesn't exist, so that code<open()> doesn't throw the exception.
77+
os.mkdir(self.__m_static_info["dir_path"])
7678
try:
77-
file_temp = open(self.__m_info["path"], "x")
79+
file_temp = open(self.__m_static_info["path"], "x")
7880
except FileExistsError: # Avoid exception caused by creating corresponding file in other ways during program execution intervals.
7981
pass
8082
else:
8183
file_temp.close()
8284
if self.__m_is_occupy:
8385
self.__lock(True)
8486
else:
85-
raise FileExistsError("File exists: " + self.__m_info["path"])
87+
raise FileExistsError("File exists: " + self.__m_static_info["path"])
8688

8789
def delete(self):
8890
if self.__m_is_lock:
8991
self.__lock(False)
9092
if self.status["exist"]:
91-
os.remove(self.__m_info["path"])
93+
os.remove(self.__m_static_info["path"])
9294

9395
def rewrite(self,content):
9496
if self.status["exist"]:
95-
file_temp = open(self.__m_info["path"], "w")
97+
"""
98+
Automatically obtain the most suitable encoding format for the input content.
99+
100+
:samp: chardet.detect(content.encode())["encoding"]
101+
"""
102+
file_temp = open(self.__m_static_info["path"], "w", encoding=chardet.detect(content.encode())["encoding"])
96103
file_temp.write(content)
97104
file_temp.close()
98105
else:
99-
raise FileNotFoundError("File not found: " + self.__m_info["path"])
106+
raise FileNotFoundError("File not found: " + self.__m_static_info["path"])
100107

101108
def append(self,content):
102109
if self.status["exist"]:
103-
file_temp = open(self.__m_info["path"], "a")
110+
file_temp = open(self.__m_static_info["path"], "a", encoding=chardet.detect(content.encode())["encoding"])
104111
file_temp.write(content)
105112
file_temp.close()
106113
else:
107-
raise FileNotFoundError("File not found: " + self.__m_info["path"])
114+
raise FileNotFoundError("File not found: " + self.__m_static_info["path"])
108115

109116
@property
110117
def content(self):
111118
if self.status["exist"]:
112-
file_temp = open(self.__m_info["path"], "r")
119+
"""
120+
Automatically obtain the most suitable encoding format for the output content.
121+
122+
:samp: self.info["encoding"]
123+
124+
In fact, it gets the encoding format of the read file.
125+
"""
126+
file_temp = open(self.__m_static_info["path"], "r", encoding=self.info["encoding"])
113127
content = file_temp.read()
114128
file_temp.close()
115129
return content
116130
else:
117-
raise FileNotFoundError("File not found: " + self.__m_info["path"])
131+
raise FileNotFoundError("File not found: " + self.__m_static_info["path"])
118132

119133
@property
120134
def info(self):
121-
return self.__m_info
135+
# Get dynamic file information.
136+
def get_info_encoding():
137+
file_temp = open(self.__m_static_info["path"],'rb')
138+
encoding = chardet.detect(file_temp.read())["encoding"]
139+
file_temp.close()
140+
return encoding
141+
142+
info = DynamicDict()
143+
144+
# Store static file information directly.
145+
info["path"] = self.__m_static_info["path"]
146+
info["dir_path"] = self.__m_static_info["dir_path"]
147+
info["full_name"] = self.__m_static_info["full_name"]
148+
info["name"] = self.__m_static_info["name"]
149+
info["ext"] = self.__m_static_info["ext"]
150+
151+
# Store the acquisition way of dynamic file information.
152+
info["encoding"] = get_info_encoding
153+
154+
return info
122155

123156
@property
124157
def status(self):
125158
def get_status_file_lock():
126159
return self.__m_is_lock
127160

128161
def get_status_exist():
129-
return os.path.isfile(self.__m_info["path"])
162+
return os.path.isfile(self.__m_static_info["path"])
130163

131-
status = Dict()
164+
status = DynamicDict()
132165
# Pass function pointers for obtaining dynamic data into object:Dict<status>.
133166
status["file_lock"] = get_status_file_lock
134167
status["exist"] = get_status_exist

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "easierfile"
3-
version = "2.2.0"
3+
version = "2.3.0"
44
description = "An easier-to-use Python package that object-oriented encapsulates Python traditional built-in file operations."
55
license = "MIT"
66
authors = ["leoweyr <[email protected]>"]
@@ -14,7 +14,8 @@ packages = [{include = "easierfile"}]
1414

1515
[tool.poetry.dependencies]
1616
python = "^3.8"
17-
dynoptimdict = "^1.0.0"
17+
dynoptimdict = "^2.0.0"
18+
chardet = "^5.1.0"
1819

1920

2021
[build-system]

0 commit comments

Comments
 (0)