I am wondering whether there is any built-in operation/function to read some specific line of a text file. The only operation I find is FReadLine but it can only read the line from the current position of the file...
// ReadThisLine(pathName, filePath, whichLine, data) // Reads specified line number from file. Text is returned via data parameter. // pathName is the name of an Igor symbolic path (see "Symbolic Paths" help topic). // filePath is a file name, partial path or full path. // If filePath is a full path then pathName can be "". // The function result is 0 if the line was found, non-zero otherwise. // Because the data is returned through a pass-by-reference parameter, // this function can not be called from the command line. It must be // called from another function. // Example: // String data // Variable err = ReadThisLine("Igor", "License Agreement.txt", 2, data) // Print data Function ReadThisLine(pathName, filePath, whichLine, data) String pathName // Name of Igor symbolic path String filePath // File name, partial path or full path Variable whichLine // 0-based line number
String& data // Output
data = ""
Variable refNum
Open/R/P=$pathName refNum as filePath
Variable lineNumber = 0 do String tmpData FReadLine refNum, tmpData if(strlen(tmpData) == 0) return -1// Error - end of file endif if(lineNumber == whichLine)
data = tmpData return0// Success endif
lineNumber += 1 while(1) End
Function DemoReadThisLine() String data Variable err = ReadThisLine("Igor", "License Agreement.txt", 2, data) Print err, data End
Seems like a good idea to close the file afterward:
if(strlen(tmpData) == 0) close refNum return -1// Error - end of file endif if(lineNumber == whichLine)
data = tmpData close refNum return0// Success endif
I might also point out that this function reads the file from the beginning, one line at a time. In fact, that's the only way it could work since "lines" can be any number of bytes. You have to read the line to know where it ends and the next begins. So if you are going to read several lines, it is best to create a modified version that doesn't close the file, and keeps track of which line it is currently reading from. That way you don't have to re-read from the beginning for every line you need to read.
Assuming you are looking for some specific information, you could just use Grep
e.g. Grep/Q/LIST/E="Date: ""C:data:filename.csv"
creates a string named S_value in the current data folder containing any line that includes "Date: " in your file. If you learn regular expressions it's quite powerful; if you don't want to learn them just be careful with brackets and parentheses, as you might have to escape (\) them
My intention is to acquire certain lines embraced by two lines which carry some specific marks. I used GREP with /INDX to catch the line numbers of these two lines but found no existed function/operation could finish the job...
If the file uses single character line endings (that is, \r or \n but not \r\n), you could read the entire file into a string variable and then use StringFromList() to get a single line from the string. Alternately, you could use Grep with a target regular expression that is effectively "CRLF or CR or LF" and store the results in a text wave. The text wave would then have every line of the file in a different row of the wave, so getting a particular line is easy. Neither of these methods is optimal if the file is large, however.
// Reads specified line number from file. Text is returned via data parameter.
// pathName is the name of an Igor symbolic path (see "Symbolic Paths" help topic).
// filePath is a file name, partial path or full path.
// If filePath is a full path then pathName can be "".
// The function result is 0 if the line was found, non-zero otherwise.
// Because the data is returned through a pass-by-reference parameter,
// this function can not be called from the command line. It must be
// called from another function.
// Example:
// String data
// Variable err = ReadThisLine("Igor", "License Agreement.txt", 2, data)
// Print data
Function ReadThisLine(pathName, filePath, whichLine, data)
String pathName // Name of Igor symbolic path
String filePath // File name, partial path or full path
Variable whichLine // 0-based line number
String& data // Output
data = ""
Variable refNum
Open /R /P=$pathName refNum as filePath
Variable lineNumber = 0
do
String tmpData
FReadLine refNum, tmpData
if (strlen(tmpData) == 0)
return -1 // Error - end of file
endif
if (lineNumber == whichLine)
data = tmpData
return 0 // Success
endif
lineNumber += 1
while(1)
End
Function DemoReadThisLine()
String data
Variable err = ReadThisLine("Igor", "License Agreement.txt", 2, data)
Print err, data
End
November 21, 2010 at 04:07 pm - Permalink
close refNum
return -1 // Error - end of file
endif
if (lineNumber == whichLine)
data = tmpData
close refNum
return 0 // Success
endif
I might also point out that this function reads the file from the beginning, one line at a time. In fact, that's the only way it could work since "lines" can be any number of bytes. You have to read the line to know where it ends and the next begins. So if you are going to read several lines, it is best to create a modified version that doesn't close the file, and keeps track of which line it is currently reading from. That way you don't have to re-read from the beginning for every line you need to read.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
November 22, 2010 at 10:35 am - Permalink
I did the similar things in my code and I just wondered I might just reinvent the wheels.
November 22, 2010 at 04:44 pm - Permalink
e.g.
Grep/Q/LIST/E="Date: " "C:data:filename.csv"
creates a string named S_value in the current data folder containing any line that includes "Date: " in your file. If you learn regular expressions it's quite powerful; if you don't want to learn them just be careful with brackets and parentheses, as you might have to escape (\) them
November 25, 2010 at 07:41 am - Permalink
November 26, 2010 at 08:53 am - Permalink
StringFromList()
to get a single line from the string. Alternately, you could use Grep with a target regular expression that is effectively "CRLF or CR or LF" and store the results in a text wave. The text wave would then have every line of the file in a different row of the wave, so getting a particular line is easy. Neither of these methods is optimal if the file is large, however.November 26, 2010 at 03:41 pm - Permalink