2

First, I would like to express that I come to post my question, after a lot of searching on the internet, without finding a proper article or solution to what I'm looking for.

As mentioned in the title, I need to convert an ASCII file to Binary file.

My file is composed of lines, every line contain float separated by space.

I found that many people use c++ since it's more easy for this kind of task.

I tried the following code, but the generated file is so big.

#include <iostream>
#include <fstream>
#include <string>

using namespace std;


int main(int argc, char const *argv[])
{
   char buffer;

    ifstream in("Points_in.txt");
    ofstream out("binary_out.bin", ios::out|ios::binary);

    float nums[9];

    while (!in.eof())
    {
        in >> nums[0] >> nums[1] >> nums[2]>> nums[3] >> nums[4] >> nums[5]>> nums[6] >> nums[7] >> nums[8];

        out.write(reinterpret_cast<const char*>(nums), 9*sizeof(float));

    }
    return 0;
}

I found those 2 resources :

http://www.eecs.umich.edu/courses/eecs380/HANDOUTS/cppBinaryFileIO-2.html https://r3dux.org/2013/12/how-to-read-and-write-ascii-and-binary-files-in-c/

I appreciate if you have any others resources ?

lines in my ASCII input file are as below :

-16.505 -50.3401 -194 -16.505 -50.8766 -193.5 -17.0415 -50.3401 -193.5

Thank you for your time

MGM
  • 33
  • 6
  • What format do you have in mind? Binary format could mean almost anything. – Arndt Jonasson Apr 09 '18 at 11:45
  • 2
    If your lines contain three `float` why are you reading them into `int` variables? – Cory Kramer Apr 09 '18 at 11:45
  • Please provide a [mcve], including the input file, your expected output file size and the actual output file size. Although I can guess what's your problem in this case, that should be included in every questions. – user202729 Apr 09 '18 at 11:46
  • 2
    BTW [why-is-iostreameof-inside-a-loop-condition-considered-wrong](https://stackoverflow.com/questions/5605125/) – user202729 Apr 09 '18 at 11:46
  • A [mcve] looks like [this](https://tio.run/##Sy4o0E1PTv7/XzkzLzmnNCXVJjO/uKQoNTHXjiszr0QhNzEzT0OzGszOs@Yqz8jMSdVQLC5JsbJKzszTS81P09AESsME7OzyrCHs/NISGxugjlqu2v//DfWMAA). (but use proper indentation) – user202729 Apr 09 '18 at 11:47
  • I edited, by a sample from my input file. – MGM Apr 09 '18 at 12:47
  • Is this too big? sizeof(float) is probably four, and your numbers in text including separator are around nine bytes. – Arndt Jonasson Apr 09 '18 at 13:07
  • I can't help thinking i would be more efficient to read the file line by line into a string and parse the floats out of the string using your own tokenising function. – Bob Moore Apr 09 '18 at 13:07
  • @ArndtJonasson the problem is next step when I need to parse the binary output file. I should convert space too . – MGM Apr 09 '18 at 13:28
  • The advantage of a binary format is that you know where everything is and don't need to parse anything. Just read it back. I still don't understand the requirements. – Arndt Jonasson Apr 09 '18 at 13:30
  • @ArndtJonasson exactly, that's why I need to convert the ASCII file; first, the make the parse faster, second to reduce the size. – MGM Apr 09 '18 at 13:35
  • 1
    So what is wrong with the code you have? – Arndt Jonasson Apr 09 '18 at 13:57
  • it parses all file and returns the same value. – MGM Apr 09 '18 at 14:14
  • @ArndtJonasson What I mean by binary : Ascii Text Value : -125.050 ==> binary value : 00101101 00110001 00110010 00110101 00101110 00110000 00110101 00110000 – MGM Apr 10 '18 at 08:57
  • You could present anything, such as the text "-125.050" as binary in the same way. A better way would be to say IEEE-754 floating-point, which is very specific. – Arndt Jonasson Apr 10 '18 at 10:50
  • @ArndtJonasson I find a solution working perfectly, just I'm trying to find how to convert line by line. please, could you check: https://stackoverflow.com/questions/49751660/ascii-to-binary-conversion-read-line-by-line-c?noredirect=1#comment86518052_49751660 – MGM Apr 10 '18 at 11:18

1 Answers1

0

Here is a simpler method:

#include <iostream>
#include <fstream>

int main()
{
  float value = 0.0;
  std::ifstream input("my_input_file.txt");
  std::ofstream output("output.bin");
  while (input >> value)
  {
    output.write(static_cast<char *>(&value), sizeof(value));
  }
  input.close(); // explicitly close the file.
  output.close();
  return EXIT_SUCCESS;
}

In the above code fragment, a float is read using formatted read into a variable.

Next, the number is output in its raw, binary form.

The reading and writing repeat until there is no more input data.

Exercises for the reader/OP:
1. Error handling for opening of files.
2. Optimize the reading and writing (read & write using bigger blocks of data).

Thomas Matthews
  • 52,985
  • 12
  • 85
  • 144
  • Hi Thomas Thank you I tried your code, but an error appeared : error: invalid static_cast from type ‘float*’ to type ‘char*’ output.write(static_cast(&value), sizeof(value)); – MGM Apr 09 '18 at 14:51
  • @MGM: It (still) needs to be a `reinterpret_cast`. – Davis Herring Apr 09 '18 at 15:05
  • @MGM You can also first cast to `void *`, then to `char *`: `static_cast(static_cast(&value))` will work. “_A prvalue of type pointer to void (possibly cv-qualified) can be converted to pointer to any object type._” (see [cppreference](http://en.cppreference.com/w/cpp/language/static_cast)) – mindriot Apr 09 '18 at 15:07
  • You could also use a C-style cast: `(const char *)`. – Thomas Matthews Apr 09 '18 at 15:15
  • @ThomasMatthews I think, it work : output.write((const char *)(&value), sizeof(value)); for this first line : -16.505 -50.3401 -194 -16.505 -50.8766 -193.5 -17.0415 -50.3401 -193.5 I got this in the first binary output file : 3d0a 84c1 435c 49c2 0000 42c3 3d0a 84c1 – MGM Apr 09 '18 at 15:34
  • @ThomasMatthews what if I need to verify if this conversation is correct, if I apply the inverse now, which mean, binary to ascii : int main(int argc, char const *argv[]) { char value; int i=0; std::ifstream input("binary_out.bin"); std::ofstream output("Points_b2a.txt"); if (input && output) { std::cout << "Open input / output files" << std::endl; while (input >> value) { i++; output.write((const float *)(&value), sizeof(value)); } } else cerr << "can't open file !" << endl; ---- – MGM Apr 10 '18 at 08:38
  • As I said, use `std::fstream::read` to read in a value from a binary file, which should be the "inverse" of writing binary to the file. Remember to open the file in binary mode. Also, search the internet for "stackOverflow c++ read file binary float" – Thomas Matthews Apr 10 '18 at 14:02