Thread: Read large amount of numbers from file

  1. #1
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485

    Read large amount of numbers from file

    Hallo,

    I am working on a function for reading large amount of data from a file. Each line contains the information needed to build a triangle. What is the best way to do this?

    Right now Im tying to read each line, convert it into a float and than create a triangle before I read the next line. Is there a smarter way? Would be great to get some input on this.

    Code:
          std::string currentLine;            // Variable that holds the current line
                                              // we are using.
          int nrLines = 0;                    // Variable for checking how many lines 
                                              // there are in the file      
          
          // Open file
          std::ifstream myFile (FileName);
          
          /*  
          // The content of the file
            random line   11 ra
            V: 2.020,0.121,12.1212 4.657,11.31,9.11 4.7,11.00,5.411
            V: 2.020,0.121,12.1212 4.657,11.31,9.11 4.7,11.00,5.411
            V: 2.020,0.121,12.1212 4.657,11.31,9.11 4.7,11.00,5.411
            V: 2.020,0.121,12.1212 4.657,11.31,9.11 4.7,11.00,5.411
          */
          
          
          
          // An array of strings, for reading the 3 vertexes we will later
          // use. Note that there is 3 vertexes, each made up of 3 
          // cordinates
          std::string vertex[3][3];
    
          
          if (myFile.is_open())
          {
              // While the file is open, we read the info and construct triangles
              while (! myFile.eof())
              {
                  // Read line
                  getline(myFile, currentLine);
                  
                  // Check if this line holds vertex information. If the line starts 
                  // with V, we will use it.
                  if (currentLine[0] == 'V')
                  {
                      // Break the line into different components, so that we can
                      // create 3 different vertexes for each cordinate in the file
                      // V: 0.0,0.0,0.0 1.0,1.0,1.0 2.0,2.0,2.0
                      
                      // Variable for keeping track of which character in currentLine
                      // we are reading, it starts at 2, as the 3 first characters
                      // are not part of the number we are tring to read
                      int x = 3;
                      
                      // Make a loop for creating 3 vertexes
                      for (int i = 0; i < 3; i++)
                      {
                          // Loop for looping throught the three cordinates of each
                          // vertex
                          for (int j = 0; j < 3; j++)
                          {
                              // Make sure the vertex string we are writing to now is 
                              // empty
                              vertex[i][j].clear();
                              
                              // Make sure the current character is part of the number
                              while (currentLine[x] != ',' && currentLine[x] != ' ')
                              {
                                 // If the current character is part of a number,
                                 // append it to the vertex string
                                 vertex[i][j].push_back(currentLine[x]);
                                 x++;
                              }
                              x++;
                          }
                      }   
                      // Convert the string into floats 
                  }
                  // Increment the line counter
                  nrLines++;
              }
              // Finished with reading the file, close it
              myFile.close();
          }
    I also have a problem with the printing. I get a lot of random characters after i have printed the numbers.
    Code:
          // Print the thing
          for (int i = 0; i < 3; i++)
          {
              for (int j = 0; j < 3; j++)
              {
                  std::cout << vertex[i][j] << " ";
              }
              std::cout << " - ";
          }
          
          std::cout << std::endl;
    Thanks for your time

    EDIT:
    Right now Im trying to load my own file format, which kind of suck. Does anyone know where to find good information on how to load .obj files? I have looked, but could not find anything good (simple)

    Thanks again
    Last edited by h3ro; 05-09-2007 at 05:24 PM.

  2. #2
    Registered User
    Join Date
    Dec 2006
    Location
    Scranton, Pa
    Posts
    252
    Obj (Model files) have 3 vertice cords per line, not the 9 you're doing. I've never seen a text-based model format like the one you're developing before.

    -0.252000 0.169971 0.008000 //this is standard (as you probably already know).

    I'm not certain, but I think you could actually read the floats directly from a file such as;

    Code:
     float getcord;
    
     ifstream in("model.obj", ios::in | ios::binary)
     in>>getcord;
    I'd dump the comma separator, btw. Just use a space. Some use the comma as a decimal point, so that can get confusing -

  3. #3
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Obj (Model files) have 3 vertice cords per line, not the 9 you're doing. I've never seen a text-based model format like the one you're developing before.
    This is what I get when I try to export from Maya. What are all the stuff at the end?
    Also, when I open the file, everything are at the same line (it changed when I pasted it here)

    Code:
    # This file uses centimeters as units for non-parametric coordinates.
    
    mtllib box.mtl
    g default
    v -0.500000 -0.500000 0.500000
    v 0.500000 -0.500000 0.500000
    v -0.500000 0.500000 0.500000
    v 0.500000 0.500000 0.500000
    v -0.500000 0.500000 -0.500000
    v 0.500000 0.500000 -0.500000
    v -0.500000 -0.500000 -0.500000
    v 0.500000 -0.500000 -0.500000
    vt 0.000000 0.000000
    vt 1.000000 0.000000
    vt 0.000000 1.000000
    vt 1.000000 1.000000
    vt 0.000000 2.000000
    vt 1.000000 2.000000
    vt 0.000000 3.000000
    vt 1.000000 3.000000
    vt 0.000000 4.000000
    vt 1.000000 4.000000
    vt 2.000000 0.000000
    vt 2.000000 1.000000
    vt -1.000000 0.000000
    vt -1.000000 1.000000
    vn 0.000000 0.000000 1.000000
    vn 0.000000 0.000000 1.000000
    vn 0.000000 0.000000 1.000000
    vn 0.000000 0.000000 1.000000
    vn 0.000000 1.000000 0.000000
    vn 0.000000 1.000000 0.000000
    vn 0.000000 1.000000 0.000000
    vn 0.000000 1.000000 0.000000
    vn 0.000000 0.000000 -1.000000
    vn 0.000000 0.000000 -1.000000
    vn 0.000000 0.000000 -1.000000
    vn 0.000000 0.000000 -1.000000
    vn 0.000000 -1.000000 0.000000
    vn 0.000000 -1.000000 0.000000
    vn 0.000000 -1.000000 0.000000
    vn 0.000000 -1.000000 0.000000
    vn 1.000000 0.000000 0.000000
    vn 1.000000 0.000000 0.000000
    vn 1.000000 0.000000 0.000000
    vn 1.000000 0.000000 0.000000
    vn -1.000000 0.000000 0.000000
    vn -1.000000 0.000000 0.000000
    vn -1.000000 0.000000 0.000000
    vn -1.000000 0.000000 0.000000
    s off
    g pCube1
    usemtl initialShadingGroup
    f 1/1/1 2/2/2 4/4/3 3/3/4
    f 3/3/5 4/4/6 6/6/7 5/5/8
    f 5/5/9 6/6/10 8/8/11 7/7/12
    f 7/7/13 8/8/14 2/10/15 1/9/16
    f 2/2/17 8/11/18 6/12/19 4/4/20
    f 7/13/21 1/1/22 3/3/23 5/14/24
    I'm not certain, but I think you could actually read the floats directly from a file such as;

    Code:

    float getcord;

    ifstream in("model.obj", ios::in | ios::binary)
    in>>getcord;

    I'd dump the comma separator, btw. Just use a space. Some use the comma as a decimal point, so that can get confusing -
    That did not work very well. When I tried to output the numbers again I got things like 1.#### and so on, which did not make sense.

    Right now im experimenting with sscanf, not sure if its the right thing or not, but at least I can do things like this:
    sscanf(file, float, float, float).

    But right now it does not read the numbers correct.


    Thanks for your time
    Last edited by h3ro; 05-10-2007 at 05:29 AM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > while (! myFile.eof())
    See the FAQ as to why using eof in a control loop is bad.

    Use
    while ( getline(myFile, currentLine) )

    > if (currentLine[0] == 'V')
    None of your input begins with upper case V ?

    Personally, I'd go with
    Code:
    while ( getline(myFile, currentLine) ) {
      if ( currentLine[0] == 'V' ) {
        processVertex( currentLine );
      } else {
        // unknown line type?
      }
    }
    Don't try to do too much in the same function, break it up into functions which perform very specific tasks.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Thank you Salem, I changed it a bit now, so I don't have so long code. But I am still struggling with how to read the numbers efficiently.

  6. #6
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    hallo,

    Now I have something working here, but I would very much like some input on it. Is this a good way to do it?

    Code:
    Vector3D processVertex(std::string line);
    
    std::vector<Triangle> loadFromFile(char* FileName)
    {     
          std::string currentLine;            // Variable that holds the current line
                                              // we are using.
          std::vector<Vector3D> vertexList;   // A dynamic vector array for holding
                                              // the info about the vertexs
            
          // Open file
          std::ifstream myFile (FileName);
          if (myFile.is_open())
          {
              // While the file is open, we read the info and construct triangles
              while ( getline(myFile, currentLine) ) 
              {
                  // Check if this line holds vertex information. If the line starts 
                  // with "v ", we will use it.
                  if (currentLine[0] == 'v' && currentLine[1] == ' ' )
                  {
                      vertexList.push_back(processVertex(currentLine));
                  }
                  
                  // Check if the line holds uv information. If its starts with
                  // "vt" if a uv.
                  if (currentLine[0] == 'v' && currentLine[1] == 't')
                  {
                     // Read uv info
                  }
                  
                  // Check if the line holds normal information. If its starts with
                  // "vn" if a normal.
                  if (currentLine[0] == 'v' && currentLine[1] == 'n')
                  {
                     // Read normal info
                  }
              
              }
              // Finished with reading the file, close it
              myFile.close();
          }
          
          // Temp, without it, the program crashes
          std::vector <Triangle> myVar;
          
          return myVar;
    }
    
    
    Vector3D processVertex(std::string line)
    {
             std::string vertexString[3];
             
             for (int x = 0; x < 3; x++)
             {
                 for (int i = 2; i <= line.size(); i++)
                 {
                     //Break up the string into the three cordinates
                     if ( line[i] != ' ')
                     {
                        vertexString[x].push_back(line[i]);    
                     }
                 }
             }
             
             // Convert the string into a number
             Vector3D vertex( (float)atof(vertexString[0].c_str()),
                              (float)atof(vertexString[1].c_str()),
                              (float)atof(vertexString[2].c_str())
                              );
             
             return vertex;
    }

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I would use a stringstream inside processVertex. You can read each value into a float variable directly. An istringstream constructed with your line variable will work just like an ifstream or cin, so it shouldn't be that hard to use.

    Is there a reason you're not using double, the default floating-point typein C++, instead of float?

  8. #8
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Is there a reason you're not using double, the default floating-point typein C++, instead of float?
    The only reason is that Vector3D takes floats, so its just the easiest to do.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A development process
    By Noir in forum C Programming
    Replies: 37
    Last Post: 07-10-2011, 10:39 PM
  2. read from file problem
    By Martin Kovac in forum C Programming
    Replies: 1
    Last Post: 04-13-2009, 08:33 AM
  3. File transfer- the file sometimes not full transferred
    By shu_fei86 in forum C# Programming
    Replies: 13
    Last Post: 03-13-2009, 12:44 PM
  4. Simple File encryption
    By caroundw5h in forum C Programming
    Replies: 2
    Last Post: 10-13-2004, 10:51 PM
  5. archive format
    By Nor in forum A Brief History of Cprogramming.com
    Replies: 0
    Last Post: 08-05-2003, 07:01 PM