@@ -53,6 +53,7 @@ TWeatherStation = class
5353 procedure CreateLookupTemp ;
5454 procedure ReadMeasurements ;
5555 procedure ReadMeasurementsBuf ;
56+ procedure ReadMeasurementsBufSL ;
5657 procedure ParseStationAndTemp (const line: string);
5758 procedure AddCityTemperatureLG (const cityName: string; const newTemp: int64);
5859 procedure SortWeatherStationAndStats ;
@@ -328,7 +329,7 @@ procedure TWeatherStation.ReadMeasurements;
328329 // Open the file for reading
329330 fileStream := TFileStream.Create(self.fname, fmOpenRead);
330331 try
331- streamReader := TStreamReader.Create(fileStream, 65536 * 2 , False);
332+ streamReader := TStreamReader.Create(fileStream, 65536 * 16 , False);
332333 try
333334 // Read and parse chunks of data until EOF -------------------------------
334335 while not streamReader.EOF do
@@ -355,7 +356,7 @@ procedure TWeatherStation.ReadMeasurementsBuf;
355356 index, lineCount: int64;
356357begin
357358
358- chunksize := 536870912 * 1 ;
359+ chunksize := 4194304 * 1 ;
359360
360361 // Open the file for reading
361362 fileStream := TFileStream.Create(self.fname, fmOpenRead);
@@ -432,12 +433,96 @@ procedure TWeatherStation.ReadMeasurementsBuf;
432433 end ;
433434end ;
434435
436+ procedure TWeatherStation.ReadMeasurementsBufSL ;
437+ var
438+ fileStream: TFileStream;
439+ strList: TStringList;
440+ streamReader: TStreamReader;
441+ buffer, trimmedBuffer: TBytes;
442+ bytesRead, totalBytesRead, chunkSize, lineBreakPos, chunkIndex,
443+ slIndex, lineCount: int64;
444+ begin
445+
446+ chunksize := 8192 * 1 ;
447+
448+ // Open the file for reading
449+ fileStream := TFileStream.Create(self.fname, fmOpenRead);
450+ SetLength(buffer, chunkSize);
451+ try
452+ strList := TStringList.Create;
453+ try
454+ totalBytesRead := 0 ;
455+ chunkIndex := 0 ;
456+ lineCount := 0 ;
457+
458+ // Read and parse chunks of data until EOF
459+ while totalBytesRead < fileStream.Size do
460+ begin
461+ // Read more bytes and keep track on bytes read
462+ bytesRead := fileStream.Read(buffer[0 ], chunkSize);
463+ Inc(totalBytesRead, bytesRead);
464+
465+ // Find the position of the last newline character in the chunk
466+ lineBreakPos := BytesRead;
467+ while (lineBreakPos > 0 ) and (Buffer[lineBreakPos - 1 ] <> Ord(#10 )) do
468+ Dec(lineBreakPos);
469+
470+ { Now, must ensure that if the last byte read in the current chunk
471+ is not a newline character, the file pointer is moved back to include
472+ that byte and any preceding bytes of the partial line in the next
473+ chunk's read operation.
474+
475+ Also, no need to update the BytesRead variable in this context because
476+ it represents the actual number of bytes read from the file, including
477+ any partial line that may have been included due to moving the file
478+ pointer back.
479+ Ref: https://www.freepascal.org/docs-html/rtl/classes/tstream.seek.html}
480+ if lineBreakPos < bytesRead then
481+ fileStream.Seek(-(bytesRead - lineBreakPos), soCurrent);
482+ { $IFDEF DEBUG}
483+ // Do something with the chunk here
484+ // Like counting line
485+ for index := 0 to lineBreakPos - 1 do
486+ if buffer[index] = Ord(#10 ) then
487+ lineCount := lineCount + 1 ;
488+ { $ENDIF DEBUG}
489+
490+ // Use TStringList and a sub-TBytes array up to lineBreakPos
491+ SetLength(trimmedBuffer, lineBreakPos);
492+ // Index 'n' is inclusive, so add 1 to the length
493+ Move(buffer[0 ], trimmedBuffer[0 ], Length(trimmedBuffer)); // Copy the bytes
494+ strList.Clear;
495+ strList.Text := ansistring(trimmedBuffer);
496+ for slIndex := 0 to strList.Count - 1 do
497+ self.ParseStationAndTemp(strList[slIndex]);
498+
499+ { $IFDEF DEBUG}
500+ // Display user feedback
501+ WriteLn(' Line count: ' , IntToStr(lineCount));
502+ WriteLn(' Chunk ' , chunkIndex, ' , Total bytes read:' , IntToStr(totalBytesRead));
503+ { $ENDIF DEBUG}
504+
505+ { $IFDEF DEBUG}
506+ // Increase chunk index - a counter
507+ Inc(chunkIndex);
508+ { $ENDIF DEBUG}
509+ end ;
510+ finally
511+ strList.Free;
512+ end ;
513+ finally
514+ // Close the file
515+ fileStream.Free;
516+ end ;
517+ end ;
518+
435519// The main algorithm
436520procedure TWeatherStation.ProcessMeasurements ;
437521begin
438522 self.CreateLookupTemp;
439523 self.ReadMeasurements;
440- // self.ReadMeasurementsBuf;
524+ // self.ReadMeasurementsBuf;
525+ // self.ReadMeasurementsBufSL;
441526 self.SortWeatherStationAndStats;
442527 self.PrintSortedWeatherStationAndStats;
443528end ;
0 commit comments