@@ -390,18 +390,14 @@ def _read(cls, fileobj, header, buffer_size=4):
390390 buffer_size = int (buffer_size * MEGABYTE )
391391 buffer_size += coordinate_size - (buffer_size % coordinate_size )
392392
393- # Markers for streamline end and file end
394- fiber_marker = cls .FIBER_DELIMITER .astype (dtype ).tostring ()
395- eof_marker = cls .EOF_DELIMITER .astype (dtype ).tostring ()
396-
397393 with Opener (fileobj ) as f :
398394 start_position = f .tell ()
399395
400396 # Set the file position at the beginning of the data.
401397 f .seek (header ["_offset_data" ], os .SEEK_SET )
402398
403399 eof = False
404- buffs = []
400+ leftover = np . empty (( 0 , 3 ), dtype = '<f4' )
405401 n_streams = 0
406402
407403 while not eof :
@@ -411,37 +407,36 @@ def _read(cls, fileobj, header, buffer_size=4):
411407 if eof :
412408 buff = buff [:n_read ]
413409
414- buffs .append (buff )
415-
416- # Make sure we've read enough to find a streamline delimiter.
417- if fiber_marker not in buff :
418- # If we've read the whole file, then fail.
419- if eof :
420- # Could have minimal buffering, and have read only the
421- # EOF delimiter
422- buffs = [bytearray ().join (buffs )]
423- if not buffs [0 ] == eof_marker :
424- raise DataError (
425- "Cannot find a streamline delimiter. This file"
426- " might be corrupted." )
427- else :
428- # Otherwise read a bit more.
429- continue
430-
431- all_parts = bytearray ().join (buffs ).split (fiber_marker )
432- point_parts , buffs = all_parts [:- 1 ], all_parts [- 1 :]
433- point_parts = [p for p in point_parts if p != b'' ]
434-
435- for point_part in point_parts :
436- # Read floats.
437- pts = np .frombuffer (point_part , dtype = dtype )
438- # Convert data to little-endian if needed.
439- yield pts .astype ('<f4' , copy = False ).reshape ([- 1 , 3 ])
440-
441- n_streams += len (point_parts )
442-
443- if not buffs [- 1 ] == eof_marker :
444- raise DataError ("Expecting end-of-file marker 'inf inf inf'" )
410+ raw_values = np .frombuffer (buff , dtype = dtype )
411+
412+ # Convert raw_values into a list of little-endian triples (for x,y,z coord)
413+ coords = raw_values .astype ('<f4' , copy = False ).reshape ((- 1 , 3 ))
414+
415+ # Find stream delimiter locations (all NaNs)
416+ delims = np .where (np .isnan (coords ).all (axis = 1 ))[0 ]
417+
418+ # Recover leftovers, which can't have delimiters in them
419+ if leftover .size :
420+ delims += leftover .shape [0 ]
421+ coords = np .vstack ((leftover , coords ))
422+
423+ begin = 0
424+ for delim in delims :
425+ pts = coords [begin :delim ]
426+ if pts .size :
427+ yield pts
428+ n_streams += 1
429+ begin = delim + 1
430+
431+ # The rest becomes the new leftover.
432+ leftover = coords [begin :]
433+
434+ if not (leftover .shape == (1 , 3 ) and np .isinf (leftover ).all ()):
435+ if n_streams == 0 :
436+ msg = "Cannot find a streamline delimiter. This file might be corrupted."
437+ else :
438+ msg = "Expecting end-of-file marker 'inf inf inf'"
439+ raise DataError (msg )
445440
446441 # In case the 'count' field was not provided.
447442 header [Field .NB_STREAMLINES ] = n_streams
0 commit comments