Jump to content
  • Advertisement
Sign in to follow this  
Boooke

Copy .txt data to another .txt file

This topic is 2396 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I do not really figure how to solve this problem. I am to make a database in a text file, and I would like to delete specific users in the file without affecting the rest of the file. To do so, I read the user list into a copied text file (Which seems to work somewhat fine), until I find the specific "ID" i want to delete. From here I continue to read the input file but avoid copying it over to the other text-file. It should then stop doing this when it finds another ID tag, but this seems to fail, Also, I want to copy the copied text file back to the original file because of the orignal filename is needed. Here it seems to fail, and the only output copied is "0x28fad4".





This is the function

void erase(std::string ID)
{
std::ifstream inFile("userlist.txt");
std::ofstream outCopy("copy.txt");
std::string buffer;
bool copyDone = false;
while (getline(inFile, buffer))
{
if (buffer == ("ID: " + ID))
{
while (getline(inFile, buffer) && buffer != "ID: ");
copyDone = true;
buffer.clear();
std::cout << "ID Found. Deleting user.";
}
outCopy << buffer;
std::cout << buffer << std::endl;
}
if (copyDone == false)
{
std::cout << "ID not present in userlist.";
outCopy.close();
inFile.close();
remove("copy.txt");
return;
}
inFile.close();
outCopy.close();
inFile.open("copy.txt");
outCopy.open("userlist.txt", std::ios::trunc);
if (outCopy.good())
std::cout << "Hej.";
outCopy << inFile;
inFile.close();
outCopy.close();
//remove("copy.txt");
}


here is userlist.txt, where ID: 111d should be deleted

Hello.
ID: 111d
Test.
ID: 202d
Should be kept safe from harm.


The copy.txt where everything concerning ID: 111d should have been removed ,but not IDs after,

Hello.

The userlist.txt after erase(string) now only contain,

0x28fad4



I guess the read loop inside the first while loop needs another condition, and the way I try to copy input from inFile to inCopy do not work, but I thought it could have been interesting to know, if it was possible to copy from the copied text back again without getline().

Regards,
Boooke

Share this post


Link to post
Share on other sites
Advertisement
Im not sure if this is the issue but it appears that you are clearing the buffer then latter attempting to write the empty buffer when you find the ID you are looking for.

if (buffer == ("ID: " + ID))
{
while (getline(inFile, buffer) && buffer != "ID: ");
copyDone = true;
buffer.clear();
std::cout << "ID Found. Deleting user.";
}
outCopy << buffer;
std::cout << buffer << std::endl;



Did you mean to put the second part inside an else block?
outCopy << buffer;
std::cout << buffer << std::endl;

Share this post


Link to post
Share on other sites
Yeah, I actually looked at that and it seemed at bit wrong, but I wasn't sure. It would be a good idea to put it into an else-statement. Thank you for the tip! I completely forgot about that one. But I still do not figure how I faulted the copy-section.

Share this post


Link to post
Share on other sites


if (buffer == ("ID: " + ID))
{


C++ doesn't do native string concatenation like one would expect:

int main() {
const char* str = "Test: " + 3; // Pointer arithmetic, not concatenation
cout << '"' << str << '"' << endl;
}

Output:
"t: "

The C++ way would probably look something like this:

istringstream ss( buffer );
string prefix, extra;
int value;
ss >> prefix >> value;
getline( ss, extra );
if ( ss && prefix == "ID:" && extra.empty() ) {
// Do something with value
} else {
// Error
}

Share this post


Link to post
Share on other sites
Given that you appear to require the database to fit in memory, I would recommend reading the database just once at startup. Read it into a record type. When changes are made to the database, add or remove these records from the collection in memory, and then write the data from memory to the file*.
This will be easier than writing multiple routines that trying to add or remove records while streaming the text from the file. It also separates the structure of the file from the logic - you can change the loader / saver without having to modify the way adding, removing, searching or sorting is done internally.


* How and when to write the data depends on how much you care about the data:

  • If you don't care (e.g. test program), you can just write the data when the user quits the program.
  • If you care a little bit about data, write changes immediately after any non-read operation.
  • If you moderately care about data, it is better to write the data to a temporary file first, and use an atomic rename to "replace" the file once you are sure it has been written correctly to disk.
  • If you really care about data loss, you'll use an ACID database to store it.


    You don't need to explicitly close std::fstreams. You shouldn't re-use them, as you would need to account for the various error reporting flags. For example, if your streams become invalid (e.g. the filesystem becomes full or some other program has obtained a lock on the file), then you will lose all data in the file. You need much more careful error handling to avoid data loss and corruption.

    [edit: I misread your code. You don't appear to require the data to fit into memory. Still, consider the above points]

Share this post


Link to post
Share on other sites
The plan is to read everything into a dynamic struct at some point. In the beginning would be a good idea. Maybe it would be much quicker to just edit the struct element that needs to be editted and then rewrite the whole "database", instead of having to edit the .txt and then read to the struct? Gonna try that, at least.

I know little of database-structuring. However, I will write the data to a copy.txt every time I change it in the struct and then I will read the copy to the now erased userlist.txt.. I am not sure if that is what you meant. But thank you for the ACID-model idea. If I have time, it would be a great idea to implement, also for exercising use in real projects.

I guess a lot of the erase() function i made is now inefficient, but the parts I need are actually still defunct, since I copying from text to text seems to give me some problems with the input.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!