@@ -20,16 +20,13 @@ TCityTemp = record
2020 numReadings: integer;
2121 end ;
2222
23-
2423implementation
2524
2625const
2726 READ_SIZE = 65536 ;
2827 // read size plus enough to hold one record if we split it
2928 BUFFER_SIZE = READ_SIZE + 1024 ;
3029 REC_SEP: char = ' ;' ;
31- LF: char = chr(10 );
32- ANSI_ZERO: integer = 48 ;
3330 DECIMAL_POINT: char = ' .' ;
3431 NEGATIVE_SIGN: char = ' -' ;
3532
@@ -45,7 +42,6 @@ procedure ProcessMeasurements(var buffer: array of char; bufferLength: integer;
4542 while idx < (bufferLength - 1 ) do
4643 begin
4744 // read the city until separator
48- // city := '';
4945 cityStart := idx;
5046 while buffer[idx] <> REC_SEP do Inc(idx);
5147 SetString(city, @buffer[cityStart], (idx - cityStart));
@@ -61,6 +57,7 @@ procedure ProcessMeasurements(var buffer: array of char; bufferLength: integer;
6157 // look ahead - is decimal point 2 spaces away then we have two digits
6258 if buffer[idx + 2 ] = DECIMAL_POINT then
6359 begin
60+ // this is the math that results from subtracting the byte value of ansi zero from each character
6461 temp := currentTempSign * (100 * byte(buffer[idx]) + 10 *
6562 byte(buffer[idx + 1 ]) + byte(buffer[idx + 2 ]) - 5328 );
6663 // move past digits and CRLF and position pointer to first character of next record
@@ -150,7 +147,6 @@ procedure DumpMeasurements(results: TFPHashList);
150147 weatherStationList: TStringList;
151148 isFirstKey: boolean = True;
152149begin
153- // WriteLn(results.Count);
154150 weatherStationList := TStringList.Create;
155151 for i := 0 to results.Count - 1 do
156152 begin
@@ -160,126 +156,68 @@ procedure DumpMeasurements(results: TFPHashList);
160156 mean := RoundEx(reading^.total / reading^.numReadings / 10 );
161157 readingStr := reading^.city + ' =' + FormatFloat(' 0.0' , min) +
162158 ' /' + FormatFloat(' 0.0' , mean) + ' /' + FormatFloat(' 0.0' , max);
163- { $IFDEF DEBUG}
164- readingStr := reading^.city + ' =' + FormatFloat(' 0.0' , min) +
165- ' /' + FormatFloat(' 0.0' , mean) + ' /' + FormatFloat(' 0.0' , max) +
166- ' /' + IntToStr(reading^.total) + ' /' + IntToStr(reading^.numReadings);
167- { $ENDIF}
168159 weatherStationList.Add(readingStr);
169160 Dispose(reading);
170161 end ;
171162 weatherStationList.CustomSort(@Compare);
172163 Write(' {' );
173164 for ws in weatherStationList do
174165 begin
175- // If it's not the first key, print a comma
176166 if not isFirstKey then
177167 Write(' , ' );
178- // Print the weather station and the temp stat
179168 Write(ws);
180- // Set isFirstKey to False after printing the first key
181169 isFirstKey := False;
182170 end ;
183171 WriteLn(' }' );
184172end ;
185173
186-
187- procedure DumpExceptionCallStack (E: Exception);
188- var
189- I: integer;
190- Frames: PPointer;
191- Report: string;
192- begin
193- Report := ' Program exception! ' + LineEnding + ' Stacktrace:' +
194- LineEnding + LineEnding;
195- if E <> nil then
196- begin
197- Report := Report + ' Exception class: ' + E.ClassName + LineEnding +
198- ' Message: ' + E.Message + LineEnding;
199- end ;
200- Report := Report + BackTraceStrFunc(ExceptAddr);
201- Frames := ExceptFrames;
202- for I := 0 to ExceptFrameCount - 1 do
203- Report := Report + LineEnding + BackTraceStrFunc(Frames[I]);
204- WriteLn(Report);
205- Halt; // End of program execution
206- end ;
207-
208-
209174procedure ReadMeasurements (inputFile: string);
175+ type
176+ TCharArray = array of char;
210177var
211- totalBytesRead, BytesRead: int64;
212- Buffer: array [ 0 ..BUFFER_SIZE] of char ;
178+ BytesRead: int64;
179+ buffer: TCharArray ;
213180 FileStream: TFileStream;
214- fileSize: int64;
215181 ReadBufferStream: TReadBufStream;
216- starttime: uint64;
217- elapsedTimeSec, MBRead: double;
218182 results: TFPHashList;
219- currentChar: char;
220183 idx: integer;
221184 startOfNextRecord: string;
222185 startOfNextRecordLength: integer;
223186 bufferLength: integer = 0 ;
224187begin
225188 try
189+ buffer := Default(TCharArray);
190+ SetLength(buffer, BUFFER_SIZE);
226191 FileStream := TFileStream.Create(inputFile, fmOpenRead);
227- FileStream.Position := 0 ; // Ensure you are at the start of the file
192+ FileStream.Position := 0 ;
228193 ReadBufferStream := TReadBufStream.Create(FileStream);
229- fileSize := FileStream.size;
230- totalBytesRead := 0 ;
231- starttime := GetTickCount64;
232194 results := TFPHashList.Create;
233195 startOfNextRecord := ' ' ;
234- while totalBytesRead <= fileSize do
235- // While the amount of data read is less than or equal to the size of the stream do
196+ while True do
236197 begin
237198 startOfNextRecordLength := Length(startOfNextRecord);
238- // WriteLn('startOfNextRecordLength: ', startOfNextRecordLength);
239199 // if we have leftover from previous read then prepend it to this buffer
240200 if startOfNextRecordLength > 0 then
241- Move(PChar(startOfNextRecord)^, Buffer[0 ], startOfNextRecordLength);
242- BytesRead := ReadBufferStream.Read(Buffer[startOfNextRecordLength], READ_SIZE);
243- // WriteLn('Bytes read: ', BytesRead);
201+ Move(PChar(startOfNextRecord)^, buffer[0 ], startOfNextRecordLength);
202+ BytesRead := ReadBufferStream.Read(buffer[startOfNextRecordLength], READ_SIZE);
244203 if BytesRead < 1 then break;
245204 // now look in buffer backwards until we find the first LF
246205 bufferLength := startOfNextRecordLength + BytesRead;
247206 idx := bufferLength - 1 ;
248- currentChar := buffer[idx];
249- while (currentChar <> LF) do
250- begin
251- Dec(idx);
252- currentChar := buffer[idx];
253- end ;
254- ProcessMeasurements(Buffer, idx + 1 , results);
255- startOfNextRecord := ' ' ;
207+ while (buffer[idx] <> REC_SEP) do Inc(idx);
208+ ProcessMeasurements(buffer, idx + 1 , results);
256209 startOfNextRecordLength := bufferLength - idx - 1 ;
257- // WriteLn('startOfNextRecordLength: ', startOfNextRecordLength);
258210 if startOfNextRecordLength > 0 then
259211 SetString(startOfNextRecord, @buffer[idx + 1 ], startOfNextRecordLength);
260- Inc(totalBytesRead, BytesRead);
261212 end ;
262213 DumpMeasurements(results);
263- elapsedTimeSec := (GetTickCount64() - starttime) / 1000 ;
264- MBRead := (totalBytesRead / (1024 * 1024 ));
265- { $IFDEF DEBUG}
266- WriteLn(inputFile);
267- WriteLn(' Buffer size: ' , SizeOf(Buffer));
268- WriteLn(' Read size: ' , READ_SIZE);
269- WriteLn(' File size: ' , FileStream.Size);
270- WriteLn(' Total Bytes Read: ' , totalBytesRead);
271- WriteLn(Format(' %f MB read' , [MBRead]));
272- WriteLn(Format(' %f secs' , [elapsedTimeSec]));
273- WriteLn(Format(' %f MB/s processed' , [MBRead / elapsedTimeSec]));
274- { $ENDIF}
275214 ReadBufferStream.Free;
276215 FileStream.Free;
277216 results.Free;
278217 except
279218 on E: Exception do
280219 begin
281220 writeln(' File ' , inputFile, ' could not be read or written because: ' , E.ToString);
282- DumpExceptionCallStack(E);
283221 end ;
284222 end ;
285223end ;
0 commit comments