def majority_vote_byte_scan(relfilepath, fileslist, outpath, blocksize=65535, default_char_null=False):
    '''Takes a list of files in string format representing the same data, and disambiguate by majority vote: for position in string, if the character is not the same accross all entries, we keep the major one. If none, it will be replaced by a null byte (because we can't know if any of the entries are correct about this character).
    relfilepath is the filename or the relative file path relative to the parent directory (ie, this is the relative path so that we can compare the files from several directories).'''
    # The idea of replication combined with ECC was a bit inspired by this paper: Friedman, Roy, Yoav Kantor, and Amir Kantor. "Combining Erasure-Code and Replication Redundancy Schemes for Increased Storage and Repair Efficiency in P2P Storage Systems.", 2013, Technion, Computer Science Department, Technical Report CS-2013-03
    # But it is a very well known concept in redundancy engineering, usually called triple-modular redundancy (which is here extended to n-modular since we can supply any number of files we want, not just three).
    # Preference in case of ambiguity is always given to the file of the first folder.

    fileshandles = []
    for filepath in fileslist:
        if filepath:
            # Already a file handle? Just store it in the fileshandles list
            if hasattr(filepath, 'read'):
                fileshandles.append(filepath)
            # Else it's a string filepath, open the file
            else:
                fileshandles.append(open(filepath, 'rb'))

    # Create and open output (merged) file, except if we were already given a file handle
    if hasattr(outpath, 'write'):
        outfile = outpath
    else:
        outpathfull = os.path.join(outpath, relfilepath)
        pardir = os.path.dirname(outpathfull)
        if not os.path.exists(pardir):
            os.makedirs(pardir)
        outfile = open(outpathfull, 'wb')

    # Cannot vote if there's not at least 3 files!
    # In this case, just copy the file from the first folder, verbatim
    if len(fileshandles) < 3:
        # If there's at least one input file, then copy it verbatim to the output folder
        if fileshandles:
            create_dir_if_not_exist(os.path.dirname(outpathfull))
            buf = 1
            while (buf):
                buf = fileshandles[0].read()
                outfile.write(buf)
                outfile.flush()
        return (1, "Error with file %s: only %i copies available, cannot vote (need at least 3)! Copied the first file from the first folder, verbatim." % (relfilepath, len(fileshandles)))

    errors = []
    entries = [1]*len(fileshandles)  # init with 0 to start the while loop
    while (entries.count('') < len(fileshandles)):
        final_entry = []
        # Read a block from all input files into memory
        for i in xrange(len(fileshandles)):
            entries[i] = fileshandles[i].read(blocksize)

        # End of file for all files, we exit
        if entries.count('') == len(fileshandles):
            break
        # Else if there's only one file, just copy the file's content over
        elif len(entries) == 1:
            final_entry = entries[0]

        # Else, do the majority vote
        else:
            # Walk along each column (imagine the strings being rows in a matrix, then we pick one column at each iteration = all characters at position i of each string), so that we can compare these characters easily
            for i in xrange(max(len(entry) for entry in entries)):
                hist = {} # kind of histogram, we just memorize how many times a character is presented at the position i in each string TODO: use collections.Counter instead of dict()?
                # Extract the character at position i of each string and compute the histogram at the same time (number of time this character appear among all strings at this position i)
                for entry in entries:
                    # Check if we are not beyond the current entry's length
                    if i < len(entry): # TODO: check this line, this should allow the vote to continue even if some files are shorter than others
                        # Extract the character and use it to contribute to the histogram
                        # TODO: add warning message when one file is not of the same size as the others
                        key = str(ord(entry[i])) # convert to the ascii value to avoid any funky problem with encoding in dict keys
                        hist[key] = hist.get(key, 0) + 1 # increment histogram for this value. If it does not exists, use 0. (essentially equivalent to hist[key] += 1 but with exception management if key did not already exists)
                # If there's only one character (it's the same accross all strings at position i), then it's an exact match, we just save the character and we can skip to the next iteration
                if len(hist) == 1:
                    final_entry.append(chr(int(hist.iterkeys().next())))
                    continue
                # Else, the character is different among different entries, we will pick the major one (mode)
                elif len(hist) > 1:
                    # Sort the dict by value (and reverse because we want the most frequent first)
                    skeys = sorted(hist, key=hist.get, reverse=True)
                    # Ambiguity! If each entries present a different character (thus the major has only an occurrence of 1), then it's too ambiguous and we just set a null byte to signal that
                    if hist[skeys[0]] == 1:
                        if default_char_null:
                            if default_char_null is True:
                                final_entry.append("\x00")
                            else:
                                final_entry.append(default_char_null)
                        else:
                            # Use the entry of the first file that is still open
                            first_char = ''
                            for entry in entries:
                                # Found the first file that has a character at this position: store it and break loop
                                if i < len(entry):
                                    first_char = entry[i]
                                    break
                            # Use this character in spite of ambiguity
                            final_entry.append(first_char)
                        errors.append(outfile.tell() + i) # Print an error indicating the characters that failed
                    # Else if there is a tie (at least two characters appear with the same frequency), then we just pick one of them
                    elif hist[skeys[0]] == hist[skeys[1]]:
                        final_entry.append(chr(int(skeys[0]))) # TODO: find a way to account for both characters. Maybe return two different strings that will both have to be tested? (eg: maybe one has a tampered hash, both will be tested and if one correction pass the hash then it's ok we found the correct one)
                    # Else we have a clear major character that appear in more entries than any other character, then we keep this one
                    else:
                        final_entry.append(chr(int(skeys[0]))) # alternative one-liner: max(hist.iteritems(), key=operator.itemgetter(1))[0]
                    continue
            # Concatenate to a string (this is faster than using a string from the start and concatenating at each iteration because Python strings are immutable so Python has to copy over the whole string, it's in O(n^2)
            final_entry = ''.join(final_entry)
            # Commit to output file
            outfile.write(final_entry)
            outfile.flush()

    # Errors signaling
    if errors:
        error_msg = "Unrecoverable corruptions (because of ambiguity) in file %s on characters: %s." % (relfilepath, [hex(int(x)) for x in errors]) # Signal to user that this file has unrecoverable corruptions (he may try to fix the bits manually or with his own script)
        return (1, error_msg) # return an error
    # Close all input files
    for fh in fileshandles:
        fh.close()
    # Close output file
    if outfile != outpath:  # close only if we were not given a file handle in the first place
        outfile.flush()
        outfile.close()
    return (0, None)