Today, I want to write a small program that replaces a row of files in batches,
The initial idea is to operate directly in the file (not generate new files), so write the following code (operate on a single file)
- /*
- String m_strrepsrc; // The identifier string in the replaced line vc98/include/
String m_strrepdes; // string F:/program files/software/Microsoft Visual Studio 8/VC/include/
- Required results:
- "E:/program files/Microsoft Visual Studio/vc98/include/basetsd. H "/
- Change to ==>
- "F:/program files/software/Microsoft Visual Studio 8/VC/include/basetsd. H "/
- The basetsd. H "/requirements remain unchanged.
- */
- Bool creplace: Deal ()
- {
- // Open the file
- Cstdiofile hfile (m_strfilepath.c_str (), cfile: modereadwrite | cfile: sharedenywrite );
- // Search
- Cstring strtemp;
- Cstring newstr;
- Long iidx = 0;
- While (hfile. readstring (strtemp ))
- {
- Iidx = strtemp. Find (m_strrepsrc.c_str (); // If the row contains an identifier string, replace
- If (iidx! =-1)
- {
- // Obtain the replacement part;
- NewStr = strTemp. Right (strTemp. GetLength ()-iIdx-1-m_strRepSrc.length (); // basetsd. h "/
- // String to be replaced
- NewStr = CString (_ T ("/" ") + CString (m_strRepDes.c_str () + newStr + CString (_ T ("/n "));
- // Write back the file
- HFile. Seek (-2-strTemp.GetLength (), CFile: current); // locate the start position of the string to be replaced
- HFile. WriteString (newStr. GetBuffer ());
- NewStr. ReleaseBuffer ();
- }
- }
- HFile. Close ();
- Return true;
- }
Result 1 is not satisfactory because
"F:/Program Files/software/Microsoft Visual Studio 8/VC/include/basetsd. h"/length ratio
"E:/program files/microsoft visual studio/vc98/include/basetsd. h"/long
As a result, the content following "e:/program files/microsoft visual studio/vc98/include/basetsd. h"/in the file is overwritten.
Since
HFile. Seek (-2-strTemp.GetLength (), CFile: current );
HFile. WriteString (newStr. GetBuffer ());
Cause: hFile. ReadString is read back to the previous content, leading to an endless loop.
And the target file is increased several times (the previous content is written into)... Khan ====> I don't understand why the previous content is written into the file...
Conclusion: The content of a file cannot be directly replaced by a common method, unless it is the same as the length of the string to be replaced.
The same length can be achieved as follows
- LPos = hFile. GetPosition ();
- HFile. Seek (-2-strTemp.GetLength (), CFile: current );
- HFile. WriteString (newStr. GetBuffer ());
- Newstr. releasebuffer ();
- Hfile. Seek (LPOS, cfile: Begin );
Finally, in another way, read the file content into the memory, replace the file content in the memory, and write it back to the file...
The implementation is as follows:
- // Replace all strsrc in strbig with strdst
- Void creplace: string_replace (string & strbig, const string & strsrc, const string & strdst)
- {
- String: size_type Pos = 0;
- String: size_type srclen = strsrc. Size ();
- String: size_type dstlen = strdst. Size ();
- While (Pos = strbig. Find (strsrc, POS ))! = String: NPOs)
- {
- StrBig. replace (pos, srclen, strdst); // replace the srclen characters starting from the index pos with the strdst
- Pos + = dstlen;
- }
- }
- Bool CReplace: deal ()
- {
- Ifstream in (m_strFilePath.c_str ());
- Stringstream ss;
- Ss <in. rdbuf ();
- String s = ss. str ();
- // Size_type is of the unsigned type, which depends on the specific machine.
- String: size_type iIdx = 0;
- String: size_type iBegin, iEnd;
- IIdx = s. find (m_strRepSrc );
- If (iIdx! = String: npos)
- {
- IBegin = s. rfind ("/" ", iIdx );
- IEnd = iIdx + m_strRepSrc.size ();
- String sRep = s. substr (iBegin, iEnd-iBegin );
- // S. replace (sRep, m_strRepDes );
- String_replace (s, sRep, m_strRepDes );
- // Write back
- Ofstream out (m_strFilePath.c_str ());
- Out <s;
- // Out. close () is not required, and the out structure of the scope end will automatically close ()
- }
- In. close ();
- Return true;
- }