read a binary file and place into a linked list

I have an assignment that asks me to create a program that when executed will read a binary file and place the information into an ordered linked list. The user can then manipulate the information stored. Then the user can the save the information back to the binary file.

I am having trouble understanding how to put the information of a binary file into and ordered list and then save that information back to the binary file when it is complete. My code here still needs to be cleaned up and worked on some more, however it works as needed otherwise. I just need help with the binary I/O.

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
  //playlist.h
#ifndef PLAYLIST_H
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

class PlaylistNode
{
public:
	PlaylistNode();

	PlaylistNode(string id, string songname, string artist);

	void InsertAfter(PlaylistNode* ptr);
	void SetNext(PlaylistNode* ptr);
	string GetID();
	string GetSongName();
	string GetArtistName();
	PlaylistNode* GetNext();
	void PrintPlaylistNode();

private:

	string uniqueID;
	string songName;
	string artistName;
	PlaylistNode* nextNodePtr;
};

class Playlist
{
private:
	PlaylistNode* head;
	PlaylistNode* tail;

public:
	Playlist();

	void AddSong(string id, string songname, string artistname);
	void AddBatch();
	void RemoveBatch();
	void PrintList();
	bool RemoveSong(string Song);
	void SongsByArtist(string artist);
	void SearchSongs(string song);

};
#endif 

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
//playlist.cpp

#include "Playlist.h"

PlaylistNode::PlaylistNode()
{
    uniqueID = "none";
    songName = "none";
    artistName = "none";
    nextNodePtr = 0;
}

PlaylistNode::PlaylistNode(string id, string songname, string artist)
{
    uniqueID = id;
    songName = songname;
    artistName = artist;
    nextNodePtr = 0;
}

void PlaylistNode::InsertAfter(PlaylistNode* ptr)
{
    this->SetNext(ptr->GetNext());
    ptr->SetNext(this);
}

void PlaylistNode::SetNext(PlaylistNode* ptr)
{
    nextNodePtr = ptr;
}

string PlaylistNode::GetID()
{
    return uniqueID;
}

string PlaylistNode::GetSongName()
{
    return songName;
}

string PlaylistNode::GetArtistName()
{
    return artistName;
}

PlaylistNode* PlaylistNode::GetNext()
{
    return nextNodePtr;
}


void PlaylistNode::PrintPlaylistNode()
{

    cout << "Unique ID: " << uniqueID << endl;
    cout << "Song Name: " << songName << endl;
    cout << "Artist Name: " << artistName << endl;
}

Playlist::Playlist()
{
    head = tail = 0;
}

void Playlist::AddSong(string id, string songname, string artistname)
{
    PlaylistNode* n = new PlaylistNode( id, songname, artistname);
    if (head == 0)
        head = tail = n;
    else
    {
        n->InsertAfter(tail);
        tail = n;
    }
}

void Playlist::AddBatch()
{
        string filename;
        string Songname;
        string id;
        string Artistname;
     
        cout << "If the executable is not in the same directory as the\nfile, then a directory needs to be provided\n\n";

        cout << "Enter the file name:  ";
        getline(cin, filename);

        ifstream myfile(filename);

        if (myfile)
        {
            while (!myfile.eof())
            {
                if (myfile.good())
                {
                    getline(myfile, id);
                    getline(myfile, Songname);
                    getline(myfile, Artistname);

                    AddSong(id, Songname, Artistname);
                }   
            }
        }
        else
            cout << "\nFile not found!" << endl;
    }

void Playlist::RemoveBatch()
{
    string filename;
    string Songname;
    string id;
    string Artistname;

    cout << "If the executable is not in the same directory as the\nfile, then a directory needs to be provided\n\n";

    cout << "Enter the file name:  ";
    getline(cin, filename);

    ifstream myfile(filename);

    if (myfile)
    {
        while (!myfile.eof())
        {
            if (myfile.good())
            {
                getline(myfile, id);
                getline(myfile, Songname);
                getline(myfile, Artistname);

                RemoveSong(id);
            }
        }
    }
    else
        cout << "\nFile not found!" << endl;
}

bool Playlist::RemoveSong(string id)
{
    if (head == NULL)
    {
        cout << "Playlist is empty." << endl;
        return false;
    }

    PlaylistNode* curr = head;
    PlaylistNode* prev = NULL;
    while (curr != NULL)
    {
        if (curr->GetID() == id)
        {
            break;
        }
        prev = curr;
        curr = curr->GetNext();
    }

    if (curr == NULL)
    {
        cout << "\"" << curr->GetSongName() << "\" is not found" << endl;
        return false;
    }
    else
    {
        if (prev != NULL)
            prev->SetNext(curr->GetNext());
        else
            head = curr->GetNext();

        if (tail == curr)
            tail = prev;
        cout << "\"" << curr->GetSongName() << "\" removed" << endl;
        delete curr;
        return true;
    }
}

void Playlist::SongsByArtist(string artist)
{
    if (head == NULL)
        cout << "Playlist is empty." << endl;
    else
    {
        PlaylistNode* curr = head;
        int i = 1;
        while (curr != NULL)
        {
            if (curr->GetArtistName() == artist)
            {
                cout << endl << i << "." << endl;
                curr->PrintPlaylistNode();
            }
            curr = curr->GetNext();
            i++;
        }
    }
}

void Playlist::SearchSongs(string song)
{
    if (head == NULL)
        cout << "Playlist is empty." << endl;
    else
    {
        PlaylistNode* curr = head;
        int i = 1;
        while (curr != NULL)
        {
            if (curr->GetSongName() == song)
            {
                cout << endl << i << "." << endl;
                curr->PrintPlaylistNode();
            }
            curr = curr->GetNext();
            i++;
        }
    }
}



void Playlist::PrintList()
{
    if (head == NULL)
        cout << "Playlist is empty." << endl;
    else
    {
        PlaylistNode* curr = head;
        int i = 1;
        while (curr != NULL)
        {
            cout << endl << i++ << "." << endl;
            curr->PrintPlaylistNode();
            curr = curr->GetNext();
        }
    }
}





Sorry couldn't post it all
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//main.cpp

#include "Playlist.h"

void PrintMenu();

int main()
{
   
    PrintMenu();
    return 0;
}

void PrintMenu()
{
    Playlist list;
    string id;
    string sname;
    string aname;
    int length;
    char choice;

    while (true)
    {
        cout << endl << "MENU" << endl;
        cout << "1 - Search by Song" << endl;
        cout << "2 - Search by Artist" << endl;
        cout << "3 - Add" << endl;
        cout << "4 - Batch Add" << endl;
        cout << "5 - Remove" << endl;
        cout << "6 - Batch Remove" << endl;
        cout << "7 - Output/Save" << endl;
        cout << "8 - Exit" << endl << endl;

        cout << "Choose an option: " << endl;
        cin >> choice;
        cin.ignore(); 

        if (choice == '1')
        {
            cout << "\nOption 1: Search by Song" << endl;
            cout << "Enter song name: " << endl;
            getline(cin, aname);
            list.SearchSongs(aname);
        }
        else if (choice == '2')
        {
        cout << "\nOption 2: Search by Artist" << endl;
        cout << "Enter artist's name: " << endl;
        getline(cin, aname);
        list.SongsByArtist(aname);
        }
        else if (choice == '3')
        {
            cout << "\nOption 3: Add" << endl;
            cout << "Enter song's id: " << endl;
            getline(cin, id);
            cout << "Enter song's name: " << endl;
            getline(cin, sname);
            cout << "Enter artist's name: " << endl;
            getline(cin, aname);
           
            list.AddSong(id, sname, aname);
        }
        else if (choice == '4')
        {
            cout << "\nOption 4: Batch Add" << endl;
            list.AddBatch();
        }
        else if (choice == '5')
        {
            cout << "\nOption 5: Remove" << endl;
            cout << "Enter song's id: " << endl;
            cin >> id;
            list.RemoveSong(id);
        }
        
        else if (choice == '6')
        {
            cout << "\nOption 6: Batch Remove" << endl;
            list.RemoveBatch();
        }
        else if (choice == '7')
        {
            cout << "\nOption 7: Save" << endl;
            list.PrintList();
        }
        else if (choice == '8')
        {
            system("pause");
            exit(1);
        }
        else
        {
            cout << "Invalid menu choice! Please try again." << endl;
        }
    }
} 


Example txt file for add/remove batch
1
2
3
4
5
6
7
8
9
123
Jesus of Suburia
Greenday
456
Want You Bad
The Offspring
789
Big Poppa
The Notorious B.I.G.
Binary files are a PITA for class objects like std::string, because the string itself contains dynamic elements. So you can't just do a simple write and then a read later on.

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
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
int main()
{
  string foo = "hello world";

  // write
  {
    ofstream ofs("myfile.dat", ios::binary);
    size_t n = foo.size();
    ofs.write(reinterpret_cast<const char*>(&n), sizeof(n));
    ofs.write(foo.c_str(), n);
  }

  // read
  {
    ifstream ifs("myfile.dat", ios::binary);
    size_t n;
    ifs.read(reinterpret_cast<char*>(&n), sizeof(n));
    string input;
    input.reserve(n); // not necessary, but will prevent reallocs later
    for ( size_t i = 0 ; i < n ; i++ ) {
      char ch;
      ifs.read(&ch,1);
      input.push_back(ch);
    }
    cout << "Read " << input << '\n';
  }

  return 0;
}

In short, it's a lot of effort.


$ g++ foo.cpp
$ ./a.out 
Read hello world
$ hd myfile.dat 
00000000  0b 00 00 00 00 00 00 00  68 65 6c 6c 6f 20 77 6f  |........hello wo|
00000010  72 6c 64                                          |rld|
00000013

As you may guess from looking at the file, the binary representation of n is 8 bytes (because this is a 64-bit machine). It it also a little endian machine as well.

Now if you were to copy this binary file to a 32-bit big endian machine, which would expect say
00 00 00 0b 68 65 6c 6c 6f 20 77 6f 72 6c 64,
you can see that's going to cause all sorts of fun and excitement.
will read a binary file and place the information into an ordered linked list


The easiest way to do this is to use c-style null terminated char array's to store the text data. Then the size of every node is the same and is known hence you can use .read() and write() to easily read/write a node from/to a file. eg

1
2
3
4
5
private:
        static const size_t MAXSTR{256};
	char uniqueID[MAXSTR];
        char songName[MAXSTR];
 	char artistName[MAXSTR];


The other code will need to be changed somewhat for this, but it makes binary file read/write so much easier! As you're not storing binary numbers, endian doesn't come into it!
Last edited on
Topic archived. No new replies allowed.