Regenerate a Winzip
--C flow technology object-oriented object analysis and design
*********************************************************** *******************
Object-oriented analysis (OOA) and programming (OOP) technology have been mature, but now, many programmers still can't actively apply object-oriented ideas to design and develop software. In this article, I will introduce the programmer how the programmer is designed with OOA and OOP in the development and design process of file segmentation and merge tool.
One function concept and overall implementation
Before designing a software, be sure to find what kind of functionality is available. The main idea of design file segmentation merge tool begins with a large file into small pieces to facilitate transmission, and it can be merged if necessary. I use this tool software to use UML as follows:
Figure 1 case example of system
It can be seen that the function of this tool software is almost exactly the same as Winzip.
The function is determined to consider the system design problem. It should be pointed out that different software systems are different, and its design phase is different. For now this gadget software, it can be considered directly to achieve its implementation technology.
In C / C , the file is regarded as a byte stream, and provides several ways to operate the file:
L C language: open and close files with fopen (), fclose (), then, then process the byte stream directly in memory;
l STL mode: use the Iostream class in the standard template library (STL);
l The class provided by the specific development environment: CFILE, CMEMFILE, etc. in VC;
The C language does not meet the OOP style, the STL is powerful, but the development effort in this example is relatively large. The development tool I use is C Builder, and the TSTREAM class is also able to meet the requirements, so it is used to develop this software from the actual number of VCL class libraries.
From the system function, it is clear that the basic operation function of the stream must be provided first, and the FileStreamopt class is designed to complete these functions for this purpose of opening, merge, extraction, etc. The interface of the FileStreamopt class is shown below:
Class FileStreamopt
{
PUBLIC:
__fastcall filestreamopt (); // Constructor
__fastcall ~ filestreamopt (); // Destructor
/ / Open the stream according to the specified file name and open mode
TFileStream * __fastcall OpenFileStream (String FileName, String OpenMode);
// Close a stream
Void __fastcall closeestream (TSTREAM * PSTREAM);
/ / Add a stream PStreamsecond to the tail of a stream PStreamFirst
BOOL __FASTCALL APPENDSTREAM (TSTREAM * PSTREAMFIRST, TSTREAM * PSTREAMSECOND);
// Extract the flow content of the Size byte starting from BeGin to store the file newfilename
BOOL __FASTCALL ExtractStream (TSTREAM * PSTREAM, STRING NewFileName, Int Begin, Int Size, Bool overcover;
// Remove the size byte starting in the stream PStream
BOOL __FASTCALL CUTOUTSTREAM (TSTREAM * PSTREAM, INT BEGIN, INT Size);
It should be pointed out that in order to achieve versatility, the interface uses the flow base type pointer parameter TSTREAM *, so that the result of these functions can be used for all subclasses of the TSTREAM class.
Data structure
Since a number of files in a file is stored, it is clear that there must be a data structure to save the information about the file, and the easiest thing to think is to define a Struct, then write this structure to the file. But more reasonable is to generate a file information class (FileInfo). The interface is as follows:
Class fileInfo: Public Tcomponent
{
Private:
String ffilename;
Int ffilesize;
Bool FneedMerge;
Int fmergeno;
Int fmergeTotaNum;
String ffilepath;
PUBLIC:
__fastcall fileinfo (tcomponent * aowner);
FileInfo & Operator = (fileInfo & a);
__publish:
//file name
__property string filename = {read = fFilename, Write = ffilename};
//file path
__property string filepath = {read = ffilepath, Write = ffilepath};
//File size
__property int filesize = {read = ffilesize, write = ffilesize};
// Do you need a merger. That is, this is a split file.
__Property Bool NeedMerge = {Read = FneedMerge, Write = FneedMerge};
// A total number of files can be divided.
__Property Int MergetotaNum = {Read = FMergetotaNum, Write = FmergeTotalNum};
// To merge file file sequence number
__Property Int Mergeno = {Read = Fmergeno, Write = fMergeno};
}
An instance of a FileInfo class (object) corresponds to a file stream object. When saving the file package, all fileInfo objects in the package are written in a package file, and the number of objects in the previous write object (the total number of files included in the package, the INT type), which is the actual data of each file. When opening a file package, first read the first int data, then a loop, read all fileInfo object data, rebuild these objects in memory.
Each file stream in the package forms a file package in order to form a file package, and each file can be calculated by the order in the file in the package and the size of all files before it.
In this way, when the software runs, the deduplication file is reflected in the insertion and deletion of the file stream for the file stream.
Now there is a problem now: How do these FileInfo objects? Do you want to define an array or a list? The most suitable method is to select the container provided by STL - List and Vector:
l Vector: Dynamic array, the disadvantage is to move the rest of the elements when adding and deleting elements in the middle, and the efficiency is not as high as LIST;
l List: Increase the deletion element very fast, but does not support random storage, if you want to access the element according to a serial number, you must start from the beginning, or with a Find () method. In my software, if you always increase the file in the end of the vector, you will not have a problem with the mobile object. Of course, you need to move the elements in the container when you delete the file, but this is not the most commonly used operation, and the file stored in a file will not be too much. The time spent on the delete file is mainly on the file flow activity instead of the vector internal element. Mobile, so I finally decided to use the Vector management of the fileInfo object, so that this file can be used in the file in the container with a file corresponding to a file.
It is worth noting that the STL requires a custom object to be overloaded to assign the operator, so I overloaded the "=" operator in the FileInfo class.
FileInfo & fileInfo :: Operator = (fileinfo & a)
{
// Overloaded assignment operator
// Note: In order to avoid errity errors when compiling,
/ / To set the return value and the parameters to reference
FFileName = a.filename;
FFilePath = a.filepath;
FFileSize = a.filesize;
FMergeno = a.mergeno;
FMergetotaNum = a.mergetotalnum;
FNEEDMERGE = a.needmerge;
RETURN * THIS;
}
The following considerations of the storage problem of Fileinfo objects: In the single document structure of the MFC, you can store objects in the stream with "<<" and ">>", but I don't use the MFC framework in BCB, of course, I can Define a class that is inherited by STL to implement this feature. In fact, the READComponent () and WriteComponent () methods have implemented in the base class of all current objects of TSTREAM, so as long as the FileInfo object is inherited Tcomponent, this object can be saved to the stream, and now you can write additional code.
It should be pointed out that the information that needs to be saved must be designed in the BCB in the PROPERTY, put it in the Published section, for data members in the public part, WriteComponent () does not save its value, this seems not very cool, but this Is it a inevitable price of something that I want to use someone else's packing, isn't it? Fortunately, this is more than yourself to write a similar method.
With a fileinfo class to represent a file information, enhance the scalability of the program, I only need to increase the data member to add new information, such as adding a file attribute and a description information for each file, It does not have to change, none of its preservation and reading code, nor does it consider the size of the size when writing files, this Borland's programmer has taken into account when designing readcomponent () and WriteComponent () methods.
Three Design Functions: FileCutmerge This class implements the basic function of the software, its interface is as follows: typedef std :: vector
Class Filecutmerge: Public Tcomponent
{
Private:
// Operating stream object pointer
FileStreamopt * pstreamopt; // Current File Package
TFileStream * ppackage;
// Total to point to the file information object
FileInfo * pinfo;
// Container pointer for saving file information objects
Fileinfos * pvector;
// The total number of files in the current package
Int filenum;
// Pointer starting with file content
Int filebegin;
// File package file name
String pkgfilename;
PUBLIC:
// Get the distance of the specified file stream and the file package in the file package
INT __fastcall getfileoffset (unsigned int num);
// Class constructor 1
__fastcall filecutmerge (String PackageFileName, Bool Needcreate, Tcomponent * aowner);
// Add a function to the package
BOOL __FASTCALL AddFile (String filename);
// classification function
__fastcall ~ filecutmerge ();
/ / Get the number of files in the file package
INT __fastcall getfilenum ();
/ / Get the fileInfo object of the specified file in the package
FileInfo * __fastcall getfileinfo (unsigned int num);
// Expand the specified file to disk
BOOL __FASTCALL Extractfile (unsigned int num, string path, bool overcover);
// Expand all files
BOOL __FASTCALL ExtractAllFiles (String Path, Bool overcover);
/ / Delete a file
Bool __fastcall deleteafile (unsigned int No);
// Split the file package
Bool __fastcall splitfile (String FileName, String Path, INT Size);
// Rehabilize the divided file package
Bool __fastcall mergefile; "); String MergeFileName;
// Read the file package file size
INT __fastcall getpackagesize ();
// Class constructor 2
__fastcall filecutmerge (tcomponent * oowner);
// Open a file package
Bool __fastcall openpackage (string packagefilename); Bool Needcreate;
// Create a new file package
Bool __fastcall newpackage (String packagefilename);
/ / Package file name
__property string packagefilename = {read = pkgfilename, Write = pkgfilename};
// store the package file into the disk
BOOL __FASTCALL SAVEPACKAGETODISK ();
}