«Строка содержит NULL байт» в программе чтения CSV (Python)

86

Я пытаюсь написать программу, которая просматривает файл .CSV (input.csv) и перезаписывает только те строки, которые начинаются с определенного элемента (corrected.csv), как указано в текстовом файле (output.txt).

Вот как сейчас выглядит моя программа:

import csv

lines = []
with open('output.txt','r') as f:
    for line in f.readlines():
        lines.append(line[:-1])

with open('corrected.csv','w') as correct:
    writer = csv.writer(correct, dialect = 'excel')
    with open('input.csv', 'r') as mycsv:
        reader = csv.reader(mycsv)
        for row in reader:
            if row[0] not in lines:
                writer.writerow(row)

К сожалению, я все время получаю эту ошибку и понятия не имею, о чем она.

Traceback (most recent call last):
  File "C:\Python32\Sample Program\csvParser.py", line 12, in <module>
    for row in reader:
_csv.Error: line contains NULL byte

Благодарность всем присутствующим здесь людям даже за то, что они довели меня до этого момента.

Джеймс Роузман
источник
Просто предположение, но похоже, что ваш файл input.csv содержит пустую строку (может быть, в конце?). Попробуйте поискать этот текст исключения в файле csvParser.py.
Sam Axe
На самом деле я просто просмотрел файл input.csv и избавился от всех пустых пространств ... все равно не повезло (та же ошибка).
Джеймс Роузман
Чтобы точно определить номер строки, я предлагаю вам ввести переменную счетчика и увеличивать ее в for row in readerцикле.
codeape
Я не уверен, как я должен это делать, когда сама программа не запускается. Я попытался добавить счетчик, и ничего другого не обнаружилось, точно такая же ошибка трассировки.
Джеймс Роузман
4
Есть ли в вашем .csv байт NULL? open('input.csv').read().index('\0')даст вам смещение первого, если вы это сделаете.
ретроспективно

Ответы:

69

Я решил аналогичную проблему более простым решением:

import codecs
csvReader = csv.reader(codecs.open('file.csv', 'rU', 'utf-16'))

Ключ заключался в использовании модуля кодеков для открытия файла в кодировке UTF-16, кодировок намного больше, проверьте документацию .

К. Дэвид С.
источник
4
У меня была такая же проблема с файлом CSV, созданным из LibreOffice, который изначально был открыт из файла Excel .xls. По какой-то причине LibreOffice сохранил CSV-файл как UTF-16. Вы можете сказать, посмотрев на первые 2 байта файла, если это FF FE, то это хороший индикатор, что это UTF-16
Том Далтон
4
Обратите внимание, что если ваш файл содержит данные UTF-16, которые находятся за пределами диапазона ASCII, csv.reader() они не смогут их обработать, и UnicodeEncodeErrorвместо этого вы получите s.
Мартейн Питерс
7
Это просто привело к возникновению другой ошибки,UnicodeError: UTF-16 stream does not start with BOM
Керин
В моем случае так и было 'utf-16le'.
Paweł Szczur
70

Я предполагаю, что у вас есть байт NUL в input.csv. Вы можете проверить это с помощью

if '\0' in open('input.csv').read():
    print "you have null bytes in your input file"
else:
    print "you don't"

если да,

reader = csv.reader(x.replace('\0', '') for x in mycsv)

может помочь вам обойти это. Или это может означать, что у вас есть utf16 или что-то «интересное» в файле .csv.

втягивать
источник
5
+1 при нахождении в файле NULL байтов ... к сожалению, теперь мой файл 'corrected.csv' теперь читается на японском ...
Джеймс Роузман
Похоже, ваш .csv не в формате ascii. Я думаю, что для дальнейшей помощи потребуется немного больше информации о фактическом содержании вашего .csv. Вы пробовали открыть его в текстовом редакторе, таком как vim или блокнот? Или работает file input.csvдля определения типа файла?
ретроспективно
Я открыл его в Блокноте, он выглядит нормально. Как должен выглядеть CSV? Он читается так же, как и в Google Analytics, но с огромными вкладками между данными.
Джеймс Роузман
Блин ... есть ли способ заменить табуляторы запятыми и заставить работать с программой Python?
Джеймс Роузман
1
Если CSV ограничен вкладке необходимо указать так: reader = csv.reader(mycsv, delimiter='\t'). Я представляю, что читатель csv пожирает весь ваш файл в поисках запятых и доходит до EOF. Но у вас определенно есть проблема с кодировкой. Вам нужно указать кодировку при открытии файла.
Стивен Румбальский,
15

Если вы хотите заменить нули чем-то, вы можете сделать это:

def fix_nulls(s):
    for line in s:
        yield line.replace('\0', ' ')

r = csv.reader(fix_nulls(open(...)))
Клаудиу
источник
2
Замена null на пробел не будет хорошим выбором. У меня получилось заменить пустой строкой
Марсело Ассис
У меня вопрос о том, как вы использовали yield. Учитывая, что это цикл, означает ли это, что он по-прежнему будет читать файл построчно или сразу загрузит его в память?
пнср,
10

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

См. (line.replace('\0','') for line in f)Ниже, также вы, вероятно, захотите открыть этот файл в режиме rb.

import csv

lines = []
with open('output.txt','r') as f:
    for line in f.readlines():
        lines.append(line[:-1])

with open('corrected.csv','w') as correct:
    writer = csv.writer(correct, dialect = 'excel')
    with open('input.csv', 'rb') as mycsv:
        reader = csv.reader( (line.replace('\0','') for line in mycsv) )
        for row in reader:
            if row[0] not in lines:
                writer.writerow(row)
Woot
источник
Благодаря! Это сработало для файлов результатов выборов NC, которые действительно (!) Используют нулевой байт вместо байта «0» в одном столбце. См. Dl.ncsbe.gov/ENRS/resultsPCT20161108.zip
nealmcb 07
7

Это скажет вам, в какой строке проблема.

import csv

lines = []
with open('output.txt','r') as f:
    for line in f.readlines():
        lines.append(line[:-1])

with open('corrected.csv','w') as correct:
    writer = csv.writer(correct, dialect = 'excel')
    with open('input.csv', 'r') as mycsv:
        reader = csv.reader(mycsv)
        try:
            for i, row in enumerate(reader):
                if row[0] not in lines:
                   writer.writerow(row)
        except csv.Error:
            print('csv choked on line %s' % (i+1))
            raise

Возможно, это от daniweb будет полезно:

Я получаю эту ошибку при чтении из файла csv: «Ошибка выполнения! Строка содержит NULL байт». Есть идеи о первопричине этой ошибки?

...

Хорошо, я понял и решил опубликовать решение. Просто еще раз огорчил меня ... Использованный файл был сохранен в формате .xls вместо .csv. Не уловил этого, потому что само имя файла имело расширение .csv, а тип был еще .xls

Стивен Румбальский
источник
1
Traceback (most recent call last): File "C:\Python32\Sample Program\csvParser.py", line 17, in <module> print ('csv choked on line %s' % (i+1)) NameError: name 'i' is not defined
Джеймс Роузман
Хорошо. Потом задыхается на самой первой строчке. Запустите это и print(open('input.csv', 'r').readlines()[0])
опубликуйте,
Что-то обалденное ... но работает. ÿþ/<Это все, что он вставлял (в основном это блоки и числа)
Джеймс Роузман
1
Возможно, ваш CSV на самом деле не является CSV. Смотрите вторую половину моего ответа.
Стивен Румбальский,
О, черт возьми, это может быть полностью, как я могу это исправить? Я тоже сохранил его прямо из Google Analytics ...
Джеймс Роузман
2

Хитрый способ:

Если вы разрабатываете под Lunux, вы можете использовать все возможности sed :

from subprocess import check_call, CalledProcessError

PATH_TO_FILE = '/home/user/some/path/to/file.csv'

try:
    check_call("sed -i -e 's|\\x0||g' {}".format(PATH_TO_FILE), shell=True)
except CalledProcessError as err:
    print(err)    

Наиболее эффективное решение для больших файлов.

Проверено на Python3, Kubuntu

Серго
источник
1

Я недавно исправил эту проблему, и в моем случае это был сжатый файл, который я пытался прочитать. Сначала проверьте формат файла. Затем убедитесь, что содержимое соответствует расширению.

Дэниел Ли
источник
1

Превращение моей среды Linux в чистую, законченную среду UTF-8 помогло мне. Попробуйте в командной строке следующее:

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
Филипп Огер
источник
для меня также переход на UTF-8 решил проблему. В Windows я использовал Notepad ++, чтобы изменить формат с UTF16 на UTF8. Затем я открыл файл с помощью libreoffice calc и удалил лишние строки и т. Д.
Yuval Harpaz
1

Это давно решено, но я столкнулся с этим ответом, потому что у меня возникла неожиданная ошибка при чтении CSV для обработки в качестве обучающих данных в Keras и TensorFlow.

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

Урок: если вы видите эту ошибку, убедитесь, что ваши данные выглядят так, как вы думаете!

Дэвид Хельзер
источник
0

Все очень просто.

не создавайте CSV-файл с помощью команды «Создать новый Excel» или сохраняйте как «.csv» из окна.

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

csv, созданный самим модулем csv python, больше не будет отображать ошибку кодировки или пустую строку.

Нитиш Гупта
источник