binary files / reading specific lines

Hi.

My program stores / writes text data to file. This data is also read by the program and by another 'administration - type' program. The data is written to specific lines in the file. Before the text is written, it is encrypted using a typical XOR method. The data is written and read in binary mode.

An example of what the text in the file look like:

1
2
3
4
001: User Data 1
002: User Data 2
...
...


My problem is reading the decrypted text 'correctly'. Note: Each line of text (excluding the line identify e.g. 002: ) is displayed in specific textBoxes in a windows form application.

I can encrypt the text and save this to file. I can also then decrypt this file but when I retrieve specific data using my line identifiers, I'm not getting just that data on a specific line. Instead, I'm getting a mixture of that line and others...

Here is the relevant code:

The following is found in 'Functions.h':

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
bool boolData1(const std::string & str);

string encryptor_decryptor(string toEncryptDecrypt) 
{
    char myKey = 'K';
    string encrypted_decrypted = toEncryptDecrypt;
    
    for (int i = 0; i < toEncryptDecrypt.size(); i++)
        encrypted_decrypted[i] = toEncryptDecrypt[i] ^ myKey;
    
    return encrypted_decrypted;
}

string encryptedString(string toBeEncrypted)
{
	string encrypted = encryptor_decryptor(toBeEncrypted);
	return (encrypted);
}

string decryptedString(string toBeDecrypted)
{
	string decrypted = encryptor_decryptor(toBeDecrypted);
	return (decrypted);
}

// decrypt, find line and place in appropriate textBox function
void fillTextBox(TextBox^ textBox){
	String^ str1;
	ifstream fin("C:\\userdata.txt", ios::binary | ios::in);
	{
		string str;
		while (getline(fin, str))
			if(boolData1(decryptedString(str)))	
			{
				string temp;
				temp = decryptedString(str);
				str1 = gcnew String(temp.substr(4).c_str());
			}
				textBox->Text = str1;
	}
	fin.close();
}


Found in Form1.h

1
2
3
4
5
6
7
8
9
// Convert String^ (info in textBox) to string
String^ textBoxInfo = textBox1->Text;
string strTextBoxInfo = msclr::interop::marshal_as<std::string>(textBoxInfo);
string encryptedProfile = encryptedString(strTextBoxInfo);

// Writes encrypted data to file.
ofstream file("C:\\userdata.txt", ios::binary | ios::out);
file2 << encryptedProfile;
file2.close();


Found in main.cpp:

1
2
3
4
bool boolData1(const std::string & str)
{
	return (str.find("001:") != string::npos);
}


Everything has been working fine until I have included the encryption / decryption function. As per my previous post, I have just started using ios::binary so I am assuming that my error lies here.

Looking forward to any advice!
Last edited on
Ok, I'm stumped!

I've spent all day trying to look for errors and try and solve the issue described above myself but I'm getting no where.... I've even tried to simply everything that I'm doing and it's still not working... No complie errors, just not decrypting the text correctly. I written a separate program (separate to the one I've been working on) which just encrypts and decrypts but no luck.

I read somewhere that using XOR with \r\n can cause issues. I've got rid of these, replacing them with \n but I've still coming up with the same issue.

For example: the word "Mathematics" after decryption is displayed as "Mfathemfatics".... This is using the encryption key 'k'.... Changing the key just mucks up some other letter combination elsewhere in the data that I'm collecting.

I need a beer, or three ;)

Any thoughts?
while (getline(fin, str))
If the file is encrypted then how will getline() know where the lines end?

You need to be careful when trying to write and read binary files if you want to have random access to the file or replace "text" in the middle of the file.

Normally binary files are written using the write() function, and read using the read() function.

When trying to replace an item in the middle of a file you need to know exactly where that item starts and exactly where that item ends. You then need to replace that item with exactly the same number of characters. If you write more characters than the original you will overwrite the next item. If you use too few you will leave part of the original in the file.

Next binary files normally don't have the problems with end of line characters, because everything is on one line. And when dealing with numeric values you write bytes not the "character representations". And normally you don't write a std::string directly to the stream, because they have a variable length. Lastly binary files are usually considered to be machine readable and not human readable.



Thanks dhayden and jlb for your replies.

I'm starting think that I need to take a different approach.

Essentially the file line numbering is there so that the program knows where to look for specific data and if necessary, write over the existing data. Up until I've got to the stage where I would like to encrypt / decrypt this data It has been working.

Forgive me if I'm wrong here as I've only been programming (regularly) for 6 - 9 months...

I get that a binary file has just the one line. Thus it would convert a '\n' - like character into a series of numbers based on the key that is used in the XOR encryption.

I'm thinking that two differnt appraoches to how my data is written may help. So far I have data like this in a txt file:
1
2
3
4
001: User data line 1
002: User data line 2
003: User data line 3
.....and so on.....


Option 1: Use something other than XOR encryption, or
Option 2: write my data so that is has a character that marks the end of that piece of data. For example, my data file would look like (before encryption):

001: User data line 1@002: User data line 2@003: User data line 3@..... and so on....

Where the '@' signifies the end of the piece of data.

This means that there are no \n characters which may help. The only thing I can see here reflects on what you said, jlb regarding reading / writing exactly the same number of characters... Writing the code to say repalce the piece of data that lies inbetween other data would be difficult.

How do these ideas sound?

Cheers,
Last edited on
Hi again,

I've had some success today after having a day's break. With the help of some other resources on the net, I've come up with something that works better than what I stated in my first post but I still have some questions...

This code is found in my Functions.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
bool boolData1(const std::string & str);

// This encrypts whatever is in temp2 and saves it in userdata.txt
void encrypyFile(string temp2)
{
	stringstream ss;
	ss.str(temp2);
	ofstream fout("C:\\userdata.txt");
	string myKey = "dog";

	int i = 0;
	char c;
	while (ss.get(c))
	{
		c += myKey[ i ];
		c -= myKey[ 0 ];
		fout << c;

		i++;
		i %= myKey.size();
	}
	fout.close();
	ss.str(std::string());
}

// This places contents of userdata.txt into a stringstream for which decryption is applied to
//, placing the decrypted information back into the appropriate textBox.

void fillTextBox(TextBox^ textBox)
{	
	ifstream fin("C:\\userdata.txt");
	string myKey = "dog";
	stringstream ss;

	int i = 0;
	char c;
	while (fin.get(c))
	{
		c += myKey[ 0 ];
		c -= myKey[ i ];
		ss << c;
		i++;
		i %= myKey.size();
	}

	String^ str1;
	string str;
	while (getline(ss, str))

		if(boolData1(str))
			str1 = gcnew String(str.substr(4).c_str());
	textBox->Text = str1;
	fin.close();
	ss.str(std::string());
}


This code is found in Form1.h:
1
2
3
4
5
6
7
	
// Converts String^ to std::string
String^ temp = textBox1->Text;
string temp2 = msclr::interop::marshal_as<std::string>(temp);

// Calls encryption function in Function.h
encryptProfile(temp2);


This code is found in main.cpp
1
2
3
4
bool boolData1(const std::string & str)
{
	return (str.find("001:") != string::npos);
}



So this works for the encrpytion key 'dog', but not 'cat'. That is data is lost when 'cat' is used. XOR isn't used here so this tells me that \t, \n and \r are being mixed up somehow (I'm sure there's a more technically correct word to use here)...

Anyway, is there a way to exclude charaters \t, \n and \r in the above encryption method? And would this work?

Cheers,
Last edited on
Topic archived. No new replies allowed.