
Remove Non-printable Characters From a String


This snippet demonstrates how to remove non-printable characters from an Igor string. This was prompted by a question in the forum. See the Working With Binary String Data Examples snippet for similar examples.
Igor Pro 9.00B08 introduced new features that make this process much faster, but the transformation can also be done using earlier versions of Igor. If your code only needs to run with Igor Pro 9, you only need the RemoveNonPrintableChars_IP9 function below. Otherwise I recommend that you include both functions and only directly call RemoveNonPrintableChars() so that when your code runs with Igor Pro 9 or later the faster function will automatically be used.
Function/S RemoveNonPrintableChars_IP8(String inStr) // Store the bytes of the string in a byte wave so we can // use wave related commands. Variable len = strlen(inStr) Make/FREE/B/U/N=(len) byteWave byteWave = char2num(inStr[p]) // Set all non-printable characters to 0 (null) // The test below considers tab (9), line feed (10), and carriage return (13) // to be printable characters. MultiThread byteWave = (byteWave[p] >= 32 && byteWave[p] <= 126) || (byteWave[p] == 9 || byteWave[p] == 10 || byteWave[p] == 13) ? byteWave[p] : 0 // Extract the non-null values from the wave. These are the printable characters. Extract/O/FREE/B/U byteWave, printableByteWave, byteWave[p] > 0 // Convert the wave's data back to a string. Variable np = numpnts(printableByteWave) String outStr = "" outStr = PadString(outStr, np, 0) Variable n For (n=0; n < np; n++) outStr[n,n] = num2char(printableByteWave[n]) EndFor return outStr End #if IgorVersion() >= 9 Function/S RemoveNonPrintableChars_IP9(String inStr) // Store the bytes of the string in a byte wave so we can // use wave related commands. WAVE/B/U byteWave = StringToUnsignedByteWave(inStr) // Set all non-printable characters to 0 (null) // The test below considers tab (9), line feed (10), and carriage return (13) // to be printable characters. MultiThread byteWave = (byteWave[p] >= 32 && byteWave[p] <= 126) || (byteWave[p] == 9 || byteWave[p] == 10 || byteWave[p] == 13) ? byteWave[p] : 0 WaveTransform zapZeros, byteWave // Remove all of the nulls from the wave String outStr = WaveDataToString(byteWave) // Convert the bytes in the wave back into a string. return outStr End #endif // IP9+ Function/S RemoveNonPrintableChars(String inStr) #if IgorVersion() >= 9 return RemoveNonPrintableChars_IP9(inStr) // MUCH faster #else return RemoveNonPrintableChars_IP8(inStr) #endif End
You can execute this test function to compare the performance between the IP8 and IP9 versions of the function.
Function testTime() Variable n Variable numTrials = 100 Variable testStringLength = 1e5 // length of test string in bytes // Generate a test string that contains random bytes. String testString = "" testString = PadString(testString, testStringLength, 0) For (n=0; n < testStringLength; n++) testString[n,n] = num2char(trunc(abs(enoise(255))), 1) EndFor String outStr_IP8 Variable aStart = StopMSTimer(-2) For (n=0; n < numTrials; n++) outStr_IP8 = RemoveNonPrintableChars_IP8(testString) EndFor Variable aStop = StopMSTimer(-2) Variable usingIP9OrLater = 0 // assume not using IP9 or later #if IgorVersion() >= 9 String outStr_IP9 Variable bStart = StopMSTimer(-2) For (n=0; n < numTrials; n++) outStr_IP9 = RemoveNonPrintableChars_IP9(testString) EndFor Variable bStop = StopMSTimer(-2) // Make sure that the two methods give the same result. if (CmpStr(outStr_IP8, outStr_IP9, 2) == 0) print "The two methods give the exact same result." else print "WARNING: The two methods give different results." endif printf "RemoveNonPrintableChars_IP8: %g s RemoveNonPrintableChars_IP9: %g s %d trials.\r", (aStop-aStart)/1e6, (bStop-bStart)/1e6, numTrials #else printf "RemoveNonPrintableChars_IP8: %g s %d trials.\r", (aStop-aStart)/1e6, numTrials #endif End
Here is what I get using Igor Pro 9.00B08:
•testTime() The two methods give the exact same result. RemoveNonPrintableChars_IP8: 3.93585 s RemoveNonPrintableChars_IP9: 0.207991 s 100 trials.

Forum

Support

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