
Rudimentary Binary File Reader

jamie
#pragma rtGlobals=1 // Use modern global access method. #pragma IgorVersion=5 #pragma IndependentModule=BinaryReader //BinaryReader helps you peek into binary files on disk to see what is inside of them. // Useful if, e.g., you are making your own file loader and need to read headers and find offsets and see what kind of data is in the file. //modified Nov 19 2007 // made independent module Constant kSegmentSize = 10000 //how many bytes of the file we are going to show at one time menu "Data" Submenu "packages" "Binary File Reader", BinaryReader# BinaryFileReader () end end //***************************************************************************************************** //make the packages folder and the global variables and the control panel Function BinaryFileReader () if (!(datafolderexists ("root:packages:"))) newdatafolder root:packages endif if (!(datafolderexists ("root:packages:BinaryReader"))) newdatafolder root:packages:BinaryReader //make waves for the list box showing the first segment of data in the selected file make/o/t/n = (kSegmentSize,2) root:packages:BinaryReader:FileListWave make/o/n = (kSegmentSize,2) root:packages:BinaryReader:FileListSelWave //Make a text wave for the listbox that shows the data after being loaded according to the chosen specs make/t/o/n=(1,2) root:packages:BinaryReader:OutPutWave //make a temporary wave to read data into before displaying it in the listbox make/o/n = (kSegmentSize) root:packages:BinaryReader:TempWave //First row of waves will show byte offset SetDimLabel 1,0,BytePos,root:packages:BinaryReader:FileListWave SetDimLabel 1,0,BytePos root:packages:BinaryReader:OutPutWave //Second row will show the data as a character SetDimLabel 1,1,Char,root:packages:BinaryReader:FileListWave //a global string to contain a list of segments in the file for loading string/G root:packages:BinaryReader:SegmentsList = "" //global variable to hold reference nmber to the open file variable/G root:packages:BinaryReader:BRrefNum = nan //global string to display name of open file in a title box string/G root:packages:BinaryReader:fileNameStr = "" endif //try to bring panel to the front doWindow/F Binary_Reader if (V_Flag) return 1 endif //make the panel, as it was not already open NewPanel /K=1 /W=(78,105,534,452) as "Binary Reader" DoWindow/C Binary_Reader ListBox FileAsByteList,pos={215,25},size={101,319} ListBox FileAsByteList,help={"Shows the selected segment of data in the selected file as characters"} ListBox FileAsByteList,listWave=root:packages:BinaryReader:FileListWave ListBox FileAsByteList,selWave=root:packages:BinaryReader:FileListSelWave ListBox FileAsByteList,mode= 3,widths={20,13} Button OpenFileButton,pos={7,2},size={67,22},proc=BRopenFIleProc,title="Open File" TitleBox FileNameTitle,pos={79,3},size={383,20} TitleBox FileNameTitle,variable= root:packages:BinaryReader:fileNameStr PopupMenu SegmentsPopup,pos={7,31},size={99,20},proc=BRLoadSegmentProc,title="Load Segment" PopupMenu SegmentsPopup,mode=1,popvalue="0",value= #"root:packages:BinaryReader:SegmentsList" PopupMenu EndianPopUp,pos={11,121},size={178,20},title="Byte Order" PopupMenu EndianPopUp,mode=1,popvalue="Big-endian (Mac)",value= #"\"Big-endian (Mac);Little-endian (Win)\"" PopupMenu UnSignedPopup,pos={9,96},size={134,20},title="Integer Data is" PopupMenu UnSignedPopup,mode=1,popvalue="Signed",value= #"\"Signed;UnSigned\"" PopupMenu DataFormatPopUp,pos={10,72},size={140,20},title="Data Format" PopupMenu DataFormatPopUp,mode=1,popvalue="1 byte int",value= #"\"1 byte int;2 byte int (word);4 byte int;4 byte float;8 byte float (double)\"" Button ShowSelectionButton,pos={39,149},size={101,27},proc=BRShowSelection,title="Show Selection" ListBox OutPutList,pos={323,27},size={129,315} ListBox OutPutList,listWave=root:packages:BinaryReader:OutPutWave SetWindow kwTopWin,hook=BRCloseHook EndMacro //***************************************************************************************************** //Close the open file when the Binary_Reader panel is closed and also kill the packages folder Function BRCloseHook (infoStr) String InfoStr if ((cmpstr (stringByKey ("EVENT", infoStr), "kill")) == 0) NVAR BRrefNum = root:packages:BinaryReader:BRrefNum variable LocalRefNum = BRrefNum FStatus LocalRefNum if (V_Flag) Close LocalRefNum endif killdatafolder/Z root:packages:BinaryReader endif end //***************************************************************************************************** //Open a file on disk, save the refernce number in a global variable, and load the first segment of the file Function BRopenFIleProc(ctrlName) : ButtonControl String ctrlName //make reference to global variables SVAR fileNameStr =root:packages:binaryReader:fileNameStr NVAR BRrefNum = root:packages:BinaryReader:BRrefNum variable localRefNum = BRrefNum SVAR segmentsList = root:packages:BinaryReader:SegmentsList segmentsList = "" WAVE/T fileListWave = root:packages:BinaryReader:FileListWave WAVE fileListSelWave = root:packages:BinaryReader:FileListSelWave WAVE tempwave = root:packages:BinaryReader:tempwave //close the file that was previously open, if any FStatus localRefNum if (V_Flag) Close localRefNum BRrefNum = Nan endif //Open a new file chosen by the user and save the refnum in the global variable Open /M="Choose a file to examine"/R localRefNum fileNameStr = S_fileName if ((cmpstr (S_fileName, "")) == 0) BRrefNum = nan fileListWave [] [1] = "" return 0 else BRrefNum = localRefNum endif //Find the number of segments in the file, and make the list of segments used in the popmenu FStatus localRefNum variable ii, numSegments = ceil (V_logEOF/kSegmentSize) for (ii = 0; ii < numSegments; ii += 1) segmentsList += num2str (ii) + ";" endfor //Load the first Segment in the file BRLoadSegmentProc("",1,"") PopupMenu SegmentsPopup mode=1 End //***************************************************************************************************** //Show the data selected in the file listbox in the output list box by loading the data from the file with the selected options Function BRShowSelection(ctrlName) : ButtonControl String ctrlName //Make references to globals NVAR BRrefNum = root:packages:BinaryReader:BRrefNum variable localRefNum = BRrefNum WAVE/T fileListWave = root:packages:BinaryReader:FileListWave WAVE fileListSelWave = root:packages:BinaryReader:FileListSelWave WAVE tempwave = root:packages:BinaryReader:tempwave WAVE/T outputWave = root:packages:BinaryReader:OutPutWave //make sure file reference is valid FStatus localRefNum if (!(V_Flag)) SVAR FileNameStr = root:packages:BinaryReader:FileNameStr doalert 0, "The selected file, " + FileNameStr +", is not open." FileNameStr = "" return 1 endif //find the start and end of the selection in the file listbox variable ii, startpos =0,numBytes=0 for (ii = 0; ii < kSegmentSize; ii += 1) if (fileListSelWave [ii] [0] == 1) break endif endfor StartPos = ii for (;ii < kSegmentSize; ii += 1) if (fileListSelWave [ii] [0] == 0) break endif endfor numBytes = (ii - StartPos) //we will read the selected bit of the file into the temporary wave according to the choices on these panel popups controlinfo DataFormatPopUp variable DataFormat = V_Value //choices in menu listed in same order as for /F= option in FBinRead command controlinfo UnSignedPopup variable UnSigned = V_Value -1 //0 for Signed (default in FBInRead) 1 for unsigned (requires/U option) controlinfo EndianPopUp variable byteOrder = V_Value + 1 //byteorder will be 2 for bigendian, 3 for small endian to specify endian in FBinRead command //set the numtype variable according to Wavemetrics conventions variable theNumType = 0 variable dataBytes //this variable will hold the number of bytes per data point if ((DataFormat < 4) && (UnSigned)) theNumType += 64 endif switch (DataFormat) case 1: //byte theNumType += 8 dataBytes = 1 SetDimLabel 1,1,Byte,root:packages:BinaryReader:OutPutWave break case 2: // 2 byte word theNumtype += 16 numbytes =floor(numBytes/2) dataBytes = 2 SetDimLabel 1,1,Word,root:packages:BinaryReader:OutPutWave break case 3: // 32 bit int theNumtype += 32 numBytes = floor(numBytes/4) dataBytes = 4 SetDimLabel 1,1,LongInt,root:packages:BinaryReader:OutPutWave break case 4: //32 bit float theNumType += 2 numBytes= floor(numBytes/4) dataBytes = 4 SetDimLabel 1,1,Float,root:packages:BinaryReader:OutPutWave break case 5: //64 bit floating point theNumType += 4 numBytes=floor(numBytes/8) databytes = 8 SetDimLabel 1,1,Double,root:packages:BinaryReader:OutPutWave break default: doalert 0, "uh oh, the Numtype Switch did not recognize the value, " + num2str (DataFormat) + "." return 1 break endswitch //check that data is selected if (numBytes == 0) doalert 0, "First select part of the file to show. For multibyte data formats, you need to select enough bytes to show at least one point" return 1 endif //Redimension the temp wave for the amount and kind of data expected Redimension/N = (numBytes)/Y=(theNumType) TempWave Redimension/N = ((numBytes),2) OutPutWave //load the selected data into the temp wave fsetpos localRefNum, (str2num (fileListWave [StartPos] [0])) if (UnSigned) FBinRead /B=(byteOrder)/F=(DataFormat) localRefNum, TempWave else FBinRead /B=(byteOrder)/F=(DataFormat)/U localRefNum, TempWave endif //Show the data in the output wave OutPutWave [] [0] = num2Str (str2Num (fileListWave [StartPos] [0])+ (p * databytes)) OutPutWave [] [1]= num2str (tempwave [p]) End //***************************************************************************************************** //Load the segment selected from the popup menu Function BRLoadSegmentProc(ctrlName,popNum,popStr) : PopupMenuControl String ctrlName Variable popNum String popStr //References to globals SVAR fileNameStr =root:packages:binaryReader:fileNameStr NVAR BRrefNum = root:packages:BinaryReader:BRrefNum variable localRefNum = BRrefNum WAVE/T fileListWave = root:packages:BinaryReader:FileListWave WAVE FileListSelWave = root:packages:BinaryReader:FileListSelWave WAVE tempwave = root:packages:BinaryReader:tempwave popnum -= 1 //should be 0 based //check that the file reference is valid fstatus localRefNum if (!(V_Flag)) doAlert 0, "The file, " + fileNameStr + " is not open." FileNameStr = "" endif //load the segment into the temp wave. If it is last segment, only load to the end of the file if (V_logEOF < ((popNum+1) * kSegmentSize)) redimension/n = (V_logEOF-(popNum * kSegmentSize)) tempwave redimension/n = ((V_logEOF-(popNum * kSegmentSize)), 2) fileListWave, fileListSelWave else redimension/n = (kSegmentSize) tempwave redimension/n = ((kSegmentSize), 2) fileListWave, fileListSelWave endif FSetPos localRefNum, (popNum * kSegmentSize) FBinRead/f=1/u localRefNum, tempwave //show the loaded segment in the fileListBox in char format. Print out the most common escape codes variable ii, points = numpnts (tempwave) for (ii=0;ii< points;ii+=1) switch (tempWave [ii]) case 0: fileListWave [ii] [1] = "NUL" break case 9: fileListWave [ii] [1] = "HorTab" break case 10: fileListWave [ii] [1] = "LineFeed" break case 11: fileListWave [ii] [1] = "VerTab" break case 12: fileListWave [ii] [1] = "FormFeed" break case 13: fileListWave [ii] [1] = "Return" break default: if (tempwave [ii] < 32) fileListWave [ii] [1] = "Other Control" else fileListWave [ii] [1] =num2char ( tempwave [ii]) endif break endswitch endfor FileListWave [] [0] = num2Str((popNum * kSegmentSize)+ p) End

Forum

Support

Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More