PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label binaryfiles. Show all posts
Showing posts with label binaryfiles. Show all posts

Sunday, October 30, 2022

[FIXED] What really is EOF for binary files? Condition? Character?

 October 30, 2022     binaryfiles, c, eof     No comments   

Issue

I have managed this far with the knowledge that EOF is a special character inserted automatically at the end of a text file to indicate its end. But I now feel the need for some more clarification on this. I checked on Google and the Wikipedia page for EOF but they couldn't answer the following, and there are no exact Stack Overflow links for this either. So please help me on this:

  • My book says that binary mode files keep track of the end of file from the number of characters present in the directory entry of the file. (In contrast to text files which have a special EOF character to mark the end). So what is the story of EOF in context of binary files? I am confused because in the following program I successfully use !=EOF comparison while reading from an .exe file in binary mode:

     #include<stdio.h>
     #include<stdlib.h>
    
     int main()
     {
    
      int ch;   
      FILE *fp1,*fp2;
    
      fp1=fopen("source.exe","rb");
      fp2=fopen("dest.exe","wb");
    
      if(fp1==NULL||fp2==NULL)
      {
      printf("Error opening files");
      exit(-1);
      }
    
      while((ch=getc(fp1))!=EOF)
      putc(ch,fp2);
    
      fclose(fp1);
      fclose(fp2);
    
      }
    
  • Is EOF a special "character" at all? Or is it a condition as Wikipedia says, a condition where the computer knows when to return a particular value like -1 (EOF on my computer)? Example of such "condition" being when a character-reading function finishes reading all characters present, or when character/string I/O functions encounter an error in reading/writing?

    Interestingly, the Stack Overflow tag for EOF blended both those definitions of the EOF. The tag for EOF said "In programming realm, EOF is a sequence of byte (or a chacracter) which indicates that there are no more contents after this.", while it also said in the "about" section that "End of file (commonly abbreviated EOF) is a condition in a computer operating system where no more data can be read from a data source. The data source is usually called a file or stream."

But I have a strong feeling EOF won't be a character as every other function seems to be returning it when it encounters an error during I/O.

It will be really nice of you if you can clear the matter for me.


Solution

The various EOF indicators that C provides to you do not necessarily have anything to do with how the file system marks the end of a file.

Most modern file systems know the length of a file because they record it somewhere, separately from the contents of the file. The routines that read the file keep track of where you are reading and they stop when you reach the end. The C library routines generate an EOF value to return to you; they are not returning a value that is actually in the file.

Note that the EOF returned by C library routines is not actually a character. The C library routines generally return an int, and that int is either a character value or an EOF. E.g., in one implementation, the characters might have values from 0 to 255, and EOF might have the value −1. When the library routine encountered the end of the file, it did not actually see a −1 character, because there is no such character. Instead, it was told by the underlying system routine that the end of file had been reached, and it responded by returning −1 to you.

Old and crude file systems might have a value in the file that marks the end of file. For various reasons, this is usually undesirable. In its simplest implementation, it makes it impossible to store arbitrary data in the file, because you cannot store the end-of-file marker as data. One could, however, have an implementation in which the raw data in the file contains something that indicates the end of file, but data is transformed when reading or writing so that arbitrary data can be stored. (E.g., by “quoting” the end-of-file marker.)

In certain cases, things like end-of-file markers also appear in streams. This is common when reading from the terminal (or a pseudo-terminal or terminal-like device). On Windows, pressing control-Z is an indication that the user is done entering input, and it is treated similarly to reach an end-of-file. This does not mean that control-Z is an EOF. The software reading from the terminal sees control-Z, treats it as end-of-file, and returns end-of-file indications, which are likely different from control-Z. On Unix, control-D is commonly a similar sentinel marking the end of input.



Answered By - Eric Postpischil
Answer Checked By - Mary Flores (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Saturday, October 29, 2022

[FIXED] How to read data from binary files properly in C++ till the last data?

 October 29, 2022     binaryfiles, c++, eof     No comments   

Issue

I recently learnt that to read properly from a text file we use

while(file>>var1>>var2){
   //do stuff with data
}

instead of

while(file){
   file>>var1>>var2;
   //do stuff with data
}

because the latter performs one extra read even after last data item is read and on the next read it is able to read the eof, so if we have something like std::vector<CLASSNAME>CLASSVECTOR, we end up having one extra entry in the vector, while if we use the first method it reads only till the last record.

My question is if how do I read till the last record in case of a binary file? So if I have something like:

class class1 {
   int a;
   class2 obj2;
   class3 obj3;
public:
   void write_ binary(std::ofstream file) const;
   void read_file(std::ifstream file);
   //rest of class definition
};

And I write this class like so :

void class1::write_ binary(std::ofstream file) const {
   file.write(reinterpret_cast<const char*>(&a),sizeof(a));
   obj2.write_binary(file); //this writes the data in the same way using 
   reinterpret_cast to ofstream file
   obj3.write_binary(file); //this writes the data in the same way using 
   reinterpret_cast to ofstream file
}

And also if I read the file like so :

void class1::read_file(std::ifstream file) {
   file.read(reinterpret_cast<char*>(&a),sizeof(a));
   obj2.read_binary(file); //this reads data for obj2 in the same way using 
   read() and reinterpret_cast
   obj3.read_binary(file); //this reads data for obj3 in the same way using read() and reinterpret_cast
}

And if I want to store this data in a vector like so:

class1 obj1;
std::vector<class1>records;

while(file)
{
   obj1.read_binary(file);
   records.push_back(obj1);
   //reset obj1 to initial state
}

I end up getting an extra record in vector records. I cannot use while(file>>obj1) since I want to use >> for cin. Please explain how do I read from binary file without reading an extra record.


Solution

It's the same as your text example, the test on the file must be after the read not before.

for (;;)
{
     obj1.read_binary(file);
     if (!file) // did the previous read fail?
         break; // if so quit the loop
     records.push_back(obj1);
}


Answered By - john
Answer Checked By - David Goodson (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to use feof to read an undefined number of float values from a binary file?

 October 29, 2022     binaryfiles, c, eof, file, floating-point     No comments   

Issue

I write some float values to a binary file, and after that I want to read them back with another .c program.

This is how I write them:

#include <stdio.h>

int main() {
    /* Create the file */
    float x = 1.1;
    FILE *fh = fopen ("file.bin", "wb");
    if (fh != NULL) {
       for (int i = 0; i < 10; ++i)
       {
            x = 1.1*i;
            fwrite (&x,1, sizeof (x), fh);
            printf("%f\n", x);
       }
        fclose (fh);
    }

    return 0;
}

And this is how I want to read them:

#include <stdio.h>


int main(){
    /* Read the file back in */
    
    FILE *fh = fopen ("file.bin", "wb");
    
    float x = 7.7;
    fh = fopen ("file.bin", "rb");
    if (fh != NULL) {
       
        while(!feof(fh)){
            if(feof(fh))
                break;
            
            fread (&x, 1, sizeof (x), fh);
            printf ("Value is: %f\n", x);
        }
        


        fclose (fh);
    }

    return 0;
}

But I got back 7.7 which means that the reader never found any of the values.

How can I do this? What did I miss here?


Solution

In your second program, FILE *fh = fopen ("file.bin", "wb"); opens the file for writing and truncates it to zero length, destroying the data in it. Change that to FILE *fh = fopen ("file.bin", "rb"); and remove the later fh = fopen ("file.bin", "rb");.

Additionally, do not use feof for testing whether there is more data in a file. feof only reports if EOF or an error occurred on a previous read or write operation. It does not tell you that the file position indicator is currently pointing to the end of the file, if no attempt to read past that has been made. Instead, check the return value of fread to see how many items it read.

If you use size_t result = fread(&x, 1, sizeof (x), fh);, you ask fread to read sizeof (x) bytes, and it will return the number of bytes read. If that is less than sizeof (x), then a complete x was not read. In contrast, if you use size_t result = fread(&x, sizeof x, 1, fh);, you ask fread to read 1 object of size sizeof x. Then fread will return the number of complete objects read, which will be 0 or 1.



Answered By - Eric Postpischil
Answer Checked By - Marilyn (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Thursday, October 20, 2022

[FIXED] How to write members of a class to a binary file using cpp?

 October 20, 2022     binaryfiles, c++, class, data-members     No comments   

Issue

I'm writing a small back-end in cpp where I have to write some crossword data into a binary file. I have created an XWPuzzle class with all its data members public, and xWord is an object of this class. Here is the piece of code with which I'm trying to write to the binary file:

#include"binIncludes.h"

int main(int argc, char** argv)
{
    cout<<"Bin read-write Tester\n";
    xWord.title="Yeah!\0";
    xWord.author="Nobody\0";
    xWord.grid=147;
    xWord.userGrid=109;
    xWord.clues[0]="as\0";
    xWord.clues[1]="de\0";
    xWord.clues[2]="re\0";
    xWord.solution[0]="ASSET\0";
    xWord.solution[1]="DEER\0";
    xWord.solution[2]="REED\0";
    xWord.checksum=(int)(xWord.title.at(0))+(int)(xWord.author.at(0))+xWord.grid+xWord.userGrid;
    xWord.checksum+=(int)(xWord.clues[0].at(0))+(int)(xWord.clues[1].at(0))+(int)(xWord.clues[2].at(0));
    xWord.checksum+=(int)(xWord.solution[0].at(0))+(int)(xWord.solution[1].at(0))+(int)(xWord.solution[2].at(0));
    fstream file;
    file.open("binTest.bin",ios::out|ios::binary);
    file.write(SIGNATURE,sizeof(SIGNATURE));
    file.write(VERSION,sizeof(VERSION));
    file.write(TYPE,sizeof(TYPE));
    file.write((char*)xWord.checksum,sizeof(xWord.checksum));
    file.write(xWord.title.c_str(),xWord.title.size());
    file.write(xWord.author.c_str(),xWord.author.size());
    file.write((char*)xWord.grid,sizeof(xWord.grid));
    file.write((char*)xWord.userGrid,sizeof(xWord.userGrid));
    file.close();
    cout<<"File written\n";
    _getch();
    return 0;
}

SIGNATURE, VERSION and TYPE are null-terminated strings, but the compiled program throws an error when it gets to the line

file.write((char*)xWord.checksum,sizeof(xWord.checksum));

The debugger throws a First-chance exception (Access Violation reading location error) at MSVCR100.dll. Am I doing something wrong by using a member of a class the wrong way? This is an independent project and not any homework. I've been running around for this for two days now. Any specific help appreciated. Thanks.

I have other data to be written also, in addition to those from this class.

EDIT:

XWPuzzle.h:

#ifndef XWPULZZLE_H
#define XWPUZZLE_H

#include"binIncludes.h"

class XWPuzzle
{
    public:
        string title;
        string author;
        int grid;
        int userGrid;
        string clues[3];
        string solution[3];
        int checksum;
} xWord;

#endif

binDefines.h:

#ifndef BIN_DEFINES_H
#define BIN_DEFINES_H

#include"binIncludes.h"

#define SIGNATURE "BinFile\0"
#define VERSION "0.1.1\0"
#define TYPE "With Solution\0"

#endif

binIncludes.h:

#ifndef BIN_INCLUDES_H
#define BIN_INCLUDES_H

#include<iostream>
#include<conio.h>
#include<string>
#include<fstream>

using namespace std;

#include"binDefines.h"
#include"XWPuzzle.h"

#endif

Solution

You are casting integer to a pointer and trying to write data by this pointer. That's wrong. You shoud get pointer to a checksum, cast it and then write

file.write((char*)(&xWord.checksum),sizeof(xWord.checksum));

Same with grid and userGrid fields



Answered By - Jeka
Answer Checked By - Robin (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Thursday, May 5, 2022

[FIXED] How can I save a base64-encoded image to disk?

 May 05, 2022     base64, binaryfiles, image, node.js     No comments   

Issue

My Express app is receiving a base64-encoded PNG from the browser (generated from canvas with toDataURL() ) and writing it to a file. But the file isn't a valid image file, and the "file" utility simply identifies it as "data".

var body = req.rawBody,
  base64Data = body.replace(/^data:image\/png;base64,/,""),
  binaryData = new Buffer(base64Data, 'base64').toString('binary');

require("fs").writeFile("out.png", binaryData, "binary", function(err) {
  console.log(err); // writes out file without error, but it's not a valid image
});

Solution

I think you are converting the data a bit more than you need to. Once you create the buffer with the proper encoding, you just need to write the buffer to the file.

var base64Data = req.rawBody.replace(/^data:image\/png;base64,/, "");

require("fs").writeFile("out.png", base64Data, 'base64', function(err) {
  console.log(err);
});

new Buffer(..., 'base64') will convert the input string to a Buffer, which is just an array of bytes, by interpreting the input as a base64 encoded string. Then you can just write that byte array to the file.

Update

As mentioned in the comments, req.rawBody is no longer a thing. If you are using express/connect then you should use the bodyParser() middleware and use req.body, and if you are doing this using standard Node then you need to aggregate the incoming data event Buffer objects and do this image data parsing in the end callback.



Answered By - loganfsmyth
Answer Checked By - Pedro (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing