How to print only printable charcters in binary file (equvalent to strings under Linux)?
<p>I am undertaking conversion of my python application from python 2 to python 3. One of the functions which I use is to get the printable character out of binary file. I earlier used following function in python 2 and it worked great:</p>

<pre><code>import string

def strings(filename, min=4):
    with open(filename, "rb") as f:
        result = ""
        for c in f.read():
            if c in string.printable:
                result += c
                continue
            if len(result) &gt;= min:
                yield result
            result = ""
        if len(result) &gt;= min:  # catch result at EOF
            yield result
</code></pre>

<p>Code is actually from <a href="http://stackoverflow.com/questions/17195924/python-equivalent-of-unix-strings-utility">Python equivalent of unix &quot;strings&quot; utility</a>. When I run the above code with python 2 it produces the output like this which is absolutely ok for me:</p>

<pre><code> +s
^!1^
i*Q(
}"~ 
%lh!ghY
#dh!
!`,!
mL#H
o!&lt;XXT0
'   &lt; 
z !Uk
%
 wS
n`  !wl
*ty

(Q  6
!XPLO$
E#kF
</code></pre>

<p>However, the function gives weird results under python 3. It produces the error:</p>

<pre><code>TypeError: 'in &lt;string&gt;' requires string as left operand, not int
</code></pre>

<p>So I converted the 'int' to 'str' by replacing this </p>

<pre><code>if c in string.printable:
</code></pre>

<p>with this</p>

<pre><code>if str(c) in string.printable:
</code></pre>

<p>(I also converted all the places where the same error message is thrown)</p>

<p>Now the python 3 gives the following output:</p>

<pre><code>56700
0000000000000000000000000000000000000000
1236
60000
400234
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2340
0000
5010
5000
17889
2348
23400000000
5600
</code></pre>

<p>I cant see any characters when I use python 3. Any help to get the code working or pointer to the solution is appreciated. All I require is to extract the strings from binary file (very small with few kb) and store it in a variable.</p>

<p>
I am sure this will work.  </p>

<p>As a generator:</p>

<pre class="lang-py prettyprint-override"><code>import string, _io
def getPrintablesFromBinaryFile(path, encoding='cp1252'):
    global _io, string
    buffer = _io.BufferedReader(open(path, 'rb'))
    while True:
        byte = buffer.read(1)
        if byte == b'':
            return #EOF
        try:
            d = byte.decode(encoding)
        except:
            continue
        if d in string.printable:
            yield d
</code></pre>

<p>As a function is to just collect the outputs of the getPrintablesFromBinaryFile() into a iterable.</p>

<p>Explanation:</p>

<ol>
<li>Import the needed modules</li>
<li>Define the function</li>
<li>Load the modules</li>
<li>Create the buffer</li>
<li>Get a byte from the buffer</li>
<li>Check if it is EOF</li>
<li>If yes, stop the generator</li>
<li>Try to decode using the encoding (like <code>'\xef'</code> does not decode using UTF-8)</li>
<li>If impossible, it cannot be a printable</li>
<li>If printable, yield it</li>
</ol>

<p><strong>Note:</strong> <code>cp1252</code> is the encoding for many text files</p>

python string python-3.x