Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Oct 29th, 2007, 7:54 PM   #1
Adeil
Newbie
 
Join Date: Mar 2005
Location: St. Louis, USA
Posts: 3
Rep Power: 0 Adeil is on a distinguished road
Send a message via ICQ to Adeil Send a message via AIM to Adeil Send a message via MSN to Adeil Send a message via Yahoo to Adeil
Jumping to a specific line number in a text file

Hello, a friend has asked me to make a program for him, and in this program i need to read lines and interpret them from a script-type of file (by script-type, it will have text in it with commands that the program will execute, script as in typed script...kind of like what the web browser does with JavaScript.)

What i would like to know is if there is an easy way to just jump to a certain line in a text file, like line 687, for example, without having to start from the beginning and read each line to get to line 687?

If there isnt, i was planning on using something like this, but if you know a more efficient way that would be great.

c++ Syntax (Toggle Plain Text)
  1. char buffer[256];
  2. ifstream fi;
  3. fi.open(INPUT_FILE);
  4. for(int i=1; i<lineNumber; i++)
  5. {
  6. if(fi.eof())
  7. {
  8. // ran out of lines before lineNumber, handle the error with output maybe
  9. fi.close();
  10. break;
  11. }
  12. fi.getline(buffer,sizeof(buffer));
  13. }
  14. if(fi.is_open())
  15. {
  16. // the next fi.getline will have all the contents of that line
  17. fi.close();
  18. }

On a slightly different track, but on the same subject, would it be effective to load the entire text file into a multi-dimensional array, so for line 687 i could just call lines[686] (because lines[0] would be the line number 1)?
Adeil is offline   Reply With Quote
Old Oct 29th, 2007, 8:09 PM   #2
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
Re: Jumping to a specific line number in a text file

A file with variable length lines has no way to directly address lines other than by counting line endings. Line endings are not magical, they're just another binary code, like the rest of the file.

A file with fixed length lines, via padding, can be address by using fseek (or the appropriate equivalent).

Disk I/O is orders of magniture slower than memory access, so your final question depends upon whether you will be accessing the data more than once, or in random order. In the latter case, reading lines into a 2D array would be advisable sometimes, depending upon the probability that you might have to access any line in the file.

You're going to have to read all the lines that occur before the latest line you have to deal with (assuming the variable length lines). If there's a significant probability that you're going to need the earlier lines at some point, then you may as well save them in memory and preclude having to do the slow mechanical operations more than once.

You might also investigate memory-mapped files.

It's situations like this that take you beyond your language and into the implementation of the system as a piece of hardware and as a system governed by some particular OS and the functions thereof.

If you're going to encounter this sort of thing very often, digging a little deeper into the actual implementations might be advisable.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Oct 30th, 2007, 2:28 AM   #3
lectricpharaoh
Caffeinated Neural Net
 
lectricpharaoh's Avatar
 
Join Date: Jun 2005
Location: Dry west coast of Canada
Posts: 925
Rep Power: 4 lectricpharaoh will become famous soon enough
Re: Jumping to a specific line number in a text file

You could load the lines into an array. Whether or not this is a practical solution depends a lot on what you're doing with them, and how big the files are. Presumably, since it's a script, you're wanting to jump from line to line in a random-access fashion to handle logic flow constructs, such as loops and conditionals.

Assuming this is the case, your best bet is to allocate a block of memory big enough to hold the file, and load it into this buffer. You can then iterate through the file, counting the newlines at the end, and determine from this how many lines are in the file (remember that the last line may not end with a newline). Allocate an array of this many size_t elements, and then iterate through the buffer again, filling the size_t array with the line offsets (ie, the buffer positions of the start of each line). Now you can use fseek() to jump to the start of any line you like, without needing to read the file (this is dependent on the file not changing during your program's run, of course). A variant on this, if you're comfortable with the vector template type, is to create a size_t vector, and fill it in as you count lines. This avoids a second pass through the buffer, but has the drawback of potentially wasting an arbitrary amount of memory, depending on what size you pick for your vector.

The above method requires you to know how to find the file's size; you can check your OS and compiler for API or library methods to do this. If you can't find any such methods, an alternative is to fseek() to the file's end, and then use ftell() to get the position.

The reason to do it this way, rather than allocate a separate block for each line in the file, is to avoid so many calls to new. Each allocation will incur overhead, and if you can minimize the number of allocations, you're better off. Another drawback to repetitive allocations is fragmentation of the heap, but this depends a lot on how you're doing things.
__________________
A man's knowledge is like an expanding sphere, the surface corresponding to the boundary between the known and the unknown. As the sphere grows, so does its surface; the more a man learns, the more he realizes how much he does not know. Hence, the most ignorant man thinks he knows it all. - L. Sprague de Camp
lectricpharaoh is offline   Reply With Quote
Old Oct 30th, 2007, 1:38 PM   #4
Adeil
Newbie
 
Join Date: Mar 2005
Location: St. Louis, USA
Posts: 3
Rep Power: 0 Adeil is on a distinguished road
Send a message via ICQ to Adeil Send a message via AIM to Adeil Send a message via MSN to Adeil Send a message via Yahoo to Adeil
Re: Jumping to a specific line number in a text file

Thank you two for the speedy replies. I think i will use vectors, i had forgotten about them until you mentioned them, lectricpharaoh. I will also look up "memory-mapped files" on google and see what i can find out about them.

The lines of the file will be variable lengths and the program will need to be able to go to any specific line at any time and read from there on (like loops.)

As for my OS and compiler, i am running Windows XP and using GNU GCC Compiler.
Adeil is offline   Reply With Quote
Old Nov 5th, 2007, 9:54 AM   #5
Soulstorm
Hobbyist Programmer
 
Soulstorm's Avatar
 
Join Date: Jan 2006
Location: Menidi, Athens, Greece
Posts: 234
Rep Power: 3 Soulstorm is on a distinguished road
Re: Jumping to a specific line number in a text file

cpp Syntax (Toggle Plain Text)
  1. class Floader{
  2. stdVector<stdString> loadedData;
  3. public:
  4. //constructors
  5. Floader(const char *);
  6. Floader(){}
  7. //data manipulation
  8. void resetData();
  9. void loadDataFromFile(const char *);
  10.  
  11. int size();
  12. stdString getLine(int);
  13. void showContents();
  14. void outputToFile(const char *);
  15. stdString str();
  16.  
  17.  
  18. stdString& operator[](int num){return loadedData[num];}
  19. Floader operator=(Floader&);
  20. Floader operator+(stdString &str){
  21. loadedData.push_back(str);
  22. return *this;
  23. }
  24.  
  25. stdVector<stdString>& getLoadedData();
  26.  
  27. //Delete Lines. You can insert as many variables as you want
  28. //At the end of the arguments, terminate with -1 as the last
  29. //argument
  30. void deleteLines(int line ... );
  31. void deleteLinesContainingCharacters(stdString str);
  32.  
  33. void loadDataFromString(const char* str);
  34. //--Look at the implementation file for this function...
  35. friend stdOstream& operator<<(stdOstream &stream, Floader &ob);
  36.  
  37.  
  38. void cleanup();
  39. void cleanupForSoulParser();
  40. };
  41.  
  42.  
  43. //IMPLEMENTATION
  44.  
  45.  
  46. Floader::Floader(const char *fileName){
  47. loadDataFromFile(fileName);
  48. }
  49.  
  50.  
  51. void Floader::resetData(){
  52. loadedData.clear();
  53. }
  54.  
  55. void Floader::loadDataFromFile(const char *fileName){
  56. int i;
  57. resetData();
  58. stdString line;
  59. fstream myFile(fileName);
  60. for (i=0; myFile.good(); i++) {
  61. getline(myFile,line);
  62. loadedData.push_back(line);
  63. }
  64.  
  65. myFile.close();
  66. stdCout << "Process completed\n";
  67. }
  68.  
  69. int Floader::size(){
  70. return loadedData.size();
  71. }
  72.  
  73. stdString Floader::getLine(int pos){
  74. return loadedData[pos];
  75. }
  76.  
  77. void Floader::showContents(){
  78. int i;
  79. for (i=0; i<loadedData.size(); i++) {
  80. stdCout << loadedData[i] << "\n";
  81. }
  82. }
  83.  
  84.  
  85. void Floader::deleteLines(int line ... )
  86. {
  87. va_list VL;
  88. va_start(VL, line);
  89. for (;;) {
  90. int p= va_arg(VL, int);
  91. try {
  92. if(p<0)
  93. break;
  94. else if (p < loadedData.size()) {
  95. stdVector<stdString>::iterator alpha;
  96. alpha = loadedData.begin();
  97. for (int i=0; i<line; i++)
  98. alpha++;
  99. loadedData.erase(alpha);
  100. }
  101. else
  102. throw argument_out_of_bounds(p,INTEGER);
  103.  
  104. }
  105. catch (argument_out_of_bounds& error) {
  106. error.description();
  107. }
  108. }
  109.  
  110. va_end(VL);
  111. }
  112.  
  113.  
  114. void Floader::outputToFile(const char *filename){
  115. int i;
  116. stdOfstream outFile(filename);
  117. for (i=0; i<loadedData.size(); i++) {
  118. outFile << loadedData[i] << "\n";
  119. }
  120. outFile.close();
  121. }
  122.  
  123. stdString Floader::str(){
  124. stdString result;
  125. for (int i=0; i<loadedData.size(); i++) {
  126. result = result + '\n' + loadedData[i];
  127. }
  128. return result;
  129. }
  130.  
  131. stdVector<stdString>& Floader::getLoadedData(){
  132. return loadedData;
  133. }
  134.  
  135. void Floader::deleteLinesContainingCharacters(stdString str){
  136. for (int i=0; i<loadedData.size(); i++) {
  137. if (loadedData[i].find(str) != stdString::npos){
  138. loadedData.erase(loadedData.begin()+i);
  139. deleteLinesContainingCharacters(str);
  140. }
  141. }
  142. }
  143.  
  144. void Floader::cleanup(){
  145. for (int i=0; i<loadedData.size(); i++) {
  146. stdString str = loadedData[i];
  147. str = clearStringFromSpaces(str);
  148. loadedData[i] = str;
  149. if( str == "\n" || str.length() <=1 ){
  150. loadedData.erase(loadedData.begin() + i);
  151. cleanup();
  152. }
  153. }
  154. }
  155.  
  156. void Floader::cleanupForSoulParser(){
  157. for (int i=0; i<loadedData.size(); i++) {
  158. stdString str = loadedData[i];
  159. if (str.find(char(OPENING_BRACKET)) == string::npos) {
  160. str = clearStringFromSpaces(str);
  161. loadedData[i] = str;
  162. if( str == "\n" || str.length() <=1 ){
  163. loadedData.erase(loadedData.begin() + i);
  164. cleanupForSoulParser();
  165. }
  166. }
  167. }
  168. }
  169.  
  170. void Floader::loadDataFromString(const char* str){
  171. stdStringStream SStream;
  172. SStream << str;
  173. stdString line;
  174. while (SStream.good()) {
  175. getline(SStream,line);
  176. loadedData.push_back(line);
  177. }
  178.  
  179. }
  180.  
  181. //----------------------FRIEND FUNCTIONS----------------------
  182. stdOstream& operator<<(stdOstream &stream, Floader &ob){
  183. for (int i=0; i<ob.size(); i++) {
  184. stream << ob[i] <<'\n';
  185. }
  186. return stream;
  187. }

It's from an old project of mine. It will have a file as an input and will result in a vector holding the lines. I hope it helps you.
__________________
Project::Soulstorm (personal homepage)
Soulstorm is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Dynamic form from text file. randum77 Visual Basic .NET 4 Apr 24th, 2007 11:39 AM
Adding more info to a text file without erasing crawforddavid2006 C# 2 Apr 11th, 2007 2:10 PM
Changing a line in a text file Dietrich Python 2 Aug 26th, 2006 2:35 PM
Installing IPB 2.03 bh4575 Other Web Development Languages 0 Apr 23rd, 2005 2:36 AM
reading a random line from a text file cloud- Visual Basic 11 Apr 8th, 2005 1:34 PM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 2:40 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC