Подтвердить что ты не робот

Ошибка CSV Python: строка содержит NULL-байт

Я работаю с некоторыми CSV файлами со следующим кодом:

reader = csv.reader(open(filepath, "rU"))
try:
    for row in reader:
        print 'Row read successfully!', row
except csv.Error, e:
    sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))

И один файл бросает эту ошибку:

file my.csv, line 1: line contains NULL byte

Что я могу сделать? Google, похоже, предположил, что это файл Excel, который был сохранен как .csv неправильно. Есть ли способ обойти эту проблему в Python?

== UPDATE ==

Следуя комментарию @JohnMachin ниже, я попытался добавить эти строки в свой script:

print repr(open(filepath, 'rb').read(200)) # dump 1st 200 bytes of file
data = open(filepath, 'rb').read()
print data.find('\x00')
print data.count('\x00')

И это результат, который я получил:

'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1\x00\x00\x00\x00\x00\x00\x00\x00\ .... <snip>
8
13834

Таким образом, файл действительно содержит NUL байты.

4b9b3361

Ответ 1

Как следует из @S.Lott, вы должны открывать свои файлы в режиме "rb", а не в режиме "rU". Однако это НЕ может быть причиной вашей текущей проблемы. Насколько я знаю, использование режима "rU" может испортить вас, если в данных встроены \r, но не вызывают никаких других драм. Я также отмечаю, что у вас есть несколько файлов (все они открыты с помощью 'rU'??), но только один из них вызывает проблему.

Если модуль csv говорит, что у вас есть "NULL" (глупое сообщение должно быть "NUL" ) байт в вашем файле, тогда вам нужно проверить, что находится в вашем файле. Я бы предположил, что вы это сделаете, даже если использование "rb" заставляет проблему уйти.

repr() является (или хочет быть) вашим отладочным другом. Он однозначно покажет то, что у вас есть, на платформе независимой моды (что полезно для помощников, которые не знают, что такое od). Сделайте это:

print repr(open('my.csv', 'rb').read(200)) # dump 1st 200 bytes of file

и аккуратно скопируйте/вставьте (не перепечатывайте) результат в редактирование вашего вопроса (не в комментарий).

Также обратите внимание, что если файл действительно неудобен, например. no\r или \n на разумном расстоянии от начала файла, номер строки, сообщенный reader.line_num, будет (бесполезно) 1. Найдите, где первый \x00 (если есть), выполнив

data = open('my.csv', 'rb').read()
print data.find('\x00')

и убедитесь, что вы сбросили, по крайней мере, столько байтов с помощью repr или od.

Что говорит data.count('\x00')? Если их много, вы можете сделать что-то вроде

for i, c in enumerate(data):
    if c == '\x00':
        print i, repr(data[i-30:i]) + ' *NUL* ' + repr(data[i+1:i+31])

чтобы вы могли видеть байты NUL в контексте.

Если вы видите \x00 в выводе (или \0 в вашем od -c выходе), то у вас определенно есть NUL-байты в файле, и вам нужно будет сделать что-то вроде этого:

fi = open('my.csv', 'rb')
data = fi.read()
fi.close()
fo = open('mynew.csv', 'wb')
fo.write(data.replace('\x00', ''))
fo.close()

Кстати, посмотрели ли вы файл (включая последние несколько строк) с помощью текстового редактора? Действительно ли он выглядит как разумный CSV файл, такой как другой (без исключений)?

Ответ 2

Чтение его как UTF-16 также было моей проблемой.

Здесь мой код, который закончился:

f=codecs.open(location,"rb","utf-16")
csvread=csv.reader(f,delimiter='\t')
csvread.next()
for row in csvread:
    print row

Где местоположение - это каталог вашего файла csv.

Ответ 3

data_initial = open("staff.csv", "rb")
data = csv.reader((line.replace('\0','') for line in data_initial), delimiter=",")

Это работает для меня.

Ответ 4

Я столкнулся с этой проблемой. Используя модуль Python csv, я пытался прочитать файл XLS, созданный в MS Excel, и запущенный в ошибке NULL byte, которую вы получали. Я огляделся и нашел xlrd Модуль Python для чтения и форматирования данных из файлов электронной таблицы MS Excel. С модулем xlrd я могу не только правильно прочитать файл, но также могу получить доступ ко многим различным частям файла так, как раньше не мог.

Я подумал, что это может вам помочь.

Ответ 5

Преобразование кодировки исходного файла из UTF-16 в UTF-8 решает мою проблему.

Как преобразовать файл в utf-8 в Python?

import codecs
BLOCKSIZE = 1048576 # or some other, desired size in bytes
with codecs.open(sourceFileName, "r", "utf-16") as sourceFile:
    with codecs.open(targetFileName, "w", "utf-8") as targetFile:
        while True:
            contents = sourceFile.read(BLOCKSIZE)
            if not contents:
                break
            targetFile.write(contents)

Ответ 6

Вы можете просто встроить генератор, чтобы отфильтровать нулевые значения, если вы хотите притвориться, что они не существуют. Конечно, это предполагает, что нулевые байты на самом деле не являются частью кодировки и действительно являются своего рода ошибочным артефактом или ошибкой.

with open(filepath, "rb") as f:
    reader = csv.reader( (line.replace('\0','') for line in f) )

    try:
        for row in reader:
            print 'Row read successfully!', row
    except csv.Error, e:
        sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))

Ответ 7

Зачем ты это делаешь?

 reader = csv.reader(open(filepath, "rU"))

Документы довольно понятны, что вы должны это сделать:

with open(filepath, "rb") as src:
    reader= csv.reader( src )

Режим должен быть "rb" для чтения.

http://docs.python.org/library/csv.html#csv.reader

Если csvfile является файловым объектом, он должен быть открыт с флагом 'b на платформах, где это имеет значение.

Ответ 9

Вместо чтения csv я использую read file и функцию split для строки:

lines = open(input_file,'rb') 

for line_all in lines:

    line=line_all.replace('\x00', '').split(";")

Ответ 10

Я получил ту же ошибку. Сохранял файл в UTF-8, и он работал.

Ответ 11

Это случилось со мной, когда я создал файл CSV с OpenOffice Calc. Это не произошло, когда я создал CSV файл в текстовом редакторе, даже если позже я его отредактировал с помощью Calc.

Я решил проблему, скопировав в текстовом редакторе данные из моего созданного Calc файла в новый файл, созданный редактором.

Ответ 12

У меня была такая же проблема, открывая CSV, созданный из веб-сервиса, который вставлял NULL-байты в пустые заголовки. Для очистки файла я сделал следующее:

with codecs.open ('my.csv', 'rb', 'utf-8') as myfile:
    data = myfile.read()
    # clean file first if dirty
    if data.count( '\x00' ):
        print 'Cleaning...'
        with codecs.open('my.csv.tmp', 'w', 'utf-8') as of:
            for line in data:
                of.write(line.replace('\x00', ''))

        shutil.move( 'my.csv.tmp', 'my.csv' )

with codecs.open ('my.csv', 'rb', 'utf-8') as myfile:
    myreader = csv.reader(myfile, delimiter=',')
    # Continue with your business logic here...

Отказ от ответственности: Имейте в виду, что это перезаписывает ваши исходные данные. Убедитесь, что у вас есть резервная копия. Вы были предупреждены!

Ответ 13

Для всех этих ненавистных читателей файловой системы rU: я просто попытался открыть файл CSV с компьютера Windows на Mac с файловым модемом "rb", и я получил эту ошибку из модуля csv:

Error: new-line character seen in unquoted field - do you need to 
open the file in universal-newline mode?

Открытие файла в режиме "rU" отлично работает. Мне нравится универсальный режим новой строки - это избавляет меня от хлопот.

Ответ 14

Я столкнулся с этим при использовании scrapy и извлечении zs файла без необходимости иметь правильное промежуточное программное обеспечение, чтобы разархивировать тело ответа перед передачей его в csvreader. Следовательно, файл не был действительно csv файлом и соответственно отклонил ошибку line contains NULL byte.

Ответ 15

Вы пытались использовать gzip.open?

with gzip.open('my.csv', 'rb') as data_file:

Я пытался открыть файл, который был сжат, но имел расширение ".csv" вместо "csv.gz". Эта ошибка продолжала появляться, пока я не использовал gzip.open

Ответ 16

В одном случае - если CSV файл содержит пустые строки, эта ошибка может появиться. Проверка строки необходима, прежде чем мы начнем писать или читать.

for row in csvreader:
        if (row):       
            do something

Я решил проблему, добавив эту проверку в код.