3131from .sqlite import SqliteReader
3232from .trc import TRCReader
3333
34+ try :
35+ import pyzstd
36+ except ImportError :
37+ pyzstd = None
38+
39+
3440#: A map of file suffixes to their corresponding
3541#: :class:`can.io.generic.MessageReader` class
3642MESSAGE_READERS : Final [Dict [str , Type [MessageReader ]]] = {
@@ -81,7 +87,16 @@ def _decompress(
8187
8288 mode = "rb" if issubclass (reader_type , BinaryIOMessageReader ) else "rt"
8389
84- return reader_type , gzip .open (filename , mode )
90+ if suffixes [- 1 ] == ".gz" :
91+ decompressor = gzip .open (filename , mode )
92+ elif suffixes [- 1 ] == ".zst" and pyzstd is not None :
93+ decompressor = pyzstd .open (filename , mode )
94+ else :
95+ raise ValueError (
96+ f"Unknown compression type { suffixes [- 1 ]} in { filename } , maybe a dependency is missing?"
97+ )
98+
99+ return reader_type , decompressor
85100
86101
87102def LogReader (filename : StringPathLike , ** kwargs : Any ) -> MessageReader : # noqa: N802
@@ -98,7 +113,7 @@ def LogReader(filename: StringPathLike, **kwargs: Any) -> MessageReader: # noqa
98113 (optional, depends on `asammdf <https://github.com/danielhrisca/asammdf>`_)
99114 * .trc :class:`can.TRCReader`
100115
101- Gzip compressed files can be used as long as the original
116+ Gzip and Zstd compressed files can be used as long as the original
102117 files suffix is one of the above (e.g. filename.asc.gz).
103118
104119
@@ -125,7 +140,7 @@ def LogReader(filename: StringPathLike, **kwargs: Any) -> MessageReader: # noqa
125140
126141 suffix = pathlib .PurePath (filename ).suffix .lower ()
127142 file_or_filename : AcceptedIOType = filename
128- if suffix == ".gz" :
143+ if suffix == ".gz" or suffix == ".zst" :
129144 reader_type , file_or_filename = _decompress (filename )
130145 else :
131146 reader_type = _get_logger_for_suffix (suffix )
0 commit comments