Lion King
Lion King

Reputation: 33813

How to find a string in a binary file?

I want to find a specific string "fileSize" in a binary file.
The purpose of finding that string is to get 4 bytes that next to the string because that 4 bytes contains the size of data that I want to read it.

The content of the binary file like the following:

The same string in another position:

Another position:

The following is the function that writes the data to a file:

void W_Data(char *readableFile, char *writableFile) {
    ifstream RFile(readableFile, ios::binary);
    ofstream WFile(writableFile, ios::binary | ios::app);

    RFile.seekg(0, ios::end);
    unsigned long size = (unsigned long)RFile.tellg();
    RFile.seekg(0, ios::beg);

    unsigned int bufferSize = 1024;
    char *contentsBuffer = new char[bufferSize];

    WFile.write("fileSize:", 9);
    WFile.write((char*)&size, sizeof(unsigned long));
    while (!RFile.eof()) {
        RFile.read(contentsBuffer, bufferSize);
        WFile.write(contentsBuffer, bufferSize); 
    }
    RFile.close();
    WFile.close();
    delete contentsBuffer;
    contentsBuffer = NULL;
}

Also, the function that searches for the string:

void R_Data(char *readableFile) {
    ifstream RFile(readableFile, ios::binary);

    const unsigned int bufferSize = 9;

    char fileSize[bufferSize];
    while (RFile.read(fileSize, bufferSize)) {
        if (strcmp(fileSize, "fileSize:") == 0) {
            cout << "Exists" << endl;
        }
    }
    RFile.close();
}

How to find a specific string in a binary file?

Upvotes: 2

Views: 5741

Answers (2)

Amadeus
Amadeus

Reputation: 10655

I think of using find() is an easy way to search for patterns.

void R_Data(const std::string filename, const std::string pattern) {
    std::ifstream(filename, std::ios::binary);
    char buffer[1024];

    while (file.read(buffer, 1024)) {
        std::string temp(buffer, 1024);
        std::size_t pos = 0, old = 0;

        while (pos != std::string::npos) {
            pos = temp.find(pattern, old);
            old = pos + pattern.length();
            if ( pos != std::string::npos )
                std::cout << "Exists" << std::endl;
        }
        file.seekg(pattern.length()-1, std::ios::cur);
    }
}

Upvotes: 3

R Sahu
R Sahu

Reputation: 206567

How to find a specific string in a binary file?

If you don't know the location of the string in the file, I suggest the following:

  1. Find the size of the file.
  2. Allocate memory for being able to read everything in the file.
  3. Read everything from the file to the memory allocated.
  4. Iterate over the contents of the file and use std::strcmp/std::strncmp to find the string.
  5. Deallocate the memory once you are done using it.

There are couple of problems with using

const unsigned int bufferSize = 9;

char fileSize[bufferSize];
while (RFile.read(fileSize, bufferSize)) {
    if (strcmp(fileSize, "filesize:") == 0) {
        cout << "Exists" << endl;
    }
}

Problem 1

The strcmp line will lead to undefined behavior when fileSize actually contains the string "fileSize:" since the variable has enough space only for 9 character. It needs an additional element to hold the terminating null character. You could use

const unsigned int bufferSize = 9;

char fileSize[bufferSize+1] = {0};
while (RFile.read(fileSize, bufferSize)) {
    if (strcmp(fileSize, "filesize:") == 0) {
        cout << "Exists" << endl;
    }
}

to take care of that problem.

Problem 2

You are reading the contents of the file in blocks of 9.

First call to RFile.read reads the first block of 9 characters.
Second call to RFile.read reads the second block of 9 characters.
Third call to RFile.read reads the third block of 9 characters. etc.

Hence, unless the string "fileSize:" is at the boundary of one such blocks, the test

if (strcmp(fileSize, "filesize:") == 0)

will never pass.

Upvotes: 1

Related Questions