3131from .trc import TRCReader
3232from .pcapng import PcapngReader
3333
34+
35+ try :
36+ import pyzstd
37+ except ImportError :
38+ pyzstd = None
39+
40+
3441#: A map of file suffixes to their corresponding
3542#: :class:`can.io.generic.MessageReader` class
3643MESSAGE_READERS : Final [Dict [str , Type [MessageReader ]]] = {
@@ -81,7 +88,16 @@ def _decompress(
8188
8289 mode = "rb" if issubclass (reader_type , BinaryIOMessageReader ) else "rt"
8390
84- return reader_type , gzip .open (filename , mode )
91+ if suffixes [- 1 ] == ".gz" :
92+ decompressor = gzip .open (filename , mode )
93+ elif suffixes [- 1 ] == ".zst" and pyzstd is not None :
94+ decompressor = pyzstd .open (filename , mode )
95+ else :
96+ raise ValueError (
97+ f"Unknown compression type { suffixes [- 1 ]} for file { filename } , maybe a dependency is missing?"
98+ )
99+
100+ return reader_type , decompressor
85101
86102
87103def LogReader (filename : StringPathLike , ** kwargs : Any ) -> MessageReader : # noqa: N802
@@ -98,7 +114,7 @@ def LogReader(filename: StringPathLike, **kwargs: Any) -> MessageReader: # noqa
98114 (optional, depends on `asammdf <https://github.com/danielhrisca/asammdf>`_)
99115 * .trc :class:`can.TRCReader`
100116
101- Gzip compressed files can be used as long as the original
117+ Gzip and Zstd compressed files can be used as long as the original
102118 files suffix is one of the above (e.g. filename.asc.gz).
103119
104120
@@ -125,7 +141,7 @@ def LogReader(filename: StringPathLike, **kwargs: Any) -> MessageReader: # noqa
125141
126142 suffix = pathlib .PurePath (filename ).suffix .lower ()
127143 file_or_filename : AcceptedIOType = filename
128- if suffix == ".gz" :
144+ if suffix == ".gz" or suffix == ".zst" :
129145 reader_type , file_or_filename = _decompress (filename )
130146 else :
131147 reader_type = _get_logger_for_suffix (suffix )
0 commit comments