🔒 Locked
File Stream
Advertisement
Original Post
I have a couple instances where i need to get the data from a file. It's in char format and i need them to be longs so i use atol(), i don't really think that's all that efficient, then i thought about using file streams.. can someone post some code as to how to use it and is it cross-platform to linux and mac and whatnot?
what exactly does that do? i'm not really too familiar with file streams.. or streams in general. i'm just now getting into string manipulation, i've mostly been into graphics programming...
or even is there an internal pointer that i can get one byte at a time? or how ever many bytes i want at a time to put in some sort of buffer to handle my own way?
Quote:
Original post by EvilKnuckles666what exactly does that do? i'm not really too familiar with file streams.. or streams in general.
std::ifstream input("inputfile.txt"); opens the file "inputfile.txt" for reading: inputfilestream.
input >> value; reads a long integer from the file, and sets the value variable to that integer. This, if the file contained the string "0", then the value of value would be 0.
Quote:
Original post by EvilKnuckles666
or even is there an internal pointer that i can get one byte at a time? or how ever many bytes i want at a time to put in some sort of buffer to handle my own way?
1° No, there is no internal pointer. There is no internal anything when using abstractions: everything you can use is external, the rest is not for your eyes to see or your fingers to type.
2° You can read one character at a time, using stream >> myCharacter. You can read one byte at a time using the stream.read(&myCharacter,1) function, or several bytes using stream.read(buffer,bytes).
3° The C++ streams provide an efficient and elegant way to read numbers in text format from a file. While you can tinker with them and adapt them to your previous way of thinking, this will result in an unelegant, inefficient and wasteful usage of both your approach and the streams themselves. Therefore, I suggest that you use the streams in the way for which they were created and optimized in the first place, instead of doing any byte manipulation yourself - or give up using them altogether. One does not use a screwdriver to plant nails.
so using the read function to read one or how ever many bytes i need is efficient? is it better than using fgetc()? that's what i've been using before but sometimes it would fail when i have a string of "0"
Quote:
Original post by EvilKnuckles666
so using the read function to read one or how ever many bytes i need is efficient? is it better than using fgetc()?
It is more akin to fread, which is more efficient than fgetc in a loop. There is no real advantage to stream.read over fread (aside from, of course, polymorphism).
Quote:
that's what i've been using before but sometimes it would fail when i have a string of "0"
I'd be more inclined to say that the cause of the error was elsewhere.
i looked up the documentation to ifstream instead of fstream and i found it said something about use read_s() instead of read() because it is potentially unsafe.. is there a reason for that? should i use read_s() instead or just use read()?
In C++, istream has no method named read_s, although certain libraries will have extensions that provide this method (in a non-portable fashion). The rationale is that, like fgets, read can overflow its buffer, resulting in a security problem for your program.
However, to read a long from a file in C++, you should not have to read the file contents to a buffer: it would be akin to shifting the bits by hand when performing an addition.
However, to read a long from a file in C++, you should not have to read the file contents to a buffer: it would be akin to shifting the bits by hand when performing an addition.
well, actually, see the way i'm handling my "long"'s are in my file i have a string of say "215", then buffer would read the "2" then the "1" then the "5", and i need to turn that into a long of 215 and store that in a variable. how would i do that with ifstream? the file i'm reading from is a csv separated by commas, i need to read each number in between the commas and store that into a long. can you post of code as to how to go about doing that?
#include<iostream> #include<vector>#include<iterator>int main() { std::istream & input = std::cin; long value; // A long number to store the read value char comma; // To store the character that follows a long std::vector<long> values; // Where we put all the values for output do { input >> value // read a long from the input >> comma; // and the character right after it values.push_back(value); // append the read value to the vector } while (input // First loop end condition: if there is a read error && comma == ','); // Second condition: if the character after the // long is not a comma (such as end of line) std::copy( // Copy values between ... values.begin(), // the first ... values.end(), // and the last element of the vector ... std::ostream_iterator<long>( std::cout, // to standard output... "\n") // and insert a newline after each of them );}This version reads data from STDIN. Use an ifstream instead of cin to read from a file.
Input:1812378,198273,127635,12873,98723,-325,2225Output:18123781982731276351287398723-3252225EDIT: comments.
[Edited by - ToohrVyk on August 8, 2006 2:52:12 PM]
i'm not exactly sure what's going on with your "input >> value >> comma".. sorry.. but can you put comments to what everything is doing? i'm not too familiar with streams and the "<<" and ">>" operator either
ohhh, alright thanks. but when it reads a long, will it read the actually number in the string? or will it read the ascii value as the long?
also, when i read "comma" which is the next character and it's NOT a ',' when it loops again, won't it skip that character because it already read it?
also, when i read "comma" which is the next character and it's NOT a ',' when it loops again, won't it skip that character because it already read it?
Quote:
Original post by EvilKnuckles666
ohhh, alright thanks. but when it reads a long, will it read the actually number in the string? or will it read the ascii value as the long?
The number in the string, as shown in the INPUT/OUTPUT example in my post.
Quote:
also, when i read "comma" which is the next character and it's NOT a ',' when it loops again, won't it skip that character because it already read it?
It will not loop again, because the loop ends when comma != ','. The character will already have been read, so it is not present in the stream anymore. You have two options: use the value stored in comma, or put the character back using input.unget();
ok, here's the new code with using your example in it. does this look correct?
ok, that should be right; how's it look to you?
bool cWTextureLayer::StoreData(std::string Filename) { if (Filename == "") return cWUtility::ErrorLog.Write("cWTextureLayer::StoreData() no Filename"); std::ifstream ifstr; std::vector<long> values; // Where we put all the values for output long value; // A long number to store the read value char comma; // To store the character that follows a long ifstr.open(Filename.c_str()); if (ifstr.is_open() == false) return cWUtility::ErrorLog.Write("cWTexture::Load() no file ", Filename); for (long i=0 ; i<m_lLayerRow && ifstr ; i++) { for (long j=0 ; j<m_lLayerCol && ifstr ; j++) { ifstr >> comma; do { if (comma != ',') ifstr.unget(); else break; ifstr >> value >> comma; values.push_back(value); } while (ifstr); std::copy(values.begin(),values.end(),m_TileData[j]); } } ifstr.close(); return true; }ok, that should be right; how's it look to you?
wait.. something's are not taken out yet.. i get too anxious hah
Quote:
Original post by EvilKnuckles666
ok, that should be right; how's it look to you?
Confused. What you are attempting to do is not obvious from your code, so I'd wager it doesn't work.
bool cWTextureLayer::StoreData(std::string Filename) { if (Filename == "") return cWUtility::ErrorLog.Write("cWTextureLayer::StoreData() no Filename"); std::ifstream ifstr; char comma; // To store the character that follows a long ifstr.open(Filename.c_str()); if (ifstr.is_open() == false) return cWUtility::ErrorLog.Write("cWTexture::Load() no file ", Filename); int i = 0, j = 0; do { ifstr >> m_tileData[j] >> comma; ++i; if (i >= m_lLayerRow) { i = 0; ++j; } } while (ifstr && comma == ',' && j < m_lLayerCol); ifstr.close(); return (j == m_lLayerCol);}EDIT: should be faster, stronger, better.
well, that is a function in my engine that loads a file of type "csv" (for now), then iterates through the characters and stores each of the long values (one number at a time) into another long value (m_TileData). m_TileData is a 2d dimenstional array of longs that specifies the tiles for a 2d map that in my Draw() function i iterate through and load that tile from a texture that i have loaded. basically in that function i just need to iterate through a csv file storing the number into the array and when a comma is seen, moves to the next array and puts the next number into that position until the file has ended
After looking at your code, i think i can see how you're confused. In the csv file here's what it looks like:
"10, 11, 0, 10, 11, 0, 8, 10, 9, 10, 8, 10, 0, 22, 0, 0,
0, 9, 0, 0, 0, 0,
10, 9, 10, 0, 9, 10, 0, 8, 53, 11, 0, 10, 8, 0, 0, 9,
0, 8, 11, 9, 10, 9,
10, 0, 8, 8, 10, 10, 9, 11, 52, 0, 10, 52, 0, 8, 11, 8,
9, 9, 11, 9, 11, 9,
0, 8, 9, 10, 9, 10, 9, 10, 9, 9, 8, 8, 0, 10, 0, 10,
0, 10, 10, 10, 9, 9,
9, 0, 11, 10, 10, 11, 9, 10, 8, 10, 0, 9, 9, 0, 53, 8,
9, 9, 0, 9, 11, 11,
8, 9, 8, 10, 9, 10, 8, 53, 9, 52, 10, 10, 9, 11, 0, 9,
0, 8, 10, 10, 9, 10,
10, 0, 10, 8, 52, 9, 10, 8, 0, 9, 8, 10, 10, 0, 8, 0,"
that's only a small portion. When the ifstr >> reads a "long" will it read (staring from the beginning), will it read the first character as a long value of 1 or will it look at the ascii value of the "1" and store that as the long?
"10, 11, 0, 10, 11, 0, 8, 10, 9, 10, 8, 10, 0, 22, 0, 0,
0, 9, 0, 0, 0, 0,
10, 9, 10, 0, 9, 10, 0, 8, 53, 11, 0, 10, 8, 0, 0, 9,
0, 8, 11, 9, 10, 9,
10, 0, 8, 8, 10, 10, 9, 11, 52, 0, 10, 52, 0, 8, 11, 8,
9, 9, 11, 9, 11, 9,
0, 8, 9, 10, 9, 10, 9, 10, 9, 9, 8, 8, 0, 10, 0, 10,
0, 10, 10, 10, 9, 9,
9, 0, 11, 10, 10, 11, 9, 10, 8, 10, 0, 9, 9, 0, 53, 8,
9, 9, 0, 9, 11, 11,
8, 9, 8, 10, 9, 10, 8, 53, 9, 52, 10, 10, 9, 11, 0, 9,
0, 8, 10, 10, 9, 10,
10, 0, 10, 8, 52, 9, 10, 8, 0, 9, 8, 10, 10, 0, 8, 0,"
that's only a small portion. When the ifstr >> reads a "long" will it read (staring from the beginning), will it read the first character as a long value of 1 or will it look at the ascii value of the "1" and store that as the long?
*SIGH*
It will read the integer 10 (as in 5+5), then the integer 11, then the integer 0. If your file contains the string 12345678, then it will read the integer 12345678. Basically, it does what atol does without forcing you to manipulate the string in the first place.
EDIT: the semantics of operator>>(std::istream &, long &) are as follows: skip any initial whitespace (space, tab, newline). Interpret any subsequent characters as part of the decimal (text) representation of a long integer, until you reach a character that cannot possibly part of such a representation. Convert the characters (which are the text representation of a long integer) into their integer value and place that value in the right-hand operand. If there are no such characters (for instance, if the file does not contain a long, but something else), do not modify the right operand and set the input stream in a "fail" state. The read cursor is placed on the first character that was not used when reading the long integer.
It will read the integer 10 (as in 5+5), then the integer 11, then the integer 0. If your file contains the string 12345678, then it will read the integer 12345678. Basically, it does what atol does without forcing you to manipulate the string in the first place.
EDIT: the semantics of operator>>(std::istream &, long &) are as follows: skip any initial whitespace (space, tab, newline). Interpret any subsequent characters as part of the decimal (text) representation of a long integer, until you reach a character that cannot possibly part of such a representation. Convert the characters (which are the text representation of a long integer) into their integer value and place that value in the right-hand operand. If there are no such characters (for instance, if the file does not contain a long, but something else), do not modify the right operand and set the input stream in a "fail" state. The read cursor is placed on the first character that was not used when reading the long integer.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement