/****************************************************************************** * Random-access file example program in C++. * * This shows how to treat a text file as binary and access records within * it. This reads only the first two records from a 1K block, keeping track * of where each record starts and ends in the buffer. * * Written by John Cole at The University of Texas at Dallas on November 1, * 2016. Copy, adapt, and use this code freely. ******************************************************************************/ #include "stdafx.h" #include #include #include #include #include #include using namespace std; union charLong { long long lpart; char cpart[8]; }; charLong cl; struct Student { char name[20]; char grade; double gpa; int year; string school; }; int main() { Student s; Student t; s.grade = 'A'; s.gpa = 3.97; s.year = 3; strcpy_s(s.name, 20, "Bill"); s.school = "The University of Texas at Dallas"; // Write a "Student" structure, then reposition to the beginning of the file // and read it back. fstream stu; stu.open("Student.txt", ios::out | ios::binary); stu.write(reinterpret_cast(&s), sizeof(Student)); long long whereami = stu.tellp(); stu.close(); stu.open("Student.txt", ios::in | ios::binary); stu.read(reinterpret_cast(&t), sizeof(Student)); stu.close(); // This section write binary data to a file, then reads it back. What // you should see if you list the file is not all text. fstream f; char buffer[1024]; int recptr = 0; int startptr = 0; char record1[100]; char record2[100]; long long l1, l2; char fname[] = "JCBinary1.txt"; // Open the file, re-creating it if we can't open it the first time. f.open(fname, ios::in | ios::out | ios::binary); if (f.fail()) { cout << "error opening file" << endl; f.open(fname, ios::out); if (f.fail()) { cout << "Real error opening file" << endl; system("pause"); return 0; } f.close(); f.open(fname, ios::in | ios::out | ios::binary); } int x = 1; int bufptr = 0; int keylen = 15; char str1[] = "This is a slightly longer test\n"; char str2[] = "After the long\n"; // This section writes a string, then binary data, then another string, // to a file that is open for input and output. strcpy_s(buffer, 1024, str1); bufptr += strlen(str1); cl.lpart = 13; memcpy_s(&buffer[bufptr], 8, cl.cpart, 8); bufptr += sizeof(charLong); strcpy_s(&buffer[bufptr], 100, str2); bufptr += strlen(str2); cl.lpart = 123456789; memcpy_s(&buffer[bufptr], 8, cl.cpart, 8); try { f.write(buffer, 1024); // Having written the file, reposition to the beginning, read in the // 1K block we wrote, and pull data out of it. memset(&buffer[0], 0, 1024); f.seekg(0l, ios::beg); f.read(&buffer[0], 1024); bufptr = 0; x = 0; while (buffer[x] != '\n') { record1[x] = buffer[bufptr]; x++; bufptr++; } record1[x] = buffer[bufptr]; x++; bufptr++; record1[x] = 0; memcpy_s(cl.cpart, 8, &buffer[bufptr], 8); l1 = cl.lpart; bufptr += 8; x = 0; while (buffer[bufptr] != '\n') { record2[x] = buffer[bufptr]; x++; bufptr++; } record2[x] = buffer[bufptr]; x++; bufptr++; record2[x] = 0; memcpy_s(cl.cpart, 8, &buffer[bufptr], 8); l2 = cl.lpart; cout << "First long: " << l1 << " Second long: " << l2 << endl; // Illustrate updating: f.seekg(strlen(str1), ios::beg); l2 = 65 * 256 + 66; f.write(reinterpret_cast(&l2), sizeof(l2)); f.seekg(strlen(str1), ios::beg); f.read(reinterpret_cast(&l1), sizeof(l1)); cout << "l1 variable after rewrite and read: " << l1 << endl; f.close(); } catch (exception ex) { cout << "Error in binary I/O " << ex.what() << endl; } // Read a text file as binary and split out the records. x = 1; //??? f = new fstream(); // Poor practice here, hard-coding the fully-qualified path of a file. f.open("H:\\Classes\\2016Fall\\CS6360Fall2016\\CS6360Asg5TestData.txt", ios::in | ios::binary); f.read(buffer, 1024); // Find the end of the first record. while (buffer[recptr] != '\n') recptr++; cout << "Record1 is " << recptr << " bytes long" << endl; strncpy_s(record1, &buffer[startptr], recptr); record1[recptr] = 0; cout << "Record1: " << record1 << endl; // Move past the NL character, then save that as the start of the second line. recptr++; startptr = recptr; // Find the end of the second record. while (buffer[recptr] != '\n') recptr++; cout << "Record2 is " << (recptr - startptr) << " bytes long" << endl; strncpy_s(record2, &buffer[startptr], recptr-startptr); record2[recptr] = 0; cout << "Record2: " << record2 << endl; f.close(); system("pause"); return 0; }