Project Iterative Development Instruction - Implementation Process of File Segmentation Storage Case (3)
After the iteration 2 was completed, we got a complete code of complete compressing function. This iteated completed code is available. We completed our established tasks in iteration 2. In a group discussion in the afternoon, we continue to consider the next stage iterative goal. Since there is no format of the file file, we decided not to consider the problem in the picture format, first implement the file segmentation function. The segmentation of the file is mainly to consider that the database submission performance becomes very slow when the file file file is too large, and the purpose of the segmentation is to improve the performance of the submitted.
Iteration 3:
Split the binary flow submitted to the database; then decompressed and spliced operations from the database extraction to obtain the original image file data.
Before the design and encoding of the segmentation function, we re-examined the morning code - that compressed class TloadBinaryDatatoDB, I found that this class seems to be duty, it is responsible for loading the file to stream, then compress and decompress the flow, we discovered The UncompressStream function has better versatility, as long as it is a compressed flow, it can be decompressed. The compression function seems to compress the stream loaded through the file, if the flow is obtained in another form, not in the form of file loading, then we do not know how to compress the flow. It seems to violate the functional single responsibility, and the class is responsible for the loading of the stream, also responsible for the compression of the stream; so we reacting the class with better structures to increase the reuse.
The reconstructed classes only two common methods CompressStream and UncompressStream they have flowed into parameters, and the compression and decompression functions are implemented by processing the incoming stream.
Procedure TcompressStream.com (Var Stream: TmemoryStream);
VAR
ISIZE: INTEGER;
LDestStream: TMemoryStream;
LCompressionStream: TcompressionStream;
Begin
LDestStream: = TMEMORYSTREAM.CREATE;
LCompressionStream: = TcompressionStream.create (CLmax, LDestStream);
Try
ISIZE: = stream.size; // Get the original size of the image stream
Stream.SaveTroupTream (LCompRessionsTream); // Compress the original image stream,
// LDestStream saves a compressed image stream
LCompRessionsTream.free;
stream.clear;
Stream.writeBuffer (isize, sizeof (isize)); // Write the size of the original image
Stream.copyFrom (LDestStream, 0); // Write a compressed image stream
Finally
LDestStream.free
END;
END;
Unzipped function
Procedure TcompressStream.uncompressstream (Var Stream: TmemoryStream);
VAR
DecompressionStream: TDECompRessionsTream;
Buffer: pchar;
Count: integer;
Begin
Stream.Readbuffer (Count, Sizeof (count);
GetMem (buffer, count); / / / / According to the size of the original image stream to be read, the original image stream to be read is allocated.
DecompressionStream: = TDECompressionStream.create (stream);
Try
DecompressionStream.readbuffer (buffer ^, count); // Replenish the compressed image,
/ / Then store into the buffer memory block
stream.clear;
Stream.WriteBuffer (buffer ^, count); // Save the original image stream to the Stream stream
Stream.position: = 0;
Finally
FreeMem (buffer); // Release memory
END;
END;
After repetitting, TcompressStream has undoubtedly increases reuse and has a better structure. After removing the function of loading the file, TcompressStream duties have become more silent. It can compress and decompress the streams obtained in any form. Complete TLOADBINARYDATATODB Refactoring We start considering the implementation of segmentation functionality.
In assumed a stream to be split into 5 copies, then there is a sequence we consider adding a segmentation in the database to save the segmentation order between the flow of each block.
Field Name Field Type Field Length Field Description
FID NUMBER
Primary key
F_name varchar2 50 file name
F_serial
Number
File segmentation sequence number
F_binary_data long row
Binary data
Similarly, we consider encapsulating this feature in a class. We have realized a class called TSTReamIncise. When designing this class, we have a good discussion for such a better increase in this class, first we simulate how to use this class.
For i: = 0 to incisedcount - 1 DO
Begin
StreamIncise.GetIncisesTream (LSTREAM); // Get split stream
ClientDataSet2.Append;
ClientDataSet2.fieldByname ('f_id'). Value: = i; // Urban sequence number
ClientDataSet2.fieldByName ('f_name'). Value: = ffilefullname
ClientDataSet2.fieldByname ('f_serial'). Value: = i; // Take the serial number of each split
LCompressionStream.comPressStream (LSTREAM);
(ClientDataSet2.fieldByname ('f_binary_data')
as tblobfield .loadfromstream (LSTREAM);
ClientDataSet2.post;
END;
We use code to estimate the way the class is called, and we have obtained the following information through such analog code.
1) To obtain the number of divisions of the file, if we use the above analog code, we must first get the number of divisions of the stream.
2) The TSTReamIncise stream gets the to process the stream before execution, and sets the size of the split block.
Figure:
We use FinciseSize to save the split size, the FStreamSize saves the size value of the stream, and the FremainSize saves the remainder of each split. FINCISESIZE initializes in the initialization function crete.
FINCISESIZE: = 50000; // Set the size of the segmentation
LoadFromstream overlooks the original stream.
Procedure TSTREAMINCISE.LOADFROMSTREAM (Stream: tmemorystream);
Begin
FMemoryStream: = stream; // Save a stream reference
FSTREAMSIZE: = stream.size;
Fremainsize: = fstreamsize;
GetIncisedCount gains the number of loaded raw streams.
Function TSTREAMINCISE.GETITICISEDCOUNT: Integer;
Begin
Result: = FStreamsize Div Fincisesize 1;
END;
SetStreamDefault is used to set the get stream to the initial location.
Procedure TStreamIncise.setstreamdefault;
Begin
IF assigned (fMemoryStream) Then fmemorystream.position: = 0;
END;
The core function is GetIncisesTream by calling its user to get a split stream.
Procedure TStreamIncise.getIncisesTream (Incisestream: TMemoryStream);
VAR
ImaxError: Integer;
Count: integer;
Buffer: pchar;
Begin
Count: = getBufferCount;
GetMem (buffer, count);
Try
FMemoryStream.readbuffer (buffer ^, count);
InciseStream.clear;
INCISESTREAM.WRITEBUFFER (Buffer ^, Count);
INCISESTREAM.POSITION: = 0;
FremainSize: = FremainSize - count
Finally
FreeMem (buffer);
END;
END;
Here GetBufferCount each time returns the size of the split block, when the remaining stream size is not 5000, it returns the length of the remaining stream.
Function TSTREAMINCISE.GETBUFFERCOUNT: Integer;
Begin
Result: = FINCISESIZE;
IF FremainSize Result: = FremainSize; END; In the end we got a division class that can be called: Procedure TFORM1.BUTTON8CLICK (Sender: TOBJECT); VAR StreamIncise: TSTREAMINCISE; I: integer; LSTREAM: TMEMORYSTREAM; LCompRESSIONSTREAM: TCompRessstream; Begin StreamIncise: = TSTREAMINCISE.CREATE LSTREAM: = TMEMORYSTREAM.CREATE LCompressionStream: = Tcompressstream.create; StreamIncise.LoadFromstream (FStream); StreamIncise.setstreamDefault; Try For i: = 0 to streamincise.incisedcount - 1 DO Begin StreamIncise.GetIncisesTream (LSTREAM); // Get split stream ClientDataSet2.Append; ClientDataSet2.fieldByname ('f_id'). Value: = i; // Urban sequence number ClientDataSet2.fieldByName ('f_name'). Value: = ffilefullname ClientDataSet2.fieldByname ('f_serial'). Value: = i; // Take each segmentation number LCompRessionsTream.comPressStream (LSTREAM); (ClientDataSet2.fieldByname ('f_binary_data') as tblobfield .loadfromstream (LSTREAM); ClientDataSet2.post; END; Finally StreamIncise.free; LSTream.free; LCompRessionsTream.free; END; END; Finally, we have added the InciseSize property, allowing programmers to modify the size of the split block after the creation class. With such a call, we can unlock the coupling of the segmentation class specific save service, thereby increasing the possibility of the segmentation class next reuse. In the process of checking the information, we also found some segmented examples, just coupling specific business coupling, reusing this code, except for paste replication, there is basically no doctor. Thus when it is completed, we realize the split compression of the flow, file segmentation storage case to get a good solution, through small iteration, we can get the functionality that can be used at each iteration. The code is left to consider the format of the file file. In fact, more importantly, through this development, we have made newly joined group members have achieved good programming training, making it easier to understand the specific ideas and steps to achieve a function.